You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cxf.apache.org by Nilupa Bandara <ni...@gmail.com> on 2010/06/18 02:58:36 UTC

[JiBX DataBinding] Question on handling Simple Types

Hi,

Consider the following Java class which provides simple echoString service.

public interface EchoService {

    String echoString(String content);
}

I exposed it as a Web service using the following code.

EchoServiceImpl echoServiceImpl = new EchoServiceImpl();
ServerFactoryBean svrFactory = new ServerFactoryBean();
svrFactory.setServiceClass(EchoService.class);
svrFactory.setAddress("http://localhost:8080/EchoService");
svrFactory.setServiceBean(echoServiceImpl);
svrFactory.getServiceFactory().setDataBinding(new JiBXDataBinding());
svrFactory.create();

It produces the correct output for the following input.

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <ns1:echoString xmlns:ns1="http://simple_types.jibx.xcf.apache.org/">
         <ns1:arg0>Alice</ns1:arg0>
      </ns1:echoString>
   </soap:Body>
</soap:Envelope>

My question is the following.

When the CXF framework receives the message, it invokes the JiBXDataReader
to unmarshall  xml content which is "<ns1:arg0>Alice</ns1:arg0>".  However
it seems that I can't unmarshall it using
unmarshallingContext.unmarshallElement(..) method since UnmarhallingContext
can't be obtained for "<ns1:arg0>Alice</ns1:arg0>". That is because
"<ns1:arg0>Alice</ns1:arg0>" element doesn't corresponds to a Java classes
compiled with binding info. One work around would be to use
the JibxNullBindingFactory[2]  to imitate the IBindingFactory interface for
simple types.

So should we proceed with the above workaround /  Is there a better way of
doing it? Or should we completely ignore above case and support only the
exposure of Java beans compiled with binding information. (i.e. the
echoString method should be change to something like  Output
echoString(Input) where both Input, Output are Java beans compiled with
binding information. Input, Output act as wrapper classes for the string
content going to-and-from)

Any thoughts ?

Nilupa

[1] Updated JiBX DataBinding implementation code is available at :
http://github.com/nilupa/cxf/tree/trunk/rt/databinding/jibx/
[2]
http://github.com/nilupa/cxf/blob/trunk/rt/databinding/jibx/src/main/java/org/apache/xcf/jibx/JibxNullBindingFactory.java

Re: [JiBX DataBinding] Question on handling Simple Types

Posted by Nilupa Bandara <ni...@gmail.com>.
On Sat, Jun 26, 2010 at 1:38 AM, Dennis Sosnoski <dm...@sosnoski.com> wrote:

> Daniel Kulp wrote:
>
>> There is a ReflectionWrapperHelper object in there that can be used as an
>> example.   JAXB uses a more optimized version that generates a unique helper
>> using ASM, but reflection is used as a fallback if that fails.  (or asm
>> isn't available)
>>
>>
>
> Sounds like that's the way to go, then. Nilupa, for now you'll need to
> extract the schema for the wrappers (along with any other embedded schemas)
> and pass it to the JiBX code generation, then link up whatever is needed for
> the ReflectionWrapperHelper. I'll try to clean up the interface used for
> JiBX code generation as part of the 1.2.3 release, to make it easier to use
> from other programs.
>
> Generating code at runtime to do the unwrapping, rather than just using
> reflection, frankly seems a waste of effort to me. The overhead from one
> reflection method call is insignificant compared to the XML processing time,
> and you'd need to do hundreds or thousands of calls to actually come out
> with a net performance gain.
>
>  - Dennis
>

Thanks .. I'm working on it and will post my progress.

Nilupa




-- 
Nilupa Bandara

Re: [JiBX DataBinding] Question on handling Simple Types

Posted by Dennis Sosnoski <dm...@sosnoski.com>.
Daniel Kulp wrote:
> There is a ReflectionWrapperHelper object in there that can be used as an 
> example.   JAXB uses a more optimized version that generates a unique helper 
> using ASM, but reflection is used as a fallback if that fails.  (or asm isn't 
> available)
>   

Sounds like that's the way to go, then. Nilupa, for now you'll need to 
extract the schema for the wrappers (along with any other embedded 
schemas) and pass it to the JiBX code generation, then link up whatever 
is needed for the ReflectionWrapperHelper. I'll try to clean up the 
interface used for JiBX code generation as part of the 1.2.3 release, to 
make it easier to use from other programs.

Generating code at runtime to do the unwrapping, rather than just using 
reflection, frankly seems a waste of effort to me. The overhead from one 
reflection method call is insignificant compared to the XML processing 
time, and you'd need to do hundreds or thousands of calls to actually 
come out with a net performance gain.

  - Dennis

Re: [JiBX DataBinding] Question on handling Simple Types

Posted by Daniel Kulp <dk...@apache.org>.
On Friday 25 June 2010 12:55:54 pm Dennis Sosnoski wrote:
> Daniel Kulp wrote:
> > Well, another option to consider (I'm not saying this is the way to go,
> > just something to consider.  I don't even know if this is possible with
> > JIBX) is how the JAXWS/JAXB code handles this....
> > 
> > With JAX-WS/JAXB, it uses ASM to generate, in memory, classes for the
> > wrapper element which contains all the JAXB annotations and such
> > necessary to completely read/write the entire message body.   There is
> > then a WrapperHelper to pull the individual params out of that object.  
> > Thus, JAXB doesn't see the <arg0>Alice</arg0>, it sees the entire
> > message as a structure.
> > 
> > Right now, the creation of the wrapper beans is done in the JAX-WS
> > frontend, but I could definitely see pushing that into the JAXB
> > databinding and allow other databindings to do the same.   If you think
> > it's possible with JIBX, it's something we could look into more.
> 
> Ah, I hadn't realized this was the approach used by JAX-WS. That does
> tie it directly to JAXB and makes it pretty much unusable with other
> binding techniques. Ugly.

Yea.   The other databindings can make use of wrapper types providing they are 
pre-generated.   For example, with XMLBeans, if the schema used also defines 
the wrappers, it works fine.   The databinding does create the wrapper helper 
things that are used to pull/set the data from the wrappers.    The only thing 
that cannot be done right now is to fully create the wrappers in memory when 
they currently do not exist.

> > The other option would be to just handle it yourself.   Get the element
> > text, you know the Class, since it would just be the primitives, the
> > number of cases you need to handle is pretty small and most of the code
> > is probably already in Aegis someplace.
> 
> The Axis2-JiBX code is already handling unmarshalling of these types, so
> I don't think the unmarshalling using JiBX is much of a problem. What's
> more difficult is actually relaying the unmarshalled data to the service
> method.
> 
> Perhaps the cleanest way to handle this with JiBX in CXF is to have JiBX
> generate it's own wrapper classes which are unmarshalled normally. But
> then the data needs to be extracted from the wrapper class instance and
> passed to the service method. How is JAX-WS handling that extraction and
> data-passing step? If we could make it compatible for JiBX perhaps we
> could hook into the JAX-WS handling at that point.

Databindings can optional return a WrapperHelper object that does this.   
There is a ReflectionWrapperHelper object in there that can be used as an 
example.   JAXB uses a more optimized version that generates a unique helper 
using ASM, but reflection is used as a fallback if that fails.  (or asm isn't 
available)

Dan


> The alternative is probably to only support wrapped method calls for
> now, where the wrapper class instance is passed directly to the method.
> That's somewhat ugly for client-side code, though.
> 
>   - Dennis

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

Re: [JiBX DataBinding] Question on handling Simple Types

Posted by Dennis Sosnoski <dm...@sosnoski.com>.
Daniel Kulp wrote:
> Well, another option to consider (I'm not saying this is the way to go, just 
> something to consider.  I don't even know if this is possible with JIBX) is 
> how the JAXWS/JAXB code handles this....
>
> With JAX-WS/JAXB, it uses ASM to generate, in memory, classes for the wrapper 
> element which contains all the JAXB annotations and such necessary to 
> completely read/write the entire message body.   There is then a WrapperHelper 
> to pull the individual params out of that object.   Thus, JAXB doesn't see the 
> <arg0>Alice</arg0>, it sees the entire message as a structure.
>
> Right now, the creation of the wrapper beans is done in the JAX-WS frontend, 
> but I could definitely see pushing that into the JAXB databinding and allow 
> other databindings to do the same.   If you think it's possible with JIBX, 
> it's something we could look into more.
>   

Ah, I hadn't realized this was the approach used by JAX-WS. That does 
tie it directly to JAXB and makes it pretty much unusable with other 
binding techniques. Ugly.

> The other option would be to just handle it yourself.   Get the element text, 
> you know the Class, since it would just be the primitives, the number of cases 
> you need to handle is pretty small and most of the code is probably already in 
> Aegis someplace.
>   

The Axis2-JiBX code is already handling unmarshalling of these types, so 
I don't think the unmarshalling using JiBX is much of a problem. What's 
more difficult is actually relaying the unmarshalled data to the service 
method.

Perhaps the cleanest way to handle this with JiBX in CXF is to have JiBX 
generate it's own wrapper classes which are unmarshalled normally. But 
then the data needs to be extracted from the wrapper class instance and 
passed to the service method. How is JAX-WS handling that extraction and 
data-passing step? If we could make it compatible for JiBX perhaps we 
could hook into the JAX-WS handling at that point.

The alternative is probably to only support wrapped method calls for 
now, where the wrapper class instance is passed directly to the method. 
That's somewhat ugly for client-side code, though.

  - Dennis


Re: [JiBX DataBinding] Question on handling Simple Types

Posted by Nilupa Bandara <ni...@gmail.com>.
On Fri, Jun 18, 2010 at 4:33 AM, Daniel Kulp <dk...@apache.org> wrote:

>
> Well, another option to consider (I'm not saying this is the way to go,
> just
> something to consider.  I don't even know if this is possible with JIBX) is
> how the JAXWS/JAXB code handles this....
>
> With JAX-WS/JAXB, it uses ASM to generate, in memory, classes for the
> wrapper
> element which contains all the JAXB annotations and such necessary to
> completely read/write the entire message body.   There is then a
> WrapperHelper
> to pull the individual params out of that object.   Thus, JAXB doesn't see
> the
> <arg0>Alice</arg0>, it sees the entire message as a structure.
>
> Right now, the creation of the wrapper beans is done in the JAX-WS
> frontend,
> but I could definitely see pushing that into the JAXB databinding and allow
> other databindings to do the same.   If you think it's possible with JIBX,
> it's something we could look into more.
>
> The other option would be to just handle it yourself.   Get the element
> text,
> you know the Class, since it would just be the primitives, the number of
> cases
> you need to handle is pretty small and most of the code is probably already
> in
> Aegis someplace.
>


I think the right way to generate the wrapper beans with JiBX framework is
to use its tools and feed the schema or the binding definitions as
appropriate. As far as I know, a set of wrapper classes are generated for
those simple types that are used. In other words if the service author
wishes to expose a Java bean as a Web service which purely uses compiled or
generated Java beans using JiBX framework internally, this issues doesn't
occurs as we don't have to deal with simple types directly since they are
already contained in some wrapper Java beans. We can use the JiBX framework
to unmarshall them for us in the usual way.

We have to deal with this only we expose a Java bean like in the example
which is neither generated or compiled bean using jibx framework, but rather
simple bean which all its method inputs and outputs are simple types.
Perhaps in such cases, it is reasonable to handle it on our own as we do it
right now since there is only  a few number of cases. In the solution I've
opted to use the NullBindingFactory for unmarshalling they simple types
which mimics the IBandingFactory used to unmarshall complied Java beans
using jibx framework (in fact I took that piece of code from Axis2 JiBX
implementation)

Nilupa


>
> Dan
>
>
>
> On Thursday 17 June 2010 8:58:36 pm Nilupa Bandara wrote:
> > Hi,
> >
> > Consider the following Java class which provides simple echoString
> service.
> >
> > public interface EchoService {
> >
> >     String echoString(String content);
> > }
> >
> > I exposed it as a Web service using the following code.
> >
> > EchoServiceImpl echoServiceImpl = new EchoServiceImpl();
> > ServerFactoryBean svrFactory = new ServerFactoryBean();
> > svrFactory.setServiceClass(EchoService.class);
> > svrFactory.setAddress("http://localhost:8080/EchoService");
> > svrFactory.setServiceBean(echoServiceImpl);
> > svrFactory.getServiceFactory().setDataBinding(new JiBXDataBinding());
> > svrFactory.create();
> >
> > It produces the correct output for the following input.
> >
> > <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
> >    <soap:Body>
> >       <ns1:echoString xmlns:ns1="
> http://simple_types.jibx.xcf.apache.org/">
> >          <ns1:arg0>Alice</ns1:arg0>
> >       </ns1:echoString>
> >    </soap:Body>
> > </soap:Envelope>
> >
> > My question is the following.
> >
> > When the CXF framework receives the message, it invokes the
> JiBXDataReader
> > to unmarshall  xml content which is "<ns1:arg0>Alice</ns1:arg0>".
>  However
> > it seems that I can't unmarshall it using
> > unmarshallingContext.unmarshallElement(..) method since
> UnmarhallingContext
> > can't be obtained for "<ns1:arg0>Alice</ns1:arg0>". That is because
> > "<ns1:arg0>Alice</ns1:arg0>" element doesn't corresponds to a Java
> classes
> > compiled with binding info. One work around would be to use
> > the JibxNullBindingFactory[2]  to imitate the IBindingFactory interface
> for
> > simple types.
> >
> > So should we proceed with the above workaround /  Is there a better way
> of
> > doing it? Or should we completely ignore above case and support only the
> > exposure of Java beans compiled with binding information. (i.e. the
> > echoString method should be change to something like  Output
> > echoString(Input) where both Input, Output are Java beans compiled with
> > binding information. Input, Output act as wrapper classes for the string
> > content going to-and-from)
> >
> > Any thoughts ?
> >
> > Nilupa
> >
> > [1] Updated JiBX DataBinding implementation code is available at :
> > http://github.com/nilupa/cxf/tree/trunk/rt/databinding/jibx/
> > [2]
> >
> http://github.com/nilupa/cxf/blob/trunk/rt/databinding/jibx/src/main/java/o
> > rg/apache/xcf/jibx/JibxNullBindingFactory.java
>
> --
> Daniel Kulp
> dkulp@apache.org
> http://dankulp.com/blog
>



-- 
Nilupa Bandara

Re: [JiBX DataBinding] Question on handling Simple Types

Posted by Daniel Kulp <dk...@apache.org>.
Well, another option to consider (I'm not saying this is the way to go, just 
something to consider.  I don't even know if this is possible with JIBX) is 
how the JAXWS/JAXB code handles this....

With JAX-WS/JAXB, it uses ASM to generate, in memory, classes for the wrapper 
element which contains all the JAXB annotations and such necessary to 
completely read/write the entire message body.   There is then a WrapperHelper 
to pull the individual params out of that object.   Thus, JAXB doesn't see the 
<arg0>Alice</arg0>, it sees the entire message as a structure.

Right now, the creation of the wrapper beans is done in the JAX-WS frontend, 
but I could definitely see pushing that into the JAXB databinding and allow 
other databindings to do the same.   If you think it's possible with JIBX, 
it's something we could look into more.

The other option would be to just handle it yourself.   Get the element text, 
you know the Class, since it would just be the primitives, the number of cases 
you need to handle is pretty small and most of the code is probably already in 
Aegis someplace.

Dan



On Thursday 17 June 2010 8:58:36 pm Nilupa Bandara wrote:
> Hi,
> 
> Consider the following Java class which provides simple echoString service.
> 
> public interface EchoService {
> 
>     String echoString(String content);
> }
> 
> I exposed it as a Web service using the following code.
> 
> EchoServiceImpl echoServiceImpl = new EchoServiceImpl();
> ServerFactoryBean svrFactory = new ServerFactoryBean();
> svrFactory.setServiceClass(EchoService.class);
> svrFactory.setAddress("http://localhost:8080/EchoService");
> svrFactory.setServiceBean(echoServiceImpl);
> svrFactory.getServiceFactory().setDataBinding(new JiBXDataBinding());
> svrFactory.create();
> 
> It produces the correct output for the following input.
> 
> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
>    <soap:Body>
>       <ns1:echoString xmlns:ns1="http://simple_types.jibx.xcf.apache.org/">
>          <ns1:arg0>Alice</ns1:arg0>
>       </ns1:echoString>
>    </soap:Body>
> </soap:Envelope>
> 
> My question is the following.
> 
> When the CXF framework receives the message, it invokes the JiBXDataReader
> to unmarshall  xml content which is "<ns1:arg0>Alice</ns1:arg0>".  However
> it seems that I can't unmarshall it using
> unmarshallingContext.unmarshallElement(..) method since UnmarhallingContext
> can't be obtained for "<ns1:arg0>Alice</ns1:arg0>". That is because
> "<ns1:arg0>Alice</ns1:arg0>" element doesn't corresponds to a Java classes
> compiled with binding info. One work around would be to use
> the JibxNullBindingFactory[2]  to imitate the IBindingFactory interface for
> simple types.
> 
> So should we proceed with the above workaround /  Is there a better way of
> doing it? Or should we completely ignore above case and support only the
> exposure of Java beans compiled with binding information. (i.e. the
> echoString method should be change to something like  Output
> echoString(Input) where both Input, Output are Java beans compiled with
> binding information. Input, Output act as wrapper classes for the string
> content going to-and-from)
> 
> Any thoughts ?
> 
> Nilupa
> 
> [1] Updated JiBX DataBinding implementation code is available at :
> http://github.com/nilupa/cxf/tree/trunk/rt/databinding/jibx/
> [2]
> http://github.com/nilupa/cxf/blob/trunk/rt/databinding/jibx/src/main/java/o
> rg/apache/xcf/jibx/JibxNullBindingFactory.java

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