Search code examples
javawsdlcxfprimary-keyhyperjaxb

How to set existing Id as primary key in HyperJaxb3 Cxf project, (code generation from wsdl)?


I am trying to redifine primary key to existing IDs, but with Apache CXF plugin generation from wsdl file. wsdl file is here - https://api.mindbodyonline.com/0_5/ClientService.asmx?wsdl

my pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>MindBodyCXF</groupId>
  <artifactId>CXFSpring</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>CXFSpring Maven Webapp</name>
  <url>http://maven.apache.org</url>
    <properties>
        <cxf.version>2.5.6</cxf.version>
        <hibernate-jpa-2.1-api.version>1.0.0.Final</hibernate-jpa-2.1-api.version>
        <hibernate-entitymanager.version>4.3.8.Final</hibernate-entitymanager.version>
        <hyperjaxb3-ejb.version>0.5.5</hyperjaxb3-ejb.version>
        <hsqldb.version>2.3.2</hsqldb.version>
        <hibernate.maven.plugin.version>2.2</hibernate.maven.plugin.version>
    </properties>
    <dependencies>
        <!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>3.0.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>3.0.1.RELEASE</version>
        </dependency>

        <!-- Apache CXF -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>${cxf.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-beans</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context</artifactId>
                </exclusion>

            </exclusions>

        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>${cxf.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-web</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-databinding-jaxb</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <!-- Hibernate -->
        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.1-api</artifactId>
            <version>${hibernate-jpa-2.1-api.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate-entitymanager.version}</version>
        </dependency>
        <!-- Hyperjaxb3 -->
        <dependency>
            <groupId>org.jvnet.hyperjaxb3</groupId>
            <artifactId>hyperjaxb3-ejb-runtime</artifactId>
            <version>${hyperjaxb3-ejb.version}</version>
        </dependency>
        <!-- HSQLDB -->
        <dependency>
            <groupId>org.hsqldb</groupId>
            <artifactId>hsqldb</artifactId>
            <version>${hsqldb.version}</version>
            <scope>runtime</scope>
        </dependency>

        <!--PostgresSQL-->
        <dependency>
            <groupId>postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>9.1-901.jdbc4</version>
        </dependency>
        <!-- Logging -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.6.1</version>
        </dependency>

        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.1</version>
            <exclusions>
                <exclusion>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>logkit</groupId>
                    <artifactId>logkit</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>avalon-framework</groupId>
                    <artifactId>avalon-framework</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>javax.servlet</groupId>
                    <artifactId>servlet-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- Testing -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.7</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>3.0.1.RELEASE</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hisrc.hifaces20</groupId>
            <artifactId>hifaces20-testing</artifactId>
            <version>0.1.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>1.1.0.Final</version>
        </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-core</artifactId>
            <version>3.0.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-rs-client</artifactId>
            <version>3.0.4</version>
        </dependency>
        <!--String processing-->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>18.0</version>
        </dependency>
        <dependency>
            <groupId>org.jadira.usertype</groupId>
            <artifactId>usertype.core</artifactId>
            <version>3.0.0.CR1</version>
        </dependency>
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.7</version>
        </dependency>


    </dependencies>
    <build>
        <finalName>MindBodyCXF</finalName>
        <plugins>
            <!--hibernate plugin for ddl creation-->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>hibernate3-maven-plugin</artifactId>
                <version>${hibernate.maven.plugin.version}</version>
                <executions>
                    <execution>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>hbm2ddl</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <components>
                        <component>
                            <name>hbm2ddl</name>
                            <implementation>jpaconfiguration</implementation>
                            <outputDirectory>src/main/resources/hbm2ddl</outputDirectory>
                        </component>
                    </components>
                    <componentProperties>
                        <persistenceunit>integration.mindbody</persistenceunit>
                        <propertyfile>src/test/resources/persistence.properties</propertyfile>
                        <outputfilename>schema.ddl</outputfilename>

                        <drop>true</drop>
                        <create>true</create>
                        <export>true</export>
                        <format>true</format>
                    </componentProperties>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>postgresql</groupId>
                        <artifactId>postgresql</artifactId>
                        <version>9.1-901.jdbc4</version>
                    </dependency>
                </dependencies>
            </plugin>

            <!--cxf plugin for wsdl 2 java-->
            <plugin>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-codegen-plugin</artifactId>
                <version>${cxf.version}</version>
                <executions>
                    <execution>
                        <id>generate-sources</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>wsdl2java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <sourceRoot>${project.build.sourceDirectory}</sourceRoot>
                   
                    <wsdlOptions>
                        <wsdlOption>
                           
                            <wsdl>${basedir}/src/main/wsdl/ClientService.xml</wsdl>

                           
                            <bindingFiles>
                                <!-- JAX-WS bindings -->
                                <bindingFile>${basedir}/src/main/wsdl/binding.xml</bindingFile>
                               
                            </bindingFiles>
                            <extraargs>
                                <!-- Turns on the hashCode plugin -->
                                <extraarg>-xjc-XhashCode</extraarg>
                                <!-- Turns on the equals plugin -->
                                <extraarg>-xjc-Xequals</extraarg>
                                <extraarg>-xjc-XtoString</extraarg>
                                <!-- Turns on the Hyperjaxb3 EJB plugin -->
                                <extraarg>-xjc-Xhyperjaxb3-ejb</extraarg>
                                <!--<extraarg>-xjc-Xinheritance</extraarg>-->
                                <extraarg>-xjc-XfixJAXB1058</extraarg>
                                <extraarg>-xjc-enableIntrospection</extraarg>
                                <extraarg>-impl</extraarg>
                                <!--<extraarg>-verbose</extraarg>-->

                            </extraargs>
                        </wsdlOption>
                    </wsdlOptions>

                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.jvnet.jaxb2_commons</groupId>
                        <artifactId>jaxb2-basics</artifactId>
                        <version>0.9.3</version>
                    </dependency>
                    <dependency>
                        <groupId>org.jvnet.hyperjaxb3</groupId>
                        <artifactId>hyperjaxb3-ejb-plugin</artifactId>
                        <version>${hyperjaxb3-ejb.version}</version>

                    </dependency>
                </dependencies>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
        </plugins>
        <!--to allow hbm generation-->
        <resources>
            <resource>
                <directory>src/main/wsdl</directory>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>META-INF/persistence.xml</include>
                </includes>
            </resource>
        </resources>
    </build>
</project>

My binding.xml is here -

<jaxws:bindings

        xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
        xmlns:s="http://www.w3.org/2001/XMLSchema"
        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
        xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
        xmlns:hj="http://hyperjaxb3.jvnet.org/ejb/schemas/customizations"
        xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
        jaxb:extensionBindingPrefixes="xjc hj orm"
        xmlns:test="urn:test">



    <jaxws:bindings node="wsdl:definitions/wsdl:types/s:schema" >
        <jaxb:globalBindings generateElementProperty="false" localScoping="toplevel" generateIsSetMethod="false" >
            <jaxb:javaType name="java.util.Date" xmlType="s:dateTime"
                           parseMethod="org.apache.cxf.tools.common.DataTypeAdapter.parseDateTime"
                           printMethod="org.apache.cxf.tools.common.DataTypeAdapter.printDateTime" />
            <jaxb:javaType name="java.util.Date" xmlType="s:date"
                           parseMethod="org.apache.cxf.tools.common.DataTypeAdapter.parseDate"
                           printMethod="org.apache.cxf.tools.common.DataTypeAdapter.printDate" />
            <jaxb:serializable uid="1"/>
        </jaxb:globalBindings>
        <jaxws:enableWrapperStyle>
            false
        </jaxws:enableWrapperStyle>
        <hj:persistence>
            <hj:default-one-to-many fetch="EAGER"/>

        </hj:persistence>

        <jaxb:bindings node="s:complexType/s:complexContent/s:extension/s:sequence/s:element[@name='Description']">
            <hj:basic>
                <orm:column length="2500"/>
            </hj:basic>
        </jaxb:bindings>
        <jaxb:bindings node="s:complexType/s:complexContent/s:extension/s:sequence/s:element[@name='Bio']">
            <hj:basic>
                <orm:column length="750"/>
            </hj:basic>
        </jaxb:bindings>
        <jaxb:bindings node="s:complexType/s:complexContent/s:extension/s:sequence/s:element[@name='ID']">
        <hj:id/>
    </jaxb:bindings>


    </jaxws:bindings>
</jaxws:bindings>

but chosen IDs wasn't converted to @Id.

How I can change my binding.xml to convert it?

Answer to Aleksei 1 comment:

I have added more general request to cover all needed IDs and validate all results through FindPath Mozilla Extension - only needed element was chosen `

<jaxb:bindings node="//s:element[@name='ID']">
            <hj:id/>
        </jaxb:bindings>

`

Classes was generated, but when I run 'mvn process-classes' I have received an error:

Caused by: org.hibernate.AnnotationException: Unable to define/override @Id(s) on a subclass: integration.mindbody.Appointment

I think It is thrown do to generated Hjid in ArrayOfAppointment and Id in Appointment;

ArrayOfAppointment.java: `

 @Id
    @Column(name = "HJID")
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getHjid() {
        return hjid;
    }

`

Appointment.java:
`

 @Id
    @Column(name = "ID", scale = 0)
    public Long getID() {
        return id;
    }

`

I have such annotations in several places:
` 

 @ManyToOne(targetEntity = SessionType.class, cascade = {
        CascadeType.ALL
    })
    @JoinColumns({
        @JoinColumn(name = "SESSIONTYPE_APPOINTMENT_ID"),
        @JoinColumn(name = "SESSIONTYPE_APPOINTMENT_HJID")
    })
    public SessionType getSessionType() {
        return sessionType;
    }

`

I think this is the reason of an exception.

All code is available here - [bitbucket repository][1] https://bitbucket.org/sergiishapoval/mindbodyintegrationtestproject/src/179b133cf3a730c718de329c694b311347e16984/?at=mindbodyPrototype 

full stack trace -

Execution default of goal org.codehaus.mojo:hibernate3-maven-plugin:2.2:hbm2ddl failed: [PersistenceUnit: integration.mindbody] Unable to c
onfigure EntityManagerFactory
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:224)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)
        at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
        at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:120)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:347)
        at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:154)
        at org.apache.maven.cli.MavenCli.execute(MavenCli.java:582)
        at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:214)
        at org.apache.maven.cli.MavenCli.main(MavenCli.java:158)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:483)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
        at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
        at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
