← Prev in month ← Prev in thread

ISSUE 134: JAXBHelperContext

From
Barack, Ron <>
Date
2009-02-02T09:03:05+00:00
ID
Thread
ISSUE 134: JAXBHelperContext
Title: ISSUE 5 and ISSUE 22: Discussion of JAXB

Hi Blaise,

 

Some more questions on your implementation of 
JaxbHelperContext

hc.wrap(Object) always returns the same DataObject for 
the same pojo.  Does this rely on the equals() and hash() methods as 
implemented in the class?  Imagine 2 pojos, where p1!=p2 but 
p1.equals(p2).  Would hc.wrap(p1)==hc.wrap(p2)?  What about if 
p1.class has some @XmlID field?

 

Looking at your sample, it's a little hard to discern 
the lifecycle of the JaxbHelperContext.  Because constructing the types is 
expensive (involving parsing XSDs, etc), I normally think of HelperContexts as 
having to be thread-safe and shared, like a JAXBContext, or like a 
classloader.  For instance, when a session bean uses SDO, there would 
be one HelperContext that are shared by all instances of the bean.  I 
believe this to be the common 
understanding.   The sample code is of course a simple 
client; it's impossible to tell if the JaxbHelperContext is meant to 
shared.

 

I think there is reason to have maybe JaxbHelperContext 
be a sort of lightweight context, that is meant to be owned by a single 
client.  We could have a heavyweight context, with types defined by the 
XSD.  The heavyweight context could have a method, something like 
HelperContext.getJaxbHelperContext(JAXBContext).  The JaxbHelperContext 
would basically delegate to the heavyweight context, except when doing things 
like constructing instances, or implementing wrap() or 
unwrap().

 

This gives me something like a binder, a client object 
that I can use to control the scope and lifetime of the POJO -> DataObject 
map.  But without defining a new "Binder" interface.

 

Any comments?

 

Ron

 

 

 

Von: Blaise Doughan 
[mailto:] 
Gesendet: Montag, 26. Januar 2009 
16:08
An: Barack, Ron
Cc: 

Betreff: Re: AW: [sdo] ISSUE 5 and ISSUE 22: 
Discussion of JAXB

Hi Ron,

From our perspective JAXBHelper context is the POJO 
Helper Context.

Assuming the POJOs are also JPA entities, then wrapping 
(as opposed to copying via an XML step) need not trigger all the lazy 
relationships (of course this could be implementation dependent).  With 
regards to wrapping and the performance of getters/setters, there are some ways 
to do this with reasonable performance.

The POJO as a DataObject, this is 
an interesting concept.  One problem I see with this is that DataObjects do 
a lot of relationship management that most POJOs don't do (i.e. adding a 
DataObject to a new container automatically removes it from the old 
container).  Here the weaving is not invisible to the user and may not 
match the users expecations.

The XSDHelper.define() call is necessary, 
because as you have previously mentioned XML schemas generated from POJOs do not 
contain all the information required by SDO.  One example is specifying 
datatype=false/containment=false properties, that require SDO annotations on the 
XML schema.

Does  DataObject customerDO = hc.wrap(customer); 
always return the same 
DataObject?
In our 
implementation wrap always returns the same DataObject.  This does require 
some management, but with proper attention to object identity, and avoiding hard 
references it is doable.  Not sure how a "binder" solution avoids this as 
something JAXB like would require a one-to-one correspondence between a POJO and 
a DataObject.

What happens if a wrapped POJO is modified? 

Our 
customer base is not interacting with both the POJO and the DataObject at the 
same time.  If they were you are correct that weaving could be used to 
apply the changes made to the POJO back to the DataObject.

Is there 
any way to start with a DataObject, and generate a JAXB from it?
Yes, 
this was the main reason for making the entry point its own HelperContext.  
DataFactory.create() creates DataObjects that wrap POJOs, and XMLHelper loads 
DataObjects that wrap POJOs.

Usage of StAX
The usage of StAX 
does not automatically create a Java SE 6 dependency.  JAXB 2.0 based on 
Java SE 5 makes use of these APIs, it just requires implementors to ship the 
StAX (JSR 173) API jar.  I think SDO should offer the same 
marshal/unmarshal options as JAXB.  But the decision to change the base 
Java SE version is independent from our inclusion of StAX.

User 
Expectations of the XML representation of POJOs
You are correct in your 
model that the user must specify JAXB information to get the desired XML 
representation.  This is exactly the role of JAXB in the larger world of 
Java EE.  Today users are retrieving data from relational databases as 
POJOs using JPA, and exposing this data through services as XML using 
JAXB.

SDO competing with JAXB
If SDO takes a POJO graph and has 
its own XML representation then yes it is competing with JAXB.  Regardless 
of the algorithm it is impossible to guess the XML schema representation of a 
set of POJOs, as such annotations are required fix it.  With your proposal 
SDO annotations would be required to adjust the XML Schema representation of a 
set of POJOs, again this competes with JAXB.

