8 Replies Latest reply on Jul 15, 2009 11:37 AM by sirocchj

    SOAPClient (SOAPUI) support for JAXB annotated POJOs

    sirocchj

      Hi,

      I am going to try and explain what I mean in the topic subject and why I am asking for it by describing briefly what I am doing in my project and what I would like seeing happening. I apologise if you feel all this is unnecessary info.

      1. I have a fairly complex XSD schema which I need to update frequently and which maps all objects that will even get onto the bus (via WS, FS or JMS at the mo). To avoid going nuts I use JAXB RI 2.1 to generate my pojos (using also some extensions, such as fluent api, collections setter, toString, etc)

      2. Using the async continuation pattern (btw thanks to Kevin Conner for pointing that out as it turn out to be VERY useful in many of my use cases) I am exposing a synchronous (w/ failover to async, more on this after) webservice to the end user ("certify customer" is the business idea) which wraps an asyncronous JMS call to a third system (black-box to me). So, if I get a valid response on the resp Q of the third party before timeout, grand, I return it to the requestor, else I return him a fault. A note on this: in async continuation pattern the service which inits the continuation needs to be mep="OneWay" but I also need to expose this as a WS and I know it WILL have a response, so in my jboss-esb.xml I set webservice="true" inXsd="my_in.xsd" outXsd="my_out.xsd" faultXsd="my_fault.xsd", I thereby fall into https://jira.jboss.org/jira/browse/JBESB-2434. So one question might be: is this JIRA going to get closed some time? :) I believe many would fall into it if they want to adopt async continuation but need also to expose webservice for it. I patched filter code as suggested by Tom Fennelly in its comment to overcome this issue for now.

      3. Up to here nothing too special, but: 3i. As responses come in, either on time or not, the ESB needs to publish them on topic AND, as there are a few systems (mainly in PHP) unable/unwilling to subscribe to JMS topic, needs to forward them via SOAP WS. 3ii. Third system might generate "certified customers" objects w/o corresponding request and these also need to be treated as in point 3i.

      I am going to skip the rest of the story for your own good :)

      Getting to the point:
      when I get these "certified customer" objects into the ESB I use Smooks to generate an object graph, using the pojos obtained in point 1 above and I set the root obj in a map (option 1 in Programmers guide). I then use SOAPClient (SOAP-UI, not WISE) to generate SOAP message and run into what I identified as three main problems:

      a. Since I have many elements in my schemas which make use of attributes, I am watching this https://jira.jboss.org/jira/browse/JBESB-2455 and hoping 4.6 gets released soon as I would rather not build SOAPUIClientService from trunk :)

      b. I believe my object graph gets traversed using OGNL expressions... Since I have in my .xsd several xs:simpleType which are extensions of xs:string (or indeed xs:int or other primitive types) and have one or more required attributes attached to them, these would be mapped into objects like normal variables by JAXB (but also if I were to do this manually).
      So, the only way I see it, but please correct me if I am getting it wrong, to get this dumb xml:

      <outerTag>
       <innerTag attr="some attr">Inner tag value</innerTag>
      </outerTag>

      using this dumb POJO
      public class InnerTag {
       private String attr;
       private String value;
       ... //getters and setters for both
      }

      is to override default toString method so to have
      public String toString() {
       return value;
      }

      right???
      If I don't, I believe I would get something like
      <outerTag>
       <innerTag attr="some attr">InnerTag@2323423{attr="some attr", value="Inner tag value"}</innerTag>
      </outerTag>

      I don't like the idea of overriding my lovely :) JAXB-generated toString method, though, as I would definetively want to use it for the sake of clarity in my log files, etc...

      c. What about <xs:choice>, minOccurs="0" and nillable="true" ?? How are these handled?? I make use of choices and minOccurs="0" and I see my element tags in the generated xml... which is something I believe should not be there to begin with. I believe someone has asked some support on this previously in this forum...

      To sum up: what about supporting in SOAPClient (SOAP-UI) and relative service the use a Map populated with a JAXB annotated object graph? I believe this could make it easier for example to determine wheter variable value in point b. above is indeed the value of the element or not and if element in point c. is null wheter it should be set as xs:nil="true" or should be removed for document tree.

      I hope I have not overlooked at something...
      Any thoughts on this?

      Kind Regards
      \j

      ------------------------------
      Julien J. P. Sirocchi
      Software Engineer - Nexse
      Via Adolfo Rava' 124
      00142 Rome
      Italy

        • 1. Re: SOAPClient (SOAPUI) support for JAXB annotated POJOs
          tfennelly

          Hi Julien.

          So to sum it up ( ;) ) it sounds like your main issue is that you're not able to generate the correct SOAP from your populated POJO (JAXB) graph after putting it through the SOAPClient?

          You have something like this?... :

          {xml-to-pojo} -> {soapclient-invoke} - wrongsoap -> {ws-endpoint}
          


          I wonder would something like this be easier to get working...

          {xml-to-pojo} -> {freemarker-template} - correctsoap -> {HttpRouter} -> {ws-endpoint}
          


          Where the FreeMarker template would be as simple as:

          <outerTag>
           <innerTag attr="${innerTag.attr}">${innerTag.value}</innerTag>
          </outerTag>
          


          We don't have a standalone FreeMarker templating action right now, but I don't think you actually need it in your case. Because you are using Smooks to perform the "xml-to-pojo" step, you could easily add in a freemarker template in that step to generate XML from the populated pojos ala:

          {xml-to-pojo-to-soap} - correctsoap -> {HttpRouter} -> {ws-endpoint}
          


          Done this way in fact, you could actually eliminate the JAXB step completely, replacing your JAXB pojo model with a Virtual Object Model.

          • 2. Re: SOAPClient (SOAPUI) support for JAXB annotated POJOs
            sirocchj

            Hi Tom!

            Thanks for your prompt reply! I won't be long this time, I swear :)
            What you have summarised is exactly my scenario:

            {smooks: xml-to-java} -> {soap-client: invoke} wrong SOAP payload -> {ws-endpoint}


            I had some knowledge already (by reading other posts and such, I mean :) ) that I could build up my soap payload manually (either by using a custom freemarker action, smooks+ freemarker to xml->java vo->soap-xml or, indeed, by merely using JAXB marshaller to get my SOAP body content, at least and use something like http://www.jboss.org/community/wiki/JAX-WSbasedWebServiceclientaction).

            But what I meant to stress out is:
            1. Imagine I have a perfectly structured JAXB-annotated object graph resulting from some unmarshalling of my input xml (incidentally in my case this is coming from a JMS gateway listener and its populated using smooks xml-to-java)
            <customer customerId="1">
             <province code="012">Rome</province>
             <expired>true</expired>
             <addressList addressId="1">
             <street>something</street>
             <city code="012091">Rome</city>
             </addressList>
             <addressList addressId="2">
             <street>something else</street>
             <city code="012091">Rome</city>
             </addressList>
            </customer>

            2. Say I need to route this info to two different WS endpoints, each one exposing a sligtly different WS that is accepting as request payload a different subset of my object graph, like, for WS1:
            <customer customerId="1">
             <expired>true</expired>
            </customer>

            and, for WS2:
            <customer customerId="1">
             <province code="012">Rome</province>
             <addressList addressId="1">
             <street>something</street>
             <city code="012091">Rome</city>
             </addressList>
             <addressList addressId="2">
             <street>something else</street>
             <city code="012091">Rome</city>
             </addressList>
            </customer>


            I can go with what you are saying and create manually (or by templating) two different SOAP payloads or, and this is why I was asking if you had any intention of supporting in SOAP-UI client a JAXB annotated object graph, I could have to simply pass the portion(s) of the object graph each WS is interested in... Furthermore, if SOAP-UI client was aware of the JAXB annotations it would know how to handle required elements/attributes, choices, defaults and whatever else is provided (which at the moment I believe it does not handle as expected, like what I was pointing out: an element is marked minOccurs="0", you don't find it in the object graph, I am expecting not to see the element in the resulting xml)!

            Hope this cleares a bit what the intention of my previous post was :)

            (btw, what's the weather like over there?? I believe sunny as usual I miss Dublin's showers a bit :) )

            • 3. Re: SOAPClient (SOAPUI) support for JAXB annotated POJOs
              tfennelly

              Hi Julien.

              I don't ever see SOAPClient supporting JAXB annotations. Maybe you should
              take a look at the WISE SOAPClient. It's based on JAX-WS (and so JAXB), so maybe it can help you.

              Re sending different SOAP payloads depending on the content of the incoming message... using the templating approach, you could define mulitple templates and put a condition on each. e.g....

              <?xml version="1.0"?>
              <smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd"
               xmlns:jb="http://www.milyn.org/xsd/smooks/javabean-1.2.xsd"
               xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd">
              
               <!--
               Capture the customer info from the incoming message into an object model...
               -->
               <jb:bean beanId="customer" ...
              
               <!--
               If the customer is expired, generate the expired outgoing SOAP...
               -->
               <ftl:freemarker applyOnElement="#document">
               <condition>customer.expired == true</condition>
               <ftl:template>/templates/expired.ftl</ftl:template>
               </ftl:freemarker>
              
               <!--
               If the customer is not expired, generate the customerreq outgoing SOAP...
               -->
               <ftl:freemarker applyOnElement="#document">
               <condition>customer.expired != true</condition>
               <ftl:template>/templates/customerreq.ftl</ftl:template>
               </ftl:freemarker>
              
              </smooks-resource-list>


              "sirocchj" wrote:
              (btw, what's the weather like over there?? I believe sunny as usual I miss Dublin's showers a bit :) )


              hehehe... weather here in Ireland sucks as usual :) It was really nice for a few weeks back in June, but has turn crap now again. What I wouldn't give for a holiday in Rome :)

              • 4. Re: SOAPClient (SOAPUI) support for JAXB annotated POJOs
                sirocchj

                Oh well here is about 35 degrees in Rome at the moment so I guess it is not exactly pleasant... want to switch??? :)))

                Uhm... regarding what you have just said:
                I might decide to investigate a bit more into getting wise working for me as expected, I guess I have been lazy not sorting out the classloader issues I've experienced... or just revert into doing something like what you were suggesting earlier

                btw I don't need to do (at the mo) cbrouting, I need to split to a configurable number of JMS unaware clients each a different portion of my original xml payload... that's it, I've said it!! :)

                • 5. Re: SOAPClient (SOAPUI) support for JAXB annotated POJOs
                  tfennelly

                  Ah... sorry... you need to *split* the message!!

                  OK... you can do this easily enough in 4.5 and 4.6 (soon to be released). There's an example nearly exactly like this in the SVN trunk called "transform_XML2XML_stream" (for 4.6), where a message is split and the fragments are routed to another service (over JMS or other... that's transparent) "smooks". It could easily be adapted to split to multiple endpoints by simply adding multiple <esbr:routeBean> entries with conditions on them.

                  • 6. Re: SOAPClient (SOAPUI) support for JAXB annotated POJOs
                    tfennelly

                    BTW.... this is still CBR in my way way of thinking :)

                    • 7. Re: SOAPClient (SOAPUI) support for JAXB annotated POJOs
                      sirocchj

                      I guess I'll dig down into that path to see what I can come up with
                      Tom, thanks a lot for your help & patience :)

                      • 8. Re: SOAPClient (SOAPUI) support for JAXB annotated POJOs
                        sirocchj

                        btw I agree :) it is CBR after all :)