You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cxf.apache.org by Dennis Sosnoski <dm...@sosnoski.com> on 2010/04/30 02:00:32 UTC

JiBX databinding implementation

I'm curious how the JiBX databinding GSoC project is progressing... 
anything to discuss yet?

JiBX is pretty flexible in how it reads and writes XML, with its own 
org.jibx.runtime.IXMLReader and IXMLWriter interfaces used to decouple 
from the details of the parser and writer. Implementations of these 
interfaces are supplied for working with StAX XMLStreamReader and 
XMLStreamWriter, and the existing Axis2 support for JiBX should be a 
good guide for fitting the actual runtime hooks together.

Just to make sure I understand how this works, JAX-WS configuration can 
be used with any type of org.apache.cxf.databinding.DataBinding 
implementation, right? So someone wanting to use JiBX with a JAX-WS 
frontend would just need to specify this using their preferred 
configuration technique (such as cxf-client.xml on the client side).

Thanks,

  - Dennis

Re: JiBX databinding implementation

Posted by Nilupa Bandara <ni...@gmail.com>.
Hi,

Thank you very much for this detailed reply. I've taken your points and will
update this mailing thread about the progress I've made and any issues I've
come across soon.

Thanks,
Nilupa

On Sat, May 29, 2010 at 5:26 AM, Dennis Sosnoski <dm...@sosnoski.com> wrote:

> Nilupa Bandara wrote:
>
>> Hello Everyone,
>>
>> The code that I've written so far is available at[1], [2] and it for
>> simple
>> data types. I've used the Axis2 JiBX implementation as guide and now I am
>> working on implementing the complex data type support.
>>
>>
>
> I haven't had a chance to look at this in any detail, but I suspect you may
> be going off track. The Axis2 support uses code generation of the actual
> stub code called by the client to access the server, and the message
> receiver code on the server side which calls the service method. The simple
> data type support comes in when unwrapping a request message from the WSDL
> to pass the child elements as method parameters.
>
> From what I understand of CXF's implementation it always uses a wrapper
> class that matches the actual request or response message element (which is
> the content of the SOAP Body element), and handles converting this into
> method parameters with shared logic. So you shouldn't need to work with the
> simple data types at all.
>
> What I'd think you would need to work on would be handling the actual JiBX
> conversions to and from the SOAP Body. I've tried taking a look at the
> XMLBeans support in CXF to see if I could get a handle on how this needs to
> be done, but I find the code hard to follow with the only comments brief
> one-liners on interface method definitions. So here's my take on how I think
> this should work, and perhaps Dan or someone else can help match this up
> with the CXF structure.
>
> To start with, you need to have some sort of configuration which tells you
> how to access the JiBX binding factory. JiBX is very flexible in how it
> handles bindings, including allowing multiple bindings of the same class to
> different XML representations. Each binding has an associated factory class
> used to work with that binding at runtime. You load a binding factory using
> the methods in org.jibx.runtime.BindingDirectory, which work with several
> variations of parameters:
>
>  1. by the binding name and base Java package in the binding
>  2. by the binding name and one of the classes mapped in that binding
>  3. by one of the classes mapped in the binding (if that class is only
>     involved in one binding).
>
> You can pass a classloader to the first two variations, to specify where
> the classes can be found. If you don't supply a classloader, the
> BindingDirectory does its best to find things using the classloader which
> loaded the class you pass in (if using a class) or the classloader which
> loaded the BindingDirectory class (if using package name lookup). Binding
> factories are thread-safe and can be cached once you've found them.
>
> When handling input, you need to start with the XMLStreamReader positioned
> at the start tag of the message element (the child of the SOAP Body
> element). You create an unmarshalling context instance from the binding
> factory which you'll use for unmarshalling the data. This is an interface,
> but for your purposes you'll need to cast it to the actual implementation
> class org.jibx.runtime.impl.UnmarshallingContext and use the setDocument()
> method which takes an IXMLReader instance. You create the IXMLReader
> instance from your existing XMLStreamReader using the
> org.jibx.runtime.impl.StAXReaderWrapper constructor. You should be able to
> just call the unmarshalElement() method of the unmarshalling context and get
> back the unmarshalled instance.
>
> It looks like you've figured out much of this, but I wanted to spell it out
> to help you understand the sequence. From your stack trace it appears you're
> calling parseElementText(), which is definitely not what you want to use -
> this just returns text content for an element with no child elements.
>
> Handling output is a little different You first create a marshalling
> context, then a org.jibx.runtime.impl.StAXWriter using the constructor which
> takes an XMLStreamWriter (for the namespace URIs, just pass an array with
> the two required values listed in the method JavaDocs), and set the
> StAXWriter on the marshalling context. Then cast the object you're going to
> marshal to the org.jibx.runtime.IMarshallable interface (which is added to
> each mapped class by the JiBX binding compiler) and call the marshal()
> method defined by this interface.
>
> Hope this gets you further. Keep us posted on this list and I'll try to
> provide pointers whenever you run into problems.
>
> Once the basic JiBX runtime support is working we can discuss how to
> integrate JiBX code generation from schema, but I think the basic runtime
> support is the most important step.
>
>  - Dennis
>
>