Advantages of our 
Approach

  
A single integration point between SDO and Java EE (JAXB annotated 
  POJOs),  as opposed to point integrations for JAXB/JPA/POJO/etc. 
  
No SDO POJO annotations required.  Instead the integration point 
  between JAXB/Java EE and SDO is the XML schema. 
  
SDO becomes a value add to JAXB/Java EE introducing enriched metadata, 
  relationship management, dynamic APIs, change summary, etc. 
  
No changes are required to existing Java EE applications (that already 
  expose data as XML) to make them compatible with SDO.  This is what our 
  customers want, a mechanism to make their existing Java EE applications 
  compatible with SDO enabled middle-ware 
plumbing.

-Blaise

Barack, Ron wrote: 

  
  
Hi Blaise,

  
 

  
Lots of interesting stuff.  In a way, the proposal 
  is not far from the "project/cast" methods I proposed here:  http://www.oasis-open.org/apps/org/workgroup/sdo/download.php/27905/SDO3%20Java%20Projections.ppt.  
  See slides 29 and 30.  You've added JAXB intelligence.  Do you see 
  other special contexts, eg, JPAHelperContext or DomHelperContext?  If I 
  understand you, you'd be against anything like a PlainPojoHelperContext, 
  right?

  
 

  
Over the year, I've personally become less convinced of 
  the wrapping approach, as opposed to providing some kind of optimized data 
  transfer. What do you see as the advantage of wrapping over some kind of 
  convert operation?  Instead of wrapping the POJOs, I could mashal them in 
  JAXB, and load them using XMLHelper.  Does wrapping give me something 
  here I could not get through such a mechanism (modulus 
  performance)?   And of course because of the second point below, the 
  getters and setters could become significantly more expensive, offsetting the 
  gains made in avoiding a conversion step.

  
 

  
There is a third approach, and that is for the framework 
  to weave the POJO classes, so that "new Customer()", or at least 
  ObjectFactory.createCustomer() returns an object that already implements 
  DataObject.  It seems to me this is a straightforward extension of JPAs 
  approach.  In our JPA integration, you turn on this bytecode enhancement 
  with a flag in persistence.xml.  Do you think it would be possible to get 
  to this level of integration with JAXB?

  
 

  
Either way, I have some questions to the 
  details:

  
 

  
