0

My coworkers lament my adherence to code generation, but I'm determined to prove this particular chain can be done. Examples below are simplified from my project (and thus untested as typed); I will create a test harness soon. Currently using hibernate 4.1.4, hibernate-spatial 1.1.1, hyperjaxb3-ejb-plugin 0.5.6.

I start off with a schema that uses a Position element whose type is a simple string extension:

  <xsd:simpleType name="wktPoint">
    <xsd:restriction base="xsd:string">
    </xsd:restriction>
  </xsd:simpleType>

I use bindings.xjb customizations to map my xmlType wktPoint to a JTS Point javaType using jaxb:javaType, since I will want to map the JTS Point field to a postgis geometry column:

<jaxb:javaType name="com.vividsolutions.jts.geom.Point" xmlType="wktPoint" parseMethod="test.Reader.readWKTPoint" printMethod="test.Writer.writeWKTPoint" />

Later in the bindings.xjb, I start customizing the Position element using annox:annotation:

<jaxb:bindings node="xsd:complexType[@name='MyType']//xsd:element[@name='Position']">
  <annox:annotate target="getter">
    <annox:annotate annox:class="javax.persistence.Basic"/>        
    <annox:annotate annox:class="javax.persistence.Column" name="POSITION" columnDefinition="GEOMETRY"/>
    <annox:annotate annox:class="org.hibernate.annotations.Type" type="org.hibernatespatial.GeometryUserType">
      <annox:annotate annox:field="parameters">
        <annox:annotate annox:class="org.hibernate.annotations.Parameter" name="dialect" value="postgis"/>
      </annox:annotate>
    </annox:annotate>
  </annox:annotate>      
</jaxb:bindings>

However, this produces the following getPosition method in MyType.java:

/**
 * Gets the value of the position property.
 * @return
 *     possible object is
 *     {@link String }
 */
@Transient
@Basic
@Column(columnDefinition = "GEOMETRY", name = "POSITION")
@Type(parameters = {
    @Parameter(name = "dialect", value = "postgis")
}, type = "org.hibernatespatial.GeometryUserType")
public Point getPosition() {
    return position;
}

So when I start up my application and jpa/hibernate starts initializing the tables, it skips the POSITION column altogether (since it got marked @Transient).

How can I prevent @Transient from showing up? It seems I need to convince Hyperjaxb that we will be able to write the JTS Point type directly to the database (that's what all the @Type stuff is about, signaling that we want hibernatespatial to use the postgis dialect when reading and writing Positions). Any ideas on how to do that?

  • I'm looking closer at hyperjaxb3, and I've found that my Position's FieldOutline is neither basic nor complex (and thus is marked @Transient) because of the jaxb:javaType customization. Since the customization succeeds, the FieldOutline's JType shows up as com.sun.codemodel.JDirectClass(Point) and so I remain stuck... – jesse crossley Jun 01 '12 at 06:57
  • 1
    Why are you messing around with xml to generate code? You should do it the other way around, annotate the code and you should be fine. – siebz0r Jun 02 '12 at 21:36
  • Ha! Sorry, siebz0r, but your argument has failed to sway me from my path :) The schemas here are part of a larger set of schema&wsdl, like most of the web services we implement. In my experience, it has proven far more interoperable and powerful to ensure that the control files are top notch...starting with bulletproof schema&wsdl enables others to implement clients to our services using any backing impl they choose (so long as their client speaks our schema fluently). Meanwhile, we get to generate the backbone of our service and write a very little glue code and we're on our way. Besides... – jesse crossley Jun 03 '12 at 05:48

1 Answers1

2

The 0.5.6 hyperjaxb-ejb-plugin just doesn't handle the binding customization properly. I built a 0.5.7-SNAPSHOT that modified the org.jvnet.hyperjaxb3.ejb.strategy.mapping AttributesMapping.getAttributeMapping() so that my customized jaxb binding would no longer be labelled Transient. I gave it the following fallback check:

if (isFieldOutlineBasic(fieldOutline)) {
    ...
} else if (isFieldOutlineComplex(fieldOutline)) {
    ...
} else {
    if (fieldOutline.getRawType() instanceof JClass) {
        return context.getBasicMapping();
    }
}

This covered my customization, which would always show up as a JDirectClass(Point). Once I made that change, the postgis tables were created with the correct geometry types, and I can now take in a WKT Point string, have it unmarshall as a JTS Point, and then persist it with JPA as a PostGIS geometry. I did also need to rebuild Hibernate Spatial (now using a 1.1.2-SNAPSHOT) to work with Hibernate4. I'll submit this work to Karel Maesen and I'll also submit the Hyperjaxb change to Aleksei Valikov and hopefully future versions will be that much more robust.

  • Cool that you got it. -- lexi Please send me the patch, I'll consider it for 0.5.7. Actually you just needed a way to turn off the @Transient annotation in a sense of "back off, I'll do it myself". I wonder if hj:ignore would work... – lexicore Jul 11 '12 at 14:38
  • Thanks for looking. I submitted the issue (and patch) here: http://jira.highsource.org/browse/HJIII-97 – jesse crossley Jul 19 '12 at 20:39