TRY-CATCH, TRY-FINALLY, CATCH and FINALLY have been introduced with 10.5.
The others already existed in previous versions.
REPEAT is used when there is a (fixed, but configurable via variables) maximum of interations known and a delay might be needed between iterations.
LOOP is used to process a list of data regardless of size.
SEQUENCE is used to group steps together, i.e. in combination with BRANCH, when each branch contains more than one step.
MAP is used for mapping (and transfroming) data from one structure to another.
INVOKE is used to directly cal another service regadless of type.
See Working with Designer Guide and Service Development Help Guide for details.
The least used is probably REPEAT. As Holger notes, used for a fixed number of iterations. We use it mainly for auto-retry in the face of transient errors.
The TRY-CATCHā¦ constructs are new. They are a welcome change to the nested SEQUENCE approach that is still very common. The main downside to the nested SEQUENCES was that getLastError supported only exceptions of a specific type. CATCH is more consistent.
One guideline here ā use TRY-CATCH only for top-level services. In other services (e.g. services such as those in WmPublic ā used by many other services) use TRY-CATCH only to if the service needs to close a resource of some sort. E.g. file, SFTP connection, etc. This is relatively rare.
Log4J should already part of the environment. Review your About page for IS and you should see it.
Iām going to sound like a broken record here ā avoid doing things as though IS is a Java app server.
We went down the path years ago of incorporating Log4J. We ended up abandoning it. Ended up not being needed. (Side note: I recall long ago when Log4J first became available and how easy it was to use. Like many things in our industry, it grew into an over-engineered monstrosity. And multiple logging frameworks evolved into nonsense like SLF4J to abstract all the logging abstractions. Ugh.)
My advice ā donāt add log4j to your environment. You likely do not need it. Things we still do:
Rely on audit logging of the top-level services and use pub.prt.log:logActivityMessages within services whenever we want to log something, primarily IDs of the documents being processed. Then we use MWS to review/search the audit logs to find activity. Mainly āwhat happened to XYZ.ā This is our primary technique. Refer to the wM docs describing the audit log facility.
Solution-specific logging. We have a couple of utility services implemented on top of Integration Server logging components. One is a (Java service) wrapper for com.wm.app.b2b.server.ServerAPI.getLogStream. This is what IS uses internally to write and rotate stats.log.Then we have another Java service to call to write data to the log. Provides an easy way to create log that auto-rotates at midnight. We donāt use this much.
IMO, log4j/logback is unnecessary in wM IS. Learn about audit logging instead.
I accomplished half way with LOG4J2, I can see info on console but its not writing to the files or even creating the file/folder. I went through hell to figure out the configuration part but still half way to go. The only level is working is INFO. DEBUG nope. I accomplished the half way approach using External Jar way.
Regarding ServerAPI.getLogStream, I saw in some post you mention that.
Is this can be inside Java service or can it invoke in flow service?
One can only invoke Java object methods using Java services. To use such components FLOW you would write āwrapperā services to expose them via the IS service construct. Here are the 2 Java services that wrap the methods of interest.
// Wrapper service for com.wm.app.b2b.server.ServerAPI.getLogStream.
// This is what IS uses internally to write and rotate stats.log.
// Opens a log file in the server's default logs directory.
// This should only be used to obtain handles to new log files for
// solution-specific logging purposes. By convention, the name should
// be something like "myapp.log".
// The returned stream is intended to kept open for the life of the
// JVM (don't open a whole bunch of these).
// This service maintains a hash table of log streams that have
// been opened keyed by the logfile parameter. If the log has
// been previously opened, the existing stream is returned and
// the "newLog" is set to "false". If the log is opened for the
// first time a new stream is returned and the output parameter
// "newLog" is set to "true".
// The closeLogStream service can be used to force a stream closed
// but this shouldn't normally be needed (intended to aid
// development and testing).
public static final void getLogStream(IData pipeline) throws ServiceException {
IDataCursor idc = pipeline.getCursor();
String logfile = IDataUtil.getString(idc, "logfile");
boolean newLog = false;
com.wm.app.b2b.server.LogOutputStream os =
(com.wm.app.b2b.server.LogOutputStream)openLogFiles.get(logfile); // get existing stream for this filename, if present
if(os == null)
{
os = com.wm.app.b2b.server.ServerAPI.getLogStream(logfile);
openLogFiles.put(logfile, os); // keep track of this stream for future use
newLog = true;
}
IDataUtil.put(idc, "logStream", os);
IDataUtil.put(idc, "newLog", (newLog+""));
idc.destroy();
}
// Writes the specified message to the specified stream.
// When writing to the stream, the current date and time
// are written first, followed by the message, and terminated
// by the line.separator string from the system properties.
public static final void writeLogStream(IData pipeline) throws ServiceException {
IDataCursor idc = pipeline.getCursor();
com.wm.app.b2b.server.LogOutputStream os =
(com.wm.app.b2b.server.LogOutputStream)IDataUtil.get(idc, "logStream");
String message = IDataUtil.getString(idc, "message");
idc.destroy();
os.write(message);
}
// Closes the stream associated with the specified
// logfile and removes the logfile from the list
// of open files. This isn't intended for normal
// operation and is provided primarily to help
// with development/testing of these log services.
public static final void closeLogStream(IData pipeline) throws ServiceException {
IDataCursor idc = pipeline.getCursor();
String logfile = IDataUtil.getString(idc, "logfile");
idc.destroy();
com.wm.app.b2b.server.LogOutputStream os =
(com.wm.app.b2b.server.LogOutputStream)openLogFiles.get(logfile);
if(os != null)
{
openLogFiles.remove(logfile); // stop tracking this one
os.close();
}
}
// --- <<IS-BEGIN-SHARED-SOURCE-AREA>> ---
private static final java.util.Hashtable openLogFiles = new java.util.Hashtable();
// --- <<IS-END-SHARED-SOURCE-AREA>> ---
Note that these 3 services are using com.wm.app.b2b.server.LogOutputStream, a class provided by wM IS. You may notice the class name as com.wm.app.b2b.server ā you may know that the original name of wM Integration Server was wM B2B Server. Thatās why the class has that name.
With the above, you can have a FLOW service anywhere that calls āgetLogStreamā service first, passing a filename. Then pass the returned logStream variable and a string message to āwriteLogStreamā to write to that log file. The class used will take care the formatting of the entry and the automatic file rotation. Assuming youāve started with a āpublic packageā of your own, much like WmPublic provides general-purpose services, you can put these in your package and use them wherever desired.
Unfortunately Reamon team wants to go with either LOG4J2 or LOGBACK. Since flexibility is a bit tight on this. I have to somehow make this work. Like I mention I was half and half with extrenal Jar and in built Log4J2. I tried all day yesterday but it wouldnt write to the file. Not sure what exactly I am missing. More to come on that. Stay Tune