Caused by: org.apache.maven.plugin.PluginExecutionException: Execution default of goal org.codehaus.mojo:hibernate3-maven-plugin:2.2:hbm2ddl failed: [Pe
rsistenceUnit: integration.mindbody] Unable to configure EntityManagerFactory
        at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:143)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
        ... 19 more
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: integration.mindbody] Unable to configure EntityManagerFactory
        at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:265)
        at org.codehaus.mojo.hibernate3.configuration.JPAComponentConfiguration.createConfiguration(JPAComponentConfiguration.java:28)
        at org.codehaus.mojo.hibernate3.configuration.AbstractComponentConfiguration.getConfiguration(AbstractComponentConfiguration.java:51)
        at org.codehaus.mojo.hibernate3.exporter.Hbm2DDLExporterMojo.doExecute(Hbm2DDLExporterMojo.java:87)
        at org.codehaus.mojo.hibernate3.HibernateExporterMojo.execute(HibernateExporterMojo.java:152)
        at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:132)
        ... 20 more
Caused by: org.hibernate.AnnotationException: Unable to define/override @Id(s) on a subclass: integration.mindbody.Appointment
        at org.hibernate.cfg.AnnotationBinder.bindId(AnnotationBinder.java:1860)
        at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1279)
        at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:754)
        at org.hibernate.cfg.AnnotationConfiguration.processArtifactsOfType(AnnotationConfiguration.java:546)
        at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:291)
        at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1148)
        at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1226)
        at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:173)
        at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:854)
        at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:191)
        at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:253)
        ... 25 more


