IBM webMethods Hybrid Integration

IBM webMethods Hybrid Integration

Join this online group to communicate across IBM product users and experts by sharing advice and best practices with peers and staying up to date regarding product enhancements.

 View Only
Expand all | Collapse all

Can 'getLastError' return objects in its 'pipeline' output?

  • 1.  Can 'getLastError' return objects in its 'pipeline' output?

    Posted Tue April 19, 2022 10:25 PM

    I use IS 10.1 to control a telnet session, using functionality from the Apache Commons TelnetClient library. The approach I use is to write Java wrapper services for key telnet actions (connect, read, write, disconnect etc). I then call the Java telnet services from Flow code. The initial call to the connect service returns a org.apache.commons.net.telnet.TelnetClient object. I pass this object to other Java services (read, write, disconnect) via Flow code. On the whole, this approach works pretty well.

    But this approach fails in the catch block. There, I call pub.flow:getLastError and try to obtain the telnet session object from lastError/pipeline. This is so I can attempt a telnet disconnection when an exception occurs. But in the catch block, the telnet session retrieved is no longer an object - it’s a string! This causes the disconnect Java service to throw a ClassCastException at ‘>>>’ in Java code below.

    Flow Service

    Java ‘disconnect’ Service

    import org.apache.commons.net.telnet.TelnetClient;
    ...
    public static final void disconnect(IData pipeline) throws ServiceException {
    // pipeline
    IDataCursor pipelineCursor = pipeline.getCursor();
    >>>		TelnetClient telnetSession = (TelnetClient) IDataUtil.get(pipelineCursor, "telnetSession"); <<< 
    try {
    // Disconnect telnet session
    telnetSession.disconnect();
    } catch (Exception e) 
    

    Java Exception

    java.lang.ClassCastException: java.lang.String cannot be cast to org.apache.commons.net.telnet.TelnetClient
    at CECommon.utils.telnet.disconnect(telnet.java:114)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    ...
    

    The problem seems to lie with pub.flow:getLastError mapping a string - not an object - into telnetSession in the mapping below.
    image

    In the ‘Try’ block, the Java disconnect service works fine with the telnetSession object.

    Any thoughts how I can obtain the telnet session object in the ‘Catch’ block as an object, not a string?

    Update: just saw this old post where Rupinder Singh and others seem to have stumbled across the same problem. But that was 2002! Is the behavior still the same two decades on?


    #Flow-and-Java-services
    #webMethods
    #Integration-Server-and-ESB


  • 2.  RE: Can 'getLastError' return objects in its 'pipeline' output?

    Posted Wed April 20, 2022 02:22 AM

    Hi @Sonam_Chauhan ,

    I quickly tried this scenario and I did get the expected object type from the getLastError and its pipeline. Seems like something is a miss, maybe if you can attach the package you are using, will give it a try and update if anything needs to be changed.

    Thanks,
    Sree


    #webMethods
    #Flow-and-Java-services
    #Integration-Server-and-ESB


  • 3.  RE: Can 'getLastError' return objects in its 'pipeline' output?

    Posted Thu April 21, 2022 03:24 AM

    Thanks @Sreekanth_Siddapur_Channakeshava. I repeated my test and something is definitely amiss. Let me try obtaining a simple replication package I can share.

    Note, I am using a different Try/Catch structure than what @Nagendra_Prasad mentions below.


    #Integration-Server-and-ESB
    #Flow-and-Java-services
    #webMethods


  • 4.  RE: Can 'getLastError' return objects in its 'pipeline' output?

    Posted Wed April 20, 2022 07:48 AM

    Hi @Sonam_Chauhan
    I’m assuming that you have implemented the TRY CATCH in the following way

    SEQUENCE ( Exit on failure) 
    SEQUENCE(Exit on success) - TRY
    SEQUENCE ( Exit on Done) - CATCH
    pub.flow:getLastError()
    

    As long you have the TelnetClient object initialized before entering the first SEQUENCE ( Exit on failure), the call to getLastError should have the TelnetClient as an object and not a string.
    As Sree requested , please provide more details about your flow .

    Additionally , starting 10.3 , there are flow steps TRY CATCH and FINALLY , which can be used to emulate a Try Catch blocks directly , Please refer guide here- TRY CATCH FINALLY in 10.3

    -NP


    #Integration-Server-and-ESB
    #Flow-and-Java-services
    #webMethods


  • 5.  RE: Can 'getLastError' return objects in its 'pipeline' output?

    Posted Thu April 21, 2022 03:40 AM

    Thanks @Nagendra_Prasad. No – I am using a very different Try/Catch construct. Here’s what I do:

    Try/Catch:	EXIT on SUCCESS
    Try: 	EXIT on FAILURE
    ...
    <Create TelnetClient Java object>
    ...
    Catch: 	EXIT on DONE
    <Invoke getLastError>
    <Access TelnetClient Java object in /lastError/pipeline>
    

    How does your Try/Catch construct work? Since your ‘TRY’ is EXIT on success, won’t it return after the first successful step?

    In my code, getLastError’s lastError/pipeline does not properly return a custom Java object instantiated within the ‘Try’ block. Strings and other IData-based structures appear fine though. It’s just the custom Java object that turns into a string.

    I’ll try to publish a simple replication testcase.

    Good to see SAG making headway with a native TRY/CATCH/FINALLY in 10.3. It should help avoid bugs. Maybe one day I’ll also see some simple resolution of the infamous tranformers cannot loop over list elements error :slight_smile:


    #webMethods
    #Integration-Server-and-ESB
    #Flow-and-Java-services


  • 6.  RE: Can 'getLastError' return objects in its 'pipeline' output?

    Posted Thu April 21, 2022 04:57 AM

    Thanks, @Sonam_Chauhan , will wait for the test package to check it and provide you with some inputs.

    Regards,
    Sree


    #Flow-and-Java-services
    #Integration-Server-and-ESB
    #webMethods


  • 7.  RE: Can 'getLastError' return objects in its 'pipeline' output?

    Posted Thu April 21, 2022 08:22 AM

    For the sake of a simple repro , Prior to entering the outer SEQUENCE(TRY/CATCH), I created a simple Date object,
    I had the first step in the TRY SEQUENCE fail(by means of a divideInts invocation ) , to check if there can be a Object in the get Last Error of the CATCH SEQUENCE.
    In your case , I see that you have a custom Java object instantiated within the ‘Try’ block, That could be the difference, You could try having a reference to your Telnetclient object outside the TRY and see if it is retained as an object. (not a recommendation , just wondering if that could be the difference).

    -NP


    #webMethods
    #Integration-Server-and-ESB
    #Flow-and-Java-services


  • 8.  RE: Can 'getLastError' return objects in its 'pipeline' output?

    Posted Thu April 21, 2022 10:37 PM

    Thanks for the suggestion @Nagendra_Prasad - I tried it and it makes no difference. There’s still a ClassCastException thrown when attempting to use the lastError/pipeline/telnetSession object.

    When I implement your suggestion, I get two pipeline variables at runtime: a ‘top-level’ telnetSession variable, and the variable in the lastError/pipeline. Both should refer to the same object.

    Interestingly, both variables are displayed as strings in the debugger at runtime - not objects. But the ‘top-level’ variable is really an object (I know since it can be used to successfully disconnect the session). The variable in lastError/pipeline is a string - using it to disconnect the session throws the ClassCastException.

    Top-level telnetSession object:
    image

    Same telnetSession object under lastError/pipeline:


    #webMethods
    #Flow-and-Java-services
    #Integration-Server-and-ESB


  • 9.  RE: Can 'getLastError' return objects in its 'pipeline' output?

    Posted Fri April 22, 2022 12:16 PM

    Not sure if this is helpful, but we’ve found that the new TRY/CATCH steps differ sufficiently in behavior from the traditional use of nested SEQUENCE that we now avoid TRY/CATCH. This is not to say no one should ever use TRY/CATCH but to advise that one will need to learn the nuances of TRY/CATCH behavior and should not assume those behave the same as the SEQUENCE approach.

    That said, I would offer that the (very Java-like) behavior of TRY/CATCH/FINALLY is likely something that many do not need. Being able to segregate different exception types and such has been, IME, relatively rare. The coarse-grained nature of “any exception” has been largely sufficient for us.


    #webMethods
    #Flow-and-Java-services
    #Integration-Server-and-ESB


  • 10.  RE: Can 'getLastError' return objects in its 'pipeline' output?

    Posted Thu April 21, 2022 10:40 PM

    I’m seeking approval for releasing the replication code here. In the meantime, I’ve opened a ticket with SAG. I plan to update how this goes


    #Integration-Server-and-ESB
    #Flow-and-Java-services
    #webMethods


  • 11.  RE: Can 'getLastError' return objects in its 'pipeline' output?

    Posted Fri April 22, 2022 03:26 AM

    Very interesting that you are seeing two variables and that both are strings, support ticket seems like the right way to go, I’m assuming you already have the latest fixes. And if you have newer versions, maybe you can give this a try in the new versions.

    -NP


    #Integration-Server-and-ESB
    #webMethods
    #Flow-and-Java-services


  • 12.  RE: Can 'getLastError' return objects in its 'pipeline' output?

    Posted Fri April 22, 2022 09:11 AM

    Haha. No, we do not have the latest fixes, though we are pretty current. The last time we updated a core fix, it broke an obscure adapter. :smiley: … so we have to be careful with patching.

    I intend to update outcome of the support ticket here. I have a feeling the workaround may be to do object initialisation earlier - before the try block.


    #webMethods
    #Integration-Server-and-ESB
    #Flow-and-Java-services


  • 13.  RE: Can 'getLastError' return objects in its 'pipeline' output?

    Posted Thu April 28, 2022 01:34 AM

    @reamon - Thanks as always! I haven’t used the new TRY/CATCH yet and will keep your advice in mind.

    @Nagendra_Prasad , @Sreekanth_Siddapur_Channakeshava - I’ve attached a replication package. The service CEExceptionTest:test replicates the problem. You point the service to a host running a telnet service on port 23, then get the following output:
    image

    Note, the package includes Apache Commons TelnetClient library functionality via this JAR file in the package’s ‘code/jars’ folder:
    CECommon/code/jars/commons-net-3.8.0.jar

    SAG are still investigating the SI.

    CEExceptionTest.zip (303.7 KB)


    #Integration-Server-and-ESB
    #Flow-and-Java-services
    #webMethods


  • 14.  RE: Can 'getLastError' return objects in its 'pipeline' output?

    Posted Mon May 02, 2022 12:57 AM

    Thanks, @Sonam_Chauhan - If you have already raised an SI and is under investigation then we could wait I guess :slight_smile:

    Regards,
    sree


    #Integration-Server-and-ESB
    #Flow-and-Java-services
    #webMethods


  • 15.  RE: Can 'getLastError' return objects in its 'pipeline' output?

    Posted Mon May 02, 2022 07:10 PM

    Yes of course. The support person helping me reached out internally - I plan to update here when a better picture forms.


    #Integration-Server-and-ESB
    #webMethods
    #Flow-and-Java-services


  • 16.  RE: Can 'getLastError' return objects in its 'pipeline' output?

    Posted Fri May 20, 2022 01:29 AM

    webMethods support came back today:

    “The problem is that the Object in this case is not Serializable, and only serializable objects are retained. From RnD, it is not a new issue and this limitation must have been there for a long time.”

    I’ve asked them to add this to documentation on pub.flow:getLastError.

    The object in question is an instance of TelnetClient (org.apache.commons.net.telnet.TelnetClient) from the Apache Commons library. Like other socket-based classes, this doesn’t implement serializable. But that means means network sockets that have long timeouts set stay connected at the OS/network level (at least that’s what I recall from testing).


    #Flow-and-Java-services
    #webMethods
    #Integration-Server-and-ESB


  • 17.  RE: Can 'getLastError' return objects in its 'pipeline' output?

    Posted Fri May 20, 2022 03:37 AM

    You should establish the connection before the try/catch body, that way the connection will still be in the pipeline and you will be able to disconnect. This was the same issue with java until they reinvented the try/catch to include an init step.

    If you want to trap connection errors then you will need two try/catch’s. One that wraps the connection and an embedded one for the processing.

    regards,
    John.


    #Flow-and-Java-services
    #webMethods
    #Integration-Server-and-ESB


  • 18.  RE: Can 'getLastError' return objects in its 'pipeline' output?

    Posted Tue May 24, 2022 11:42 PM

    Thanks @John_Carter4 that’s exactly what I did, using a two-step try/catch:

    Try (OUTER)
    ---
    Connect
    Try (INNER)
    Use connection
    End connection
    Catch (INNER)
    End connection (if it exists)
    ---
    Catch (OUTER)
    Throw exception for retry to UM
    
    

    The OUTER Try/Catch is actually a trigger processing service (hence the throwExceptionForRetry). The INNER Try/Catch is a different service (indicated by the ‘—’).

    This is similar to the solution Rupinder Singh and others noted in this old post . Thanks a lot for pointing me again in the right direction.

    Interesting! Do you think this issue (not being able to access non-serializable ‘Try’ objects in ‘Catch’) is a limitation of pub.flow:getLastError, or a more generic Java limitation? Any thoughts?

    The issue workaround is great, but obviously not ideal for code clarity.


    #Integration-Server-and-ESB
    #webMethods
    #Flow-and-Java-services


  • 19.  RE: Can 'getLastError' return objects in its 'pipeline' output?

    Posted Wed May 25, 2022 03:23 AM

    This is an issue related to the pipeline. The lastError object is a copy of the pipeline as of when the error triggered and not simply a reference to the current pipeline, otherwise it would be just the same as the current pipeline post sequence. Unfortunately, it is this copying that breaks as we are reliant on the objects being serialisable which is often not the case. That’s why I never rely on the pipeline embedded in the getLastError other than for logging purposes.
    regards,
    John.


    #webMethods
    #Integration-Server-and-ESB
    #Flow-and-Java-services


  • 20.  RE: Can 'getLastError' return objects in its 'pipeline' output?

    Posted Wed May 25, 2022 03:44 AM


  • 21.  RE: Can 'getLastError' return objects in its 'pipeline' output?

    Posted Thu June 23, 2022 07:59 PM

    Thanks again @John_Carter4, SAG plans to update documentation with the workaround you provided.

    “we will update the webMethods IS Build in services reference document and the webMethods Service Development Helps from version 10.1 until the latest. In webMethods IS Build in services reference document, we will update the usage note for pub.flow:getLastError build-in service, while for the webMethods Service Development Helps, we will add and update the section for TRY CATCH.”

    Maybe in future R&D can force serialization to elements declared in Flow Try block:

    …Or use the Java ‘Try-with-resources’ method that exploits the AutoCloseable interface:


    #webMethods
    #Integration-Server-and-ESB
    #Flow-and-Java-services


  • 22.  RE: Can 'getLastError' return objects in its 'pipeline' output?

    Posted Fri June 24, 2022 11:56 AM

    The try-with-resources concept could be useful in FLOW. Indeed, I just had a use for something like that where it needs to make sure to close a file after opening and reading via stream (using flat file services).

    That said, I always worry when FLOW starts adopting Java-like constructs. (With apologies to Dennis Miller…) Not to go off on a rant here, when I first saw the new try/catch/finally structures I was intrigued. But after digging into the details and seeing how it is trying its best to mimic try/catch/finally of Java I was less enthused. Then when we found that the handling of the pipeline differed significantly I was dismayed. As noted in my earlier post, the try/catch/finally can be useful if one understands the specifics. But it is not a direct drop-in replacement for the nested sequence approach (which definitely has its own limitations).

    Since the beginning of Integration Server (even when it was B2B Server) there has been tension between coding with FLOW vs Java. There have been multiple discussions about when to use each. Those will continue, I’m sure. :slight_smile: My position has always been, if you want to write primarily Java code, use a different tool. Integration Server is not a Java development environment. IMO, part of the reason for its success and longevity is specifically because it is not a Java development environment. It’s primary language is FLOW.

    Striking the balance between adding useful FLOW features but avoiding being “too much like” Java is a challenge. IMO, the try/catch/finally went too far. (And the unit test framework based upon JUnit went off the rails but that’s another topc.:slight_smile: )

    Regarding the “force serialization” aspect, instead of trying to force serialization of objects that likely have good reasons for not being serializable, perhaps the focus could be on not copying the pipeline. I clearly don’t know anything about how the pipeline(s) are managed under the covers, but perhaps there is a way to keep vars in the try block as accessible/functional in the lastError/pipeline.


    #Flow-and-Java-services
    #webMethods
    #Integration-Server-and-ESB