Skip to main content

how to make property access the default for XJC generated code

2 replies [Last post]
bradfritz
Offline
Joined: 2005-02-04

Is there a way to make XJC generate code that uses property access
instead of field access by default?

The entities I am marshalling are lazily loaded with Hibernate and
CGLIB proxies. Using field access bypasses the proxy behavior.

After reading Kohsuke's blog article on field vs. property access[1],
I realize I can modify the generated files with
@XmlAccessorType(PROPERTY) or just move the @XmlElement annotations,
but many of the entities don't need other modifications, so it would
be convenient to control the default XJC behavior.

Any tips would be very much appreciated. I consulted all the JAXB 2.0
and XJC documentation I could find, but wasn't able to find any
answers on my own. Thanks.

--Brad

P.S. After migrating from the JAXB 1.0 RI to the 2.0 RI, I have to
say, excellent work! The 2.0 RI is *much* nicer to work with.

[1] http://weblogs.java.net/blog/kohsuke/archive/2005/03/should_jaxb_wor.html

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
kohsuke
Offline
Joined: 2003-06-09

I understand your frustration.

The problem is that getter/setter for properties don't always provide the same degree of the access fields provide.

For example, for a list property, there's only a getter, and no setter. Or when a property has a default value, the getter method returns the default value even if the actual value is absent.

I have been assuming that the point of using the getter/setter is to intercept the unmarshalling/marshalling. If the number of such interception is smaller and limited to a few properties, you might be able to manually move annotations.

Also, maybe you can use LifeCycleEvent callbacks to perform post-processing.

I'm not familiar with Hibernate or CGLIB proxies, so if you could explain that to me, that would be great.

BTW, it's good to know that you liked JAXB 2.0!

bradfritz
Offline
Joined: 2005-02-04

Thank you for replying so quickly. More inline...

> I understand your frustration.
>
> The problem is that getter/setter for properties don't always
> provide the same degree of the access fields provide.

That's understandable and I don't necessarily think the field access
default should be changed. (I'm not suggesting it should.) However,
it would be convenient if there was an XJC runtime option or extension
to change the placement of the annotations. The extension approach
would probably be better because it could more easily allow changing
the access type by class (xs:element or xs:complexType).

> For example, for a list property, there's only a getter, and no
> setter. Or when a property has a default value, the getter method
> returns the default value even if the actual value is absent.

I am only using JAXB for marshalling, not unmarshalling, so I hadn't
thought about the setters much. A bit off topic, but... I did have
to use wrappers, e.g.

void setFoos(List foos) {
getFoos().clear();
getFoos().addall(foos);
}

because I am using the generated classes with Spring's MVC framework.
Its DataBinder seems to require setters to work properly, at least by
default.

> I have been assuming that the point of using the getter/setter is to
> intercept the unmarshalling/marshalling. If the number of such
> interception is smaller and limited to a few properties, you might be
> able to manually move annotations.

This is what I have been doing so far. It works as expected, but
requires requires committing the slightly modified XJC-generated
code into version control. When the schema changes, it's also
necessary to manually re-sync the committed files instead of just
telling XJC to regenerate them.

> Also, maybe you can use LifeCycleEvent callbacks to perform
> post-processing.

I'm not familiar with LifeCycleEvent callbacks, so I will need to do
some more digging there. A quick search on google and the JAXB
project site didn't turn up any hits, so a pointer to any online
documentation would be much appreciated.

> I'm not familiar with Hibernate or CGLIB proxies, so if you could
> explain that to me, that would be great.

I'm no expert, but I can explain the basics for my use case...

Hibernate[1] loads persistent objects and object graphs from a
database. It allows "lazy loading"[2] to reduce database access
for associated objects. Consider the case of an Order object that has
many related LineItem objects. Both object types have corresponding
database tables with a one-to-many relationship. Order has a
getLineItems() method to return a List or Set of LineItems. Without
lazy loading, loading an Order from the database also loads the
associated LineItem objects. That's wasteful if you don't need access
to the line items.

Lazy loading provides a solution. Instead of returning an Order,
Hibernate returns a CGLIB subclass of Order. The lineItems List field
would be null initially. Calling getLineItems() in the CGLIB Order
subclass would cause a database lookup for the related line items,
populate the list field, and return it. The loading is lazy because
the line item lookup doesn't happen unless getLineItems() is called.

> BTW, it's good to know that you liked JAXB 2.0!

Thanks for working on it and for taking the time to field questions.

--Brad

[1] http://hibernate.org/
[2] http://www.hibernate.org/hib_docs/reference/en/html_single/#performance-...