Why is the call to XSDHelper.define() necessary?  
  Couldn't the metadata be introspected from the POJOs (ala 
  generateSchema())?  Isn't there a danger of the XSD being out of sync 
  with the classes (similar to your comment regarding the @schemaLoc 
  annotation?

  
 

  
Does  DataObject customerDO = hc.wrap(customer); 
  always return the same DataObject?  It's maybe a implementation 
  detail, but does wrap create the DataObjects lazilly or all at 
  once?  If you do it lazilly, you need to maintain a 
  map from the POJO object to the DataObject wrapper, right?  Otherwise as 
  we navigate around, we could wind up with the same POJO having 2 DataObject 
  wrappers.  And such a map raises a bunch of ugly lifecycle issues.  
  This is where I thought something like a binder could come come in handy, as a 
  way of putting the lifecycle in the hands of the client.  
  

  
 

  

  
What happens if a wrapped POJO is modified?  
  Obviously, calls to DataObject.get() would see the changes, but what about 
  things like change tracking, containers, and bi-directional properties, that, 
  in SDO happen implicitly when a setter is called?  Are you "weaving" the 
  byte code of the JAXB POJO?

  
 

  
Is there any way to start with a DataObject, and generate 
  a JAXB from it?  Ie, can I unwrap something that hasn't been 
  wrapped?  When I create a DataObject using DataFactory.create(), does it 
  automatically create an underlying POJO?

  
 

  
Regarding the StAX and JAXB dependencies.  
  I guess it will be 2010 before any SDO 3 implementations are released as 
  products...  I imagine by that time pretty much everyone will be on JSE 
  6.  Maybe we should consider raising the minimum compatible JSE to JSE 
  6.  What do you think?

  
 

  
You mention that customers 
  have expections about the XML representation of POJOs.  What about POJOs 
  that are not organized into a containment structure?  Eg, my 
  example:

  
 

  
    class 
  School {

  
        
  List<Student> getStudents() {...}

  
        
  List<Course> getCourse() {...}

  
     
  }

  
     
  class Course {

  
           
  School getSchool() {...}

  
           List<Student> 
  getStudents() {...}

  
      }

  
      class Student 
  {

  
           
  School getSchool() {...}

  
           
  List<Course> getCourses() {..}

  
      
  }

  
 

  
what do your customers 
  expect from the XML representation of School?  AFAIK, the programmer has 
  to specify the XML containment structure as part of the model, He must 
  annotate give the object ID properties, and he must use @XmlID to indicate 
  non-containment.  I don't think SDO is competing with JAXB if it 
  specifies a mechanism through which such graphs can be marshalled to 
  XML.  SDO 3 offers 2 such mechanisms:  the graph could be placed 
  inside an container with orphan properties, and the containment structure (or 
  alternate structures) can be imposed on the model through the project 
  method.  Offering this kind of fuctionality is one reason to include an 
  SDO-POJO binding in SDO 3.

  
 

  
 

  
 

  
Best 
  Regards,

  
Ron

  
 

  
 

  
 

  

  

  
  Von: Blaise Doughan [mailto:] 
  
Gesendet: Freitag, 23. Januar 2009 17:02
An: Barack, 
  Ron
Cc: 
Betreff: 
  Re: [sdo] ISSUE 5 and ISSUE 22: Discussion of JAXB

Hi 
  Ron,

I'm glad you raised this email thread.  Integration with JAXB 
  (POJOs) is also an important use case to Oracle and in particular the 
  EclipseLink SDO implementation.

Both SDO and JAXB have an XML schema 
  representation of their metadata.  For us this is the join point between 
  these two technologies.  EclipseLink DataObjects are capable of wrapping 
  POJOs, actions applied to the DataObjects (set/unset/detach/etc.) are 
  automatically applied to the underlying POJO.  I have included some code 
  below to demonstrate:
 
    // JAXB - Create the 
  JAXB Context
    JAXBContext jaxbContext = 
  JAXBContext.newInstance("com.example.customer");
 
    
  // SDO - Create the JAXB aware HelperContext
    
  HelperContext hc = new JAXBHelperConext(jaxbContext);
    
  hc.getXSDHelper().define(customerXSD);
 
    // SDO 
  - Wrap the POJO in a DataObject
    Customer customer = new 
  Customer();
    
  customer.setLastName("Doe");
    DataObject customerDO = 
  hc.wrap(customer);

    // SDO - Create and modify 
  DataObjects
    
  customerDO.getString("last-name");   // returns 
  "Doe"
    customerDO.setString("first-name", 
  "Jane");
    DataObject addressDO 
  customerDO.create("address");
    
  addressDO.setString("street", "123 Any 
  Street");
 
    // SDO - Unwrap the 
  POJOs
    // Note: customer == 
  hc.unwrap(customerDO)
    Customer customer2 = (Customer) 
  hc.unwrap(customerDO);
    
I would prefer to not invent 
  a POJO to SDO binding.  Our customers have expectations about the XML 
  representation of POJOs.  As JAXB is included in Java SE 6, I imagine 
  many people share these expectations.  If Java objects save to XML one 
  way, the act of wrapping them in (or converting them to) DataObjects should 
  not change the XML representation.  Of course if users choose to make use 
  of concepts such as ChangeSummary then the XML representation begins to 
  diverge but in predictable and explainable ways.  For us it is imperative 
  that SDO provides a compatible value add to Java EE, and not become a 
  competitor to any of its technologies.

Other Points:

  
    
I agree JAXB annotations do not contain enough metadata to reproduce all 
    SDO metadata.  For example JAXB cannot represent the property index of 
    attribute properties. 
    
JAXB classes generated from XML schema can contain properties that are 
    different from SDO class generation.  Especially wrt choices and 
    substitution groups. 
    
JAXB is primarily concerned with Java classes, while SDO is concerned 
    with Java interfaces.

    
More load/save targets (such as StAX) would be great.  Of course 
    StAX is not included with Java SE 5, and would introduce a new dependency 
    jar.  JAXB has this same requirement and goes away with Java SE 6, so 
    this may not be a big concern. 
    
The JAXB Binder maintains a link between POJOs and DOM nodes.  Once 
    linked you can make changes on one side and then make an explicit call (it 
    doesn't happen automatically) to apply the changes to the other side.  
    While useful the default JAXB algorithm isn't always what users 
    expect.  Our implementation provides the user with the choice of 3 
    different "binding" algorithms. 
-Blaise

Barack, Ron wrote: 
  
    
    
Hi Everyone, 

    
The idea of using JAXB annotations as a solution 
    to ISSUE 22, even of consolidating static SDO and JAXB, has come up 
    repeatedly in the calls.  I think we may be able to make better 
    progress in this regard by discussing the ideas per email, so that there is 
    a permament record of the arguments.  Having this discussion now will 
    hopefully make the discussion during the F2F more productive.

    
First I want to say that integration with JAXB is 
    a high priority issue for us, but this integration may take several 
    forms:

    
1.  Transfering data between the 
    representations 
2.  JAXB annotations 
    as a source of SDO metadata 
3.  JAXB 
    classes as static SDOs 

    
Of course, it is desireable to have as deep and 
    integration as possible.  When I first started thinking about the 
    problem, I set out to achieve all three types of integration.  After 
    long consideration, I arrived at the conclusion that only the first is 
    really possible.

    
About the first point I hope there is general 
    agreement: Applications that use SDO as a data representation must be able 
    to transfer data with applications that use JAXB. In some ways, this is 
    already possible in 2.1:  all you need to do is mashall to XML. This 
    approach introduces some performance costs, and I think we should address 
    steamlining the process in SDO 3.  One approach that we've found to be 
    very helpful is for SDO to be able to produce an XMLStreamReader which in 
    turn can be fed into a JAXB marshaller.  For maintaining an active map 
    between the representations, I believe a DOMBinder is a very promising 
    approach, and possibly we could go a step further and have a JAXB 
    binder.  (Unfortunately, I believe the JSE implementation of JAXB still 
    has an incomplete version of the DOMBinder functionality).

    
Similarly, clients can already use JAXB 
    annotations as a source of SDO metadata under SDO 2.1, at least whereever 
    JAXBContext.generateSchema works it is possible to use XSD as an 
    intermediate metadata format. However, it is important to realize that JAXB 
    does not provide the level of details we expect to see in a resolution to 
    ISSUE 22.  JAXB annotations capture exactly the information necessary 
    to correctly marshal and unmarshal to XML.  Restrictions (facets), and 
    all reference to the original simple type is lost.  JAXB creates String 
    properties for xs:NCName, xs:AnyURI, etc., and there is no way to get back 
    to the original type through reflection on the JAXB object.

    
JAXB objects reflect the purpose of JAXB, which 
    is to create an XML binding for Java.  XML models, and therefore JAXB, 
    do not contain (as a rule) bi-directional or non-containment 
    references.  It's true that XML and JAX can represent non-containment 
    relationships using @XmlID, but in SDO non-containment relationships are not 
    limited to objects that have ID properties (or even keys).

    
If we were to use JAXB annotations as the 
    standard way to represent SDO metadata in Java, then we are also accepting 
    the default behaviour associated with the *absence* of these 
    annotations.  In JAXB, an unannotated POJO class that references a 
    second POJO class is intepreted as there being a containment relationship 
    between the associated types.  I would argue that this should not be 
    the default behaviour for SDO.  If it were, then we loose the ability 
    to to take an arbitrary model based on unannotated classes, pack them in a 
    DataGraph (or anything else that has an orphan property) and being able to 
    generate XML for the model.  The assumption of containment 
    relationships means that we will get cycles and other problems, making the 
    whole approach unworkable.

    
A further problem is that I think we would 
    probably be misusing the JAXB annotations.  Static SDOs may be 
    interfaces or generated classes.  JAXBs are annotated POJOs 
    (JavaBeans).

    
Finally, very pragmatically, the JAXB spec is 
    large and complex.  Expecting implementations to make sense of the 
    annotations and their many combinations is a very high bar indeed, even more 
    so when we expect to enrich the annotation set with some of our own 
    annotations.

    
Having rejected the second point, perhaps the 
    discussion of the third point is moot, but I want to discuss it because the 
    appeal of the approach is so strong.  The appeal can be summarized as 
    follows:  "The JSE already defines a standard XML to Java 
    binding.  By defining static SDOs, we are defining a competive 
    functionality that is therefore doomed to be rejected by the java 
    community.  The problem with this argument is that static SDOs do not 
    represent an XSD, they represent SDO metadata.  Although a large part 
    of the SDO spec contains the mapping between the metamodels, the models are 
    not the same, not is the SDO metamodel a subset of the XSD metamodel 
    (multiple inheritence, bi-directional relationships being two examples of 
    constructs that do not exist in XSD).

    
On a more practical level, although for very 
    simple XSDs the classes generated by JAXB and the static SDOs defined in SDO 
    2.1 are compatible, we very quickly come to places where the models 
    diverge.  SDO represents choices as several parallel properties, and we 
    expect the user to fill one or the other.  JAXB generates a sort of 
    combined property (using the pattern "getAorB"), and the user must create an 
    JAXBElement and use this value to set the property.  It would be very 
    odd to have this structure reflected in the static SDO when it is missing 
    from the SDO metamodel.  In cases such as those where we create a 
    sequenced DataObject, JAXB creates an class with a single getContent() 
    method.  Static SDOs, like SDO itself, maintains in such cases a 
    property oriented view of the data in addition to the sequenced 
    view.

    
I hope this gets the discussion going so that we 
    can decide what sort of integration with JAXB we are aiming for, whether or 
    not we we need to define our own annotations, etc.  Blaise, as a member 
    of the JAXB EG, I'm particularly interested in your comments.

    
Best Regards, 
Ron
← Prev in month ← Prev in thread