Append to file

I am trying to process an inbound large document through the integration server v4.6, using trading networks threshhold limit. When I process the document I read it from the temp space created by trading networks and using the node iterator read it from disk. But I am running into a problem when I am writing to my pipeline out. It is filling up memory. So I think I need to also write this large document to disk as an append to disk instead of an append to record list. Does anyone know of a service to do this within 4.6? Any help at all would be greatly appreciated.

Thanks,
Marie

There are no built in file writing services. But there are some samples in the 4.6 WmSamples package under sample.IO.utils.fileWriter.

Theo

I have a similar problem. I copied the fileWriter routines from WmSamples to our project package. These routines work fine from within the WmSamples package, but they won’t even compile from our project package, where the openFileWriter generates error message complaining that the routine util.Log.log is undefined. All the filewriter packages import only java.io.*. I can’t figure out where util.Log.log is defined and what I have to do to get this statement to work from within another package. Any ideas?

Mike, you need to copy the Log class files from the WmSamples package into your package.

Off the top of my head, you should be looking in the folder [Integration Server Home]/packages/WmSamples/code for the folders “classes” and “java”. Copy the Log class file and source code from those directories and put in into the same place in your package (i.e. [Integration Server Home]/packages/Your Package/code/…).

That will solve your problem of not being able to locate the util.Log.log stuff. Hopefully, I gave you the proper folders in which to find the Log class files.

Good luck and let me know if you still have issues.

Hi Dan,

Thanks for the super-fast response. I’m working in a SAP Business Connector environment, so the Log code and classes resided in /sapbc46/Server/packages/WmSamples/code/classes/util and /sapbc46/Server/packages/WmSamples/code/source/util. Since I had already created a util folder in my package, I moved all the test code out of it into a new folder that I called utilities, deleted the util folder and recreated it. I then copied Log.class and Log.java into the appropriate subdirectories.

Those steps eliminated the util.Log.log messages, but now when I try to compile services in the utilities folder I created, they are unable to recognize the BufferedWriter object. What do I have to do to fix that? Also, where is the original souce code that created the Log class? Is that documented anywhere?

I very much appreciate your help.

– Mike

Just checking – have you imported java.io.BufferedWriter using the “Shared” tab?

Hi Dan,

Thanks again for your quick response. You’re right. I was a numbskull. I added java.io.* and of course the Buffered Writer problem disappeared.

Now the util.Log.log statements all blow up with error message "No variable Log defined in class DEVCLNT400.util. The compiler apparently recognizes the method but expects a fileWriter parameter to be available to it. Is there another step that I need to add to open the log file that util.Log.log writes to? Is this whole process documented anywhere? Where is the code that created the util.Log.log service?

– Mike

Hi Mike,

Please ensure that the Log class is in the same location as ur utility package for eg: package/Urutilitypackage/code/classes/util/log.class

Insert java.io.* in the shared tab. It should compile and work without any problem.

U can use a Java decompiler to look into Log.class implementation. U will see that util.Log.log is a method which invokes pub.flow.debugLog flow service. This service automatically appends all the logs in the Server Log which can be viewed using the BC Administrator.

You’re not picking up util.Log. Rather, you’re picking up a different class named DEVCLNT400.util and the compiler thinks you’re trying to dereference a public variable within it named Log. I assume you’re importing DEVCLNT400.* or something along those lines.

Did you move Log.java and Log.class to another directory (utilities)? If so, that’s likely to be a problem.

I can only assume that util.Log was not written as a Java service (note that it doesn’t have the usual “decorations” added such as “B2B-START-IMPORTS” and such). So you get to mess with as though it is an “external” third-party class.

You don’t have to open the log file. The class uses built-in services to write to the server logs.

I took Manohar’s advice and decompiled the Log.class file from wmSamples. I then stripped the import statements from it and wrote it to the shared tab of my own util folder. The java statement util.Log.log(“Some text…”); works fine when I call it from a test service in another folder. When I use the same statement in another service in the util folder, though, I get the error message:

/sapbc46/Server/packages/ZTest/code/source/DEVCLNT400/util.java:378: Can’t make a static reference to inner class DEVCLNT400.util. Log.
util.Log.log(“Aborting process”);
^
I also tried taking out the “util.” and using Log.log(“Aborting process”); to no avail. What do I have to do to make this work?

– Mike

The source code I inserted into the shared source tab is:

public class Log
{
public Log()
{
}

public final void log(String s) 
    throws ServiceException 
{ 
    log(s, null, null); 
} 

public final void log(String s, String s1) 
    throws ServiceException 
{ 
    log(s, s1, null); 
} 

public final void log(String s, String s1, String s2) 
    throws ServiceException 
{ 
    Values values = new Values(); 
    if(s != null) 
        values.put("message", s); 
    if(s1 != null) 
        values.put("function", s1); 
    if(s2 != null) 
        values.put("level", s2); 
    try 
    { 
        Service.doInvoke("pub.flow", "debugLog", values); 
    } 
    catch(Exception exception) 
    { 
        throw new ServiceException(exception.getMessage()); 
    } 
} 

}

– Mike

Mike, if you have the Log.java source code (packages/WmSamples/code/source/util/Log.java), copy it into your desired package in the same location.

You should then be able to reference the Log class methods as util.Log.log.

Maybe you should try creating a Java service which accepts String inputs and uses them as inputs for the Log methods. That will simply your interface from other packages.

Good luck.

Thanks, Dan. I had already tried copying the class and java files to the corresponding util directories in my package. I then got the message “No variable Log defined in class DEVCLNT400.util.” I had renamed them to .save filenames when I started working on the shared source idea so I could test the shared source without fear of conflict. I just renamed them back and commented out all the shared source code and then got the message above.

If I create a Java service as you suggested, have I really gained anything? debugLog itself is a Java service which accepts string input. Wouldn’t I have to call my own service the same way from within another Java service? Perhaps I misunderstood what you meant.

Would it be possible to get the guy(s) who wrote the sample io services to explain how one replicates util.Log.log in a custom package? It seems to me that it ought to be simpler and more tranparent than this. Overall, I think they did a great job, but it does’t make sense to me to provide a sample that one can’t more easily use in a production environment.

Regardless, I once again very much appreciate your help.

– Mike

Following up on Rob’s suggestion above, I just found Log.class, util$Log.class and util.class in …/packages/ZTest/code/classes/DEVCLNT400. As soon as I can get write permission on that directory, I’ll play around with those a bit to see if I’ve created an inadvertent conflict.

Using util.Log.log will not work. The methods are not static. And judging from the call, util.Log.log, no instance has been created.

My guess is that the calls from outside the util folder are picking up a util.Log class from somewhere else. The full class name of the thing you’re trying to do is DEVCLNT400.util, with Log as an inner class with the full name DEVCLNT400.util.Log

Try this on your shared tab:

 
public static final void log(String s) throws ServiceException  
{  
    log(s, null, null);  
}  
 
public static final void log(String s, String s1) throws ServiceException  
{  
    log(s, s1, null);  
}  
 
public static final void log(String s, String s1, String s2) throws ServiceException  
{  
    Values values = new Values();  
    if(s != null)  
        values.put("message", s);  
    if(s1 != null)  
        values.put("function", s1);  
    if(s2 != null)  
        values.put("level", s2);  
    try  
    {  
        Service.doInvoke("pub.flow", "debugLog", values);  
    }  
    catch(Exception exception)  
    {  
        throw new ServiceException(exception.getMessage());  
    }  
}

Note the elimination of the Log class and making all the methods static. These methods will become part of the DEVCLNT400.util class (if I understand your folder hierarchy correctly). You can call them within the util folder using util.log(“your text”); From outside the util folder, use DEVCLNT400.util.log(“your text”);

Well, I’m a little distressed at having to wait almost 60 seconds for your reply , so I guess I’ll just have to be satisfied with the fact that IT WORKS! You guys are unbelievable. I can’t thank you enough for the wonderful support you’ve provided me.