Jaxws 2.2

126 views
Skip to first unread message

Dan Jones

unread,
Feb 7, 2014, 10:00:07 AM2/7/14
to jsonweb...@googlegroups.com
Hi, I have pulled down versions 0.7 and 0.8 and have made some tweaks in order to get the jsonwebservice up to the 2.2 level. I'm learning a lot about it as I go along.

If I use my project with 0.8, and jaxws-rt 2.2.8, there are plenty of problems. Since the api requires new methods such as using the XMLBridge as opposed to the deprecated Bridge. 

One question I have is around the TieHandler, and how now I have the actual packet being decoded into JSON, using your MessageBodyBuilder, and it is being returned to the HttpAdapter in the handle() method. So, I now have this packet containing the JSON, and it goes to call its 

  packet = head.process(packet, con.getWebServiceContextDelegate()

                                packet.transportBackChannel);

                    } catch(Exception e) {

(And then various calling to these methods:)

com.sun.xml.ws.server.sei.SEIInvokerTube.processRequest(Packet) 
com.sun.xml.ws.db.DatabindingImpl.deserializeRequest(Packet) will call the 
com.sun.xml.ws.server.sei.TieHandler.readRequest(Message)

com.sun.xml.ws.api.message.MessageWrapper.readPayload()

com.sun.xml.ws.server.sei.EndpointArgumentsBuilder.readWrappedRequest(Message, Object[])


But, the packet (or JSONMessage) returned a "false" for its "hasPayload()". The reason why is because it is called inside here from the packet's "delegate.readPayload()"

It is called from 

  protected void readWrappedRequest(Message msg, Object[] args) throws JAXBException, XMLStreamException {

        if (!msg.hasPayload()) {

            throw new WebServiceException("No payload. Expecting payload with "+wrapperName+" element");

(BTW, the readPayload is called from inside here because JSONMessage is the delagate:)

    public XMLStreamReader readPayload() {

        try {

            return delegate.readPayload();

        } catch (XMLStreamException e) {


So, I changed that to return true, and it chokes because once it says it has a payload, it tries to read the payload as an XMLStreamReader, and the method in JSONMessage of course, returns null.



 How would you suggest converting the JSON payload to an XMLStreamReader inside of the JSONMessage com.jaxws.json.JSONMessage.readPayload()?




com.jaxws.json.codec.encode.JSONEncoder.encode(OutputStream) now returns the packet but with the message fault. It should be an actual SOAP payload that is parsed and handed off to the appropriate WS endpoint method, right?


   


  



Dan Jones

unread,
Feb 10, 2014, 3:03:27 PM2/10/14
to jsonweb...@googlegroups.com
If anyone else knows, please point me in the right direction. Gracias! 

Sundar Gmail

unread,
Feb 10, 2014, 3:44:31 PM2/10/14
to jsonweb...@googlegroups.com
Hi Dan Jones,
        From the method stack trace, I don’t see where you end with problem.  Also this library not tested directly on jaws-rt jar.  This is tested with metro web services rt jar.  I understood metro library includes jaxws rt jar. But metro also includes all dependency.

Can you please provide me more details with stack trace if any.  and your service method and sample input.  so that I can reproduce and help you with issues.


Regards
  Sundar




--
You received this message because you are subscribed to the Google Groups "jsonwebservice" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jsonwebservic...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Dan Jones

unread,
Feb 10, 2014, 4:08:05 PM2/10/14
to jsonweb...@googlegroups.com
Thank you Sundar for the reply!! 
I am going to use metro, exclusively, and then get back to you with the results.
Everything had been working fine with jsonwebservice.07 and with the older metro jars. I am in the process of upgrading everything to a newer version of web services and the errors are completely swallowed. I actually had get get into the debugger to find out exactly WHERE the errors were occurring. 

The end result was that the client was not getting back any json at all. {} to be specific. I found that a lot of the clients were actually sending POST data instead of json. The only way that I can go at this point is to use jsonwebservice.08 and find a way to make it work. 

Anyway, it will take me a while, but I will try to get back to you later on tonight (EST) and let you know more details. Thanks again for your help. 



On Friday, February 7, 2014 10:00:07 AM UTC-5, Dan Jones wrote:

Sundar Gmail

unread,
Feb 10, 2014, 4:20:10 PM2/10/14
to jsonweb...@googlegroups.com
Hi Dan Jones,
     Ok, I am interested to see what is going wrong.  Post data converted to object same like json data. So I don’t thing post data can be issue.

By the way If your issue is update issue, then it’t easier to find. You may check what is changed in 0.7 to 0.8 in svn code.


Regards
   Sundar





Dan Jones

unread,
Feb 10, 2014, 9:57:13 PM2/10/14
to jsonweb...@googlegroups.com
Ok, well, I have everything metro, 2.3 now. In order to compile the jsonwebservice, I needed to add a few new things. Like in the earlier post, I mentioned that it complained about the whole XMLBridge thing now. 
I did chnage MessageBodyBuilder in order to get things moving along, and I'm close, but here is an example of what I changed: 

if(style == Style.RPC){

WrapperComposite cs = new WrapperComposite();

//CompositeStructure cs = new CompositeStructure();

cs.values = parameterObjects;

cs.bridges = new XMLBridge[childParameters.size()];

for(ParameterImpl parameterChild : childParameters){

cs.bridges[parameterChild.getIndex()] = parameterChild.getXMLBridge();

}

obj = cs;

}else{

Class<?> type = (Class<?>)parameter.getBridge().getTypeReference().type;

obj = jsonPopulator.getNewInstance(type);

for(ParameterImpl parameterChild : childParameters){

type.getField(parameterChild.getPartName()).set(obj,

parameterObjects[parameterChild.getIndex()]);

}

}

System.err.println("\n\n\n PARAMETER GET XML BRIDGE -> " + parameter.getXMLBridge() + " obj= " + obj);

Message ret = JAXBMessage.create(parameter.getXMLBridge(), obj, this.codec.soapVersion);

System.err.println(" ret = " + ret);

return ret;

This is the part that is for the style = RPC, which is exactly what it was before. So, this is the relevant piece for me. Instead of the CompositeStructure, I changed it to WrapperComposite. This was due to some source I had been looking at inside a newer web services source that I found. I can dig up those details later if you need them.
I can step through this in the debugger and see the objects that are created. For example, the system outs will print 


 PARAMETER GET XML BRIDGE -> com.sun.xml.ws.db.glassfish.BridgeWrapper : com.sun.xml.bind.v2.runtime.BridgeImpl@719554e2 obj= com.sun.xml.ws.spi.db.WrapperComposite@79cf2f93

 ret = com.sun.xml.ws.message.jaxb.JAXBMessage@5a34252a

So the method in MessageBodyBuilder is actually returning a legit JAXBMessage. The return goes to the JSONDecoder, and the JSONDecoder's "jsonBuffer" contains the exact Json that represents the request. All is fine so far! 

The JAXBMessage is returned from the JSONDecoder, back to the JSONCodec, line 497: 


message = decoder.getWSMessage();

At the end of that decode method in JSONCodec, the message is then set to the packet and sent along the pipe. Everything seems to be going great, until it gets around to the DataBindingImpl's DeserializeRequest!! This is where it blows.

public JavaCallInfo deserializeRequest(Packet req) {

    com.sun.xml.ws.api.databinding.JavaCallInfo call = new com.sun.xml.ws.api.databinding.JavaCallInfo();

try {

    JavaMethodImpl wsdlOp = resolveJavaMethod(req);

TieHandler tie = wsdlOpMap.get(wsdlOp);

call.setMethod(tie.getMethod());

Object[] args = tie.readRequest(req.getMessage());

call.setParameters(args);

} catch (DispatchException e) {

call.setException(e);

}

return call;

}


When it calls the "tie.readRequest()" above, it gets the "req.getMessage()" and passes it into the "TieHandler"'s readRequest() method which is:

    public Object[] readRequest(Message reqMsg) {

        Object[] args = new Object[noOfArgs];

        try {

            argumentsBuilder.readRequest(reqMsg,args);

        } catch (JAXBException e) {

            throw new WebServiceException(e);

        } catch (XMLStreamException e) {

            throw new WebServiceException(e);

        }

        return args;

    }

The argumentsBuilder.readRequest() then calls EndpointArgumentsBuilder's readRequest like:

        public void readRequest(Message msg, Object[] args) throws JAXBException, XMLStreamException {

            readWrappedRequest(msg, args);

        }


and the readWrappedRequest is exactly where the problem occurs. msg.hasPayload() will call the JSONMessage's hasPayload() which I changed to return true, and then chokes on msg.readPayload() which calls the JSONMessage's readPayload(). That is where I'm sort of stuck. 


   protected void readWrappedRequest(Message msg, Object[] args) throws JAXBException, XMLStreamException {

        if (!msg.hasPayload()) {

            throw new WebServiceException("No payload. Expecting payload with "+wrapperName+" element");

        }

        XMLStreamReader reader = msg.readPayload();

        XMLStreamReaderUtil.verifyTag(reader,wrapperName);

        reader.nextTag();

        while(reader.getEventType()==XMLStreamReader.START_ELEMENT) {

            // TODO: QName has a performance issue

            QName name = reader.getName();

            WrappedPartBuilder part = wrappedParts.get(name);

            if(part==null) {

                // no corresponding part found. ignore

                XMLStreamReaderUtil.skipElement(reader);

                reader.nextTag();

            } else {

                part.readRequest(args,reader, msg.getAttachments());

            }

 

The line above:        XMLStreamReader reader = msg.readPayload(); calls JSONMessage.readPayload() which is supposed to return an XMLStreamReader. In the current code, that method returns null.

So, not sure yet how it should be handled. Maybe along the way, it took the wrong method path somehow. Before I go too far, I just wanted to confirm with you how you envisioned the result of that. 

If you remove that method from JSONMessage, there is of course a compile time error. Since now you have to supply a method for the abstract Message's readPayload. The javadoc is like

XMLStreamReader com.jaxws.json.JSONMessage.readPayload() throws XMLStreamException


@Override

Reads the payload as a XMLStreamReader This consumes the message. The caller is encouraged to call XMLStreamReaderFactory.recycle(XMLStreamReader) when finished using the instance.

Overrides: readPayload() in Message

Returns:

If there's no payload, this method returns null. Otherwise always non-null valid XMLStreamReader that points to the payload tag name.

Throws:


 

On Friday, February 7, 2014 10:00:07 AM UTC-5, Dan Jones wrote:

Dan Jones

unread,
Feb 10, 2014, 10:06:38 PM2/10/14
to jsonweb...@googlegroups.com
Clarification: When I said, "This is the part that is for the style = RPC, which is exactly what it was before"
I really meant that in my existing code, the annotations are RPC, and my existing code is the same as before!

@SOAPBinding(style = SOAPBinding.Style.RPC)

@WebService (name="core.helpthehungry.com", targetNamespace="http://core.helpthehungry.com")


On Friday, February 7, 2014 10:00:07 AM UTC-5, Dan Jones wrote:

Sundar Murthi

unread,
Feb 11, 2014, 3:58:28 PM2/11/14
to jsonweb...@googlegroups.com
Hi Dan Jones,
     thanks for details. I can reproduce the issue with test case.   In new version of metro latter 2.2.1 , all messages warped, also only xml based binding forced in codecs.  This is NOT something I like to compromise by serialising objects to xml and json.  This has performance impact in large data.

I am working on fixes with new version. I will send you new beta version of jar with fix. later today.


Regards
  Sundar


Dan Jones

unread,
Feb 11, 2014, 4:30:04 PM2/11/14
to jsonweb...@googlegroups.com
Thanks Sundar, if you need anything let me know. 
Like I said, the actual soap xml looked good in the packet, coming out of the JSONCodec.decode() method. At that point, it was all groovy. I 'thought' that perhaps if the JSONMessage could return an XMLStreamReader to that actual soap xml, all would be fine, but for some reason, it had 'lost' the xml data. (I mean it could not point back to it from wrapper to wrapper and stuff, it wasn't 'visible' inside the readPayload())

But thank you, no hurries! I'm glad that you are looking at it 

Dan Jones

unread,
Feb 11, 2014, 4:30:59 PM2/11/14
to jsonweb...@googlegroups.com

Sundar Murthi

unread,
Feb 11, 2014, 6:07:05 PM2/11/14
to jsonweb...@googlegroups.com, noster...@gmail.com
Hi  Dan Jones,
    Here is jar file.  source changes not yet in svn.  All parameter tests other than "anyType" passed. So if you used "anyType" in your xsd/wsdl you may experience problem.  Rest of them should be ok.

If you chek with this jar, and if its ok I will do some more test and make proper release of 0.9.   

Note: this is tested with metro 2.3.   If you directly use with jaxws jars, I suggest to rename this jsonwebservice-ri-0.9.jar as "1_jsonwebservice-ri-0.9.jar" 



jsonwebservice-ri-0.9.jar

Dan Jones

unread,
Feb 11, 2014, 7:03:20 PM2/11/14
to jsonweb...@googlegroups.com, noster...@gmail.com
SUCCESS!!!! Well, mostly! 
At one call, there is a NPE, but this did resolve the initial problem. I can't WAIT to see the code!! :-D 


ERROR [http-bio-8080-exec-17] (WSServletDelegate.java:181) - caught throwable

java.lang.NullPointerException

at com.oracle.webservices.api.message.BasePropertySet.containsKey(BasePropertySet.java:406)

at com.oracle.webservices.api.message.BaseDistributedPropertySet.containsKey(BaseDistributedPropertySet.java:192)

at com.jaxws.json.codec.JSONCodec.decode(JSONCodec.java:482)

at com.sun.xml.ws.transport.http.HttpAdapter.decodePacket(HttpAdapter.java:347)

at com.sun.xml.ws.transport.http.HttpAdapter.invokeAsync(HttpAdapter.java:541)

Sundar Murthi

unread,
Feb 13, 2014, 8:48:23 AM2/13/14
to jsonweb...@googlegroups.com
0.9.0 sources in svn, also new jar shared in gdrive.



Dan Jones

unread,
Feb 13, 2014, 3:21:28 PM2/13/14
to jsonweb...@googlegroups.com
Thank you! Yes, I have pulled down the code and I'm planning to check this out this afternoon. 

I'll definitely get back with you very soon! 

Dan Jones

unread,
Feb 13, 2014, 9:20:34 PM2/13/14
to jsonweb...@googlegroups.com
Ok, so I got it to work for me. 
I made 3 changes though. I'm not sure about the last one, it is a little crazy
1) In FormDecoder, around line 245, there was a slight typo: JOSN= to JSON= (I am not sure exactly what this impacts honestly, I didn't dig into that area much)

            } else if(content.startsWith("JSON=")){

2) In JSONCodec, right at the beginning of the method decode(), it is likely an Oracle bug, but the Packet.containsKey will access its "viewthis" parameter which is null for me at this point. And so, packet.get() and packet.supports() works, but there's a NPE on containsKey(). I guess that's why you had that wrapped in a try/catch before, because the type of Packet might throw that. Anywho, that was the cause of the null pointer exception that I spoke of in the earlier post

3) And the one I am least proud of (lol!) is that I had to add in a kludge to the FormDecoder. Since I'm honestly not sure what the "root" cause of the problem is, I had to add in a check here, and I'll explain why:

try {

if (jsonMap.containsKey("_")){

jsonMap.remove("_");

}

if(jsonMap.size() == 1){

The reason is that for my particular situation, the params are sent in with a trailing "&_=65636252" or whatever, so it would end up actually parsing this form post data into 2 entries in the jsonMap above. So jsonMap.size() ended up being 2, which would pass both if conditions and I ended up with the typical ""Unknown or More than one operation found. " +

"Your using form data. ""Use your parameter as 

exception. I found that it would take a query String like 
?getAppNotificationsUnreadCount.request.accessToken=aabbccddeeff1&getAppNotificationsUnreadCount.request.version=2&getAppNotificationsUnreadCount.request.fromType=User&_=1392222222228

And parse that into a jsonMap hashmap like 

Map : {getAppNotificationsUnreadCount={request={accessToken= aabbccddeeff1, fromType=User, version=2}}, _= 1392222222228}

It didn't use to do this in the older jsonwebservices, though. It is something "new". So, see how it took the last param and added to the hashmap? That ends up tricking it into thinking there are 2 operations, when really there's just the 1. 

I hope this wasn't too long-winded. I am actually really happy with the results. It's definitely working with metro jaxws 2.3, and that's cause for celebration!! Awesome work, Sundar! 

Reply all
Reply to author
Forward
0 new messages