Solution

  • This should actually work, here's one example from tests.

    Theories:

    • Customizations are not applied at all.
    • hj:id is applied to the wrong ID. You seem to have several elements matching the XPath expression. Try to be more specific i.e. add the name of the complex type to the XPath expression.
    • You have nillable="true". Maybe you get an additional wrapper property generated (ID may be a JAXBContext<Long> due to nillable). So you may actually need to customize the generated property. Here's an example.

    Seeing the generated code may give more hints, consider posting it.

    Disclosure: I'm the author of Hyperjaxb3.

    Update

    I've just got a successful mvn clean install.

    The problem is that your XPath //s:element[@name='ID'] selects several ID elements, not just one. It actually selects all the ID elements in the schema.

    This collides with complex types which inherit from other complex types (for instance, MBObject). Parent compex types already have ids (automatically generated) but your customization points to use the ID element as id anyway. This causes problems. Looks like HJ3 tries to generate a complex id (via @IdClass) but this fails in Hibernate.

    The fix is not to override id property in subclasses. This can be achieved in two ways:

    • Only customize ID elements in non-subclasses (in root classes).
    • Customize parent classes with hj:mapped-subclass.

    I've opted to the last solution and made MBObject and ScheduleItem mapped superclasses:

    https://github.com/highsource/hyperjaxb3-support/blob/master/m/MindBody/src/main/wsdl/binding.xml#L60-L65

    Thus classes like Appointment become (in JPA sense) root of the hierarchy and the id customization works correctly (mapped supperclasses do not have ids). So I get a successful build (database tests fail but don't break the build).