-- 
Nilupa Bandara

Re: JiBX databinding implementation

Posted by Dennis Sosnoski <dm...@sosnoski.com>.
Nilupa Bandara wrote:
> Hello Everyone,
>
> The code that I've written so far is available at[1], [2] and it for simple
> data types. I've used the Axis2 JiBX implementation as guide and now I am
> working on implementing the complex data type support.
>   

I haven't had a chance to look at this in any detail, but I suspect you 
may be going off track. The Axis2 support uses code generation of the 
actual stub code called by the client to access the server, and the 
message receiver code on the server side which calls the service method. 
The simple data type support comes in when unwrapping a request message 
from the WSDL to pass the child elements as method parameters.

 From what I understand of CXF's implementation it always uses a wrapper 
class that matches the actual request or response message element (which 
is the content of the SOAP Body element), and handles converting this 
into method parameters with shared logic. So you shouldn't need to work 
with the simple data types at all.

What I'd think you would need to work on would be handling the actual 
JiBX conversions to and from the SOAP Body. I've tried taking a look at 
the XMLBeans support in CXF to see if I could get a handle on how this 
needs to be done, but I find the code hard to follow with the only 
comments brief one-liners on interface method definitions. So here's my 
take on how I think this should work, and perhaps Dan or someone else 
can help match this up with the CXF structure.

To start with, you need to have some sort of configuration which tells 
you how to access the JiBX binding factory. JiBX is very flexible in how 
it handles bindings, including allowing multiple bindings of the same 
class to different XML representations. Each binding has an associated 
factory class used to work with that binding at runtime. You load a 
binding factory using the methods in org.jibx.runtime.BindingDirectory, 
which work with several variations of parameters:

   1. by the binding name and base Java package in the binding
   2. by the binding name and one of the classes mapped in that binding
   3. by one of the classes mapped in the binding (if that class is only
      involved in one binding).

You can pass a classloader to the first two variations, to specify where 
the classes can be found. If you don't supply a classloader, the 
BindingDirectory does its best to find things using the classloader 
which loaded the class you pass in (if using a class) or the classloader 
which loaded the BindingDirectory class (if using package name lookup). 
Binding factories are thread-safe and can be cached once you've found them.

When handling input, you need to start with the XMLStreamReader 
positioned at the start tag of the message element (the child of the 
SOAP Body element). You create an unmarshalling context instance from 
the binding factory which you'll use for unmarshalling the data. This is 
an interface, but for your purposes you'll need to cast it to the actual 
implementation class org.jibx.runtime.impl.UnmarshallingContext and use 
the setDocument() method which takes an IXMLReader instance. You create 
the IXMLReader instance from your existing XMLStreamReader using the 
org.jibx.runtime.impl.StAXReaderWrapper constructor. You should be able 
to just call the unmarshalElement() method of the unmarshalling context 
and get back the unmarshalled instance.

It looks like you've figured out much of this, but I wanted to spell it 
out to help you understand the sequence. From your stack trace it 
appears you're calling parseElementText(), which is definitely not what 
you want to use - this just returns text content for an element with no 
child elements.

Handling output is a little different You first create a marshalling 
context, then a org.jibx.runtime.impl.StAXWriter using the constructor 
which takes an XMLStreamWriter (for the namespace URIs, just pass an 
array with the two required values listed in the method JavaDocs), and 
set the StAXWriter on the marshalling context. Then cast the object 
you're going to marshal to the org.jibx.runtime.IMarshallable interface 
(which is added to each mapped class by the JiBX binding compiler) and 
call the marshal() method defined by this interface.

Hope this gets you further. Keep us posted on this list and I'll try to 
provide pointers whenever you run into problems.

Once the basic JiBX runtime support is working we can discuss how to 
integrate JiBX code generation from schema, but I think the basic 
runtime support is the most important step.

  - Dennis


Re: JiBX databinding implementation

Posted by Daniel Kulp <dk...@apache.org>.
On Friday 21 May 2010 8:57:32 pm Nilupa Bandara wrote:
> Hello Everyone,
> 
> The code that I've written so far is available at[1], [2] and it for simple
> data types. I've used the Axis2 JiBX implementation as guide and now I am
> working on implementing the complex data type support.
> 
> However there seems to be an error when we present the XMLSteramReader
> obtained form CXF runtime to JiBX UnmashallingContext which needs work on
> process a part of an XML document not as a whole. However when we present
> an XMLStreamRead from which it can read the desired element as a whole
> document it seems to work.[4]. I suspect this is a bug in JiBX framework
> and I am willing to hear expert advice on this.

Not really sure what to suggest on this.   I know with XMLBeans in JAX-RS, we 
did have some issues if the XMLStreamReader wasn't positioned exactly where it 
wanted to be.   I think XMLBeans didn't want the start doc events or something 
so had to make sure it was "next" beyond that.     I would try fiddling with 
the stream reader in your standalone "full document" case to see if you can 
get it the same state as CXF presents it to see if that reproduces it and then 
kind of reverse you changes to see what may be doable to fix how CXF calls 
into JiBX.

Dan


> 
> Any suggestions, advice and tips will be much appreciated !!
> 
> 
> Thanks & Regards,
> Nilupa
> 
> [1] http://github.com/nilupa/cxf
> 
> [2] http://github.com/nilupa/cxf/tree/trunk/rt/databinding/jibx/
> 
> [3] Error output:
> 
> ava.lang.ArrayIndexOutOfBoundsException: Attempt to peek past end of stack
> at org.jibx.runtime.IntStack.peek(IntStack.java:231)
> at org.jibx.runtime.IntStack.peek(IntStack.java:245)
> at
> org.jibx.runtime.impl.StAXReaderWrapper.endTag(StAXReaderWrapper.java:159)
> at
> org.jibx.runtime.impl.StAXReaderWrapper.nextToken(StAXReaderWrapper.java:18
> 2) at
> org.jibx.runtime.impl.UnmarshallingContext.accumulateText(UnmarshallingCont
> ext.java:840) at
> org.jibx.runtime.impl.UnmarshallingContext.parseContentText(UnmarshallingCo
> ntext.java:874) at
> org.jibx.runtime.impl.UnmarshallingContext.parseElementText(UnmarshallingCo
> ntext.java:936) at
> org.apache.xcf.jibx.JibxDataReader.read(JibxDataReader.java:57) at
> org.apache.xcf.jibx.JibxDataReader.read(JibxDataReader.java:1)
> at
> org.apache.cxf.interceptor.DocLiteralInInterceptor.getPara(DocLiteralInInte
> rceptor.java:251) at
> org.apache.cxf.interceptor.DocLiteralInInterceptor.handleMessage(DocLiteral
> InInterceptor.java:127) at
> org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChai
> n.java:243) at
> org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationO
> bserver.java:110) at
> org.apache.cxf.transport.http_jetty.JettyHTTPDestination.serviceRequest(Jet
> tyHTTPDestination.java:313) at
> org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTT
> PDestination.java:277) at
> org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandle
> r.java:70) at
> org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
> at
> org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCol
> lection.java:230) at
> org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
> at org.mortbay.jetty.Server.handle(Server.java:326)
> at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:536)
> at
> org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java
> :930) at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:747)
> at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
> at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:405)
> at
> org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409
> ) at
> org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:58
> 2)
> 
> [4] Work around JibxDataReader.java : line 90
> 
>         try {
>             reader =
> StaxUtils.createXMLStreamReader(StaxUtils.read(reader));
>         } catch (Exception e) {
>             throw new RuntimeException(e);
>         }
> 
> 
> 
> 
> On Fri, Apr 30, 2010 at 11:30 AM, Nilupa Bandara
> <nilupa.manamperi@gmail.com
> 
> > wrote:
> > 
> > Hi,
> > 
> > At the moment, I am running the sample Web services in debug mode just to
> > get a deeper understanding of how the cxf data
> > 
> >  binding architecture works at runtime. I am also planning to look at how
> > 
> > its done for Axis2 and perhaps we might be able to reuse some of that
> > code there. As soon as I have something concrete, will post it to this
> > mailing list.
> > 
> > Thanks & Best Regards,
> > Nilupa
> > 
> > On Fri, Apr 30, 2010 at 2:00 AM, Dennis Sosnoski <dm...@sosnoski.com> wrote:
> >> I'm curious how the JiBX databinding GSoC project is progressing...
> >> anything to discuss yet?
> >> 
> >> JiBX is pretty flexible in how it reads and writes XML, with its own
> >> org.jibx.runtime.IXMLReader and IXMLWriter interfaces used to decouple
> >> from the details of the parser and writer. Implementations of these
> >> interfaces are supplied for working with StAX XMLStreamReader and
> >> XMLStreamWriter, and the existing Axis2 support for JiBX should be a
> >> good guide for fitting the actual runtime hooks together.
> >> 
> >> Just to make sure I understand how this works, JAX-WS configuration can
> >> be used with any type of org.apache.cxf.databinding.DataBinding
> >> implementation, right? So someone wanting to use JiBX with a JAX-WS
> >> frontend would just need to specify this using their preferred
> >> configuration technique (such as cxf-client.xml on the client side).
> >> 
> >> Thanks,
> >> 
> >>  - Dennis

-- 
Daniel Kulp
dkulp@apache.org
http://dankulp.com/blog

Re: JiBX databinding implementation

Posted by Nilupa Bandara <ni...@gmail.com>.
Hello Everyone,

The code that I've written so far is available at[1], [2] and it for simple
data types. I've used the Axis2 JiBX implementation as guide and now I am
working on implementing the complex data type support.

However there seems to be an error when we present the XMLSteramReader
obtained form CXF runtime to JiBX UnmashallingContext which needs work on
process a part of an XML document not as a whole. However when we present an
XMLStreamRead from which it can read the desired element as a whole document
it seems to work.[4]. I suspect this is a bug in JiBX framework and I am
willing to hear expert advice on this.

Any suggestions, advice and tips will be much appreciated !!


Thanks & Regards,
Nilupa

[1] http://github.com/nilupa/cxf

[2] http://github.com/nilupa/cxf/tree/trunk/rt/databinding/jibx/

[3] Error output:

ava.lang.ArrayIndexOutOfBoundsException: Attempt to peek past end of stack
at org.jibx.runtime.IntStack.peek(IntStack.java:231)
at org.jibx.runtime.IntStack.peek(IntStack.java:245)
at
org.jibx.runtime.impl.StAXReaderWrapper.endTag(StAXReaderWrapper.java:159)
at
org.jibx.runtime.impl.StAXReaderWrapper.nextToken(StAXReaderWrapper.java:182)
at
org.jibx.runtime.impl.UnmarshallingContext.accumulateText(UnmarshallingContext.java:840)
at
org.jibx.runtime.impl.UnmarshallingContext.parseContentText(UnmarshallingContext.java:874)
at
org.jibx.runtime.impl.UnmarshallingContext.parseElementText(UnmarshallingContext.java:936)
at org.apache.xcf.jibx.JibxDataReader.read(JibxDataReader.java:57)
at org.apache.xcf.jibx.JibxDataReader.read(JibxDataReader.java:1)
at
org.apache.cxf.interceptor.DocLiteralInInterceptor.getPara(DocLiteralInInterceptor.java:251)
at
org.apache.cxf.interceptor.DocLiteralInInterceptor.handleMessage(DocLiteralInInterceptor.java:127)
at
org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:243)
at
org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:110)
at
org.apache.cxf.transport.http_jetty.JettyHTTPDestination.serviceRequest(JettyHTTPDestination.java:313)
at
org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTTPDestination.java:277)
at
org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandler.java:70)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at
org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:536)
at
org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:930)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:747)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:405)
at
org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
at
org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)

[4] Work around JibxDataReader.java : line 90

        try {
            reader =
StaxUtils.createXMLStreamReader(StaxUtils.read(reader));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }




On Fri, Apr 30, 2010 at 11:30 AM, Nilupa Bandara <nilupa.manamperi@gmail.com
> wrote:

> Hi,
>
> At the moment, I am running the sample Web services in debug mode just to
> get a deeper understanding of how the cxf data
>  binding architecture works at runtime. I am also planning to look at how
> its done for Axis2 and perhaps we might be able to reuse some of that code
> there. As soon as I have something concrete, will post it to this mailing
> list.
>
> Thanks & Best Regards,
> Nilupa
>
>
> On Fri, Apr 30, 2010 at 2:00 AM, Dennis Sosnoski <dm...@sosnoski.com> wrote:
>
>> I'm curious how the JiBX databinding GSoC project is progressing...
>> anything to discuss yet?
>>
>> JiBX is pretty flexible in how it reads and writes XML, with its own
>> org.jibx.runtime.IXMLReader and IXMLWriter interfaces used to decouple from
>> the details of the parser and writer. Implementations of these interfaces
>> are supplied for working with StAX XMLStreamReader and XMLStreamWriter, and
>> the existing Axis2 support for JiBX should be a good guide for fitting the
>> actual runtime hooks together.
>>
>> Just to make sure I understand how this works, JAX-WS configuration can be
>> used with any type of org.apache.cxf.databinding.DataBinding implementation,
>> right? So someone wanting to use JiBX with a JAX-WS frontend would just need
>> to specify this using their preferred configuration technique (such as
>> cxf-client.xml on the client side).
>>
>> Thanks,
>>
>>  - Dennis
>>
>
>


-- 
Nilupa Bandara

Re: JiBX databinding implementation

Posted by Nilupa Bandara <ni...@gmail.com>.
Hi,

At the moment, I am running the sample Web services in debug mode just to
get a deeper understanding of how the cxf data
 binding architecture works at runtime. I am also planning to look at how
its done for Axis2 and perhaps we might be able to reuse some of that code
there. As soon as I have something concrete, will post it to this mailing
list.

Thanks & Best Regards,
Nilupa


On Fri, Apr 30, 2010 at 2:00 AM, Dennis Sosnoski <dm...@sosnoski.com> wrote:

> I'm curious how the JiBX databinding GSoC project is progressing...
> anything to discuss yet?
>
> JiBX is pretty flexible in how it reads and writes XML, with its own
> org.jibx.runtime.IXMLReader and IXMLWriter interfaces used to decouple from
> the details of the parser and writer. Implementations of these interfaces
> are supplied for working with StAX XMLStreamReader and XMLStreamWriter, and
> the existing Axis2 support for JiBX should be a good guide for fitting the
> actual runtime hooks together.
>
> Just to make sure I understand how this works, JAX-WS configuration can be
> used with any type of org.apache.cxf.databinding.DataBinding implementation,
> right? So someone wanting to use JiBX with a JAX-WS frontend would just need
> to specify this using their preferred configuration technique (such as
> cxf-client.xml on the client side).
>
> Thanks,
>
>  - Dennis
>