Search code examples
javaweb-serviceshibernatejaxbspring-ws

JAXB2 source generation


I have User entity with Hibernate and Validation annotations as below.

@Entity
@Table(name = "USER")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "User", propOrder = {
        "id",
        "login"
})
public class User {

    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.AUTO)
    @XmlElement(required = true, type = Long.class, nillable = true)
    private Long id;

    @Pattern(regexp = "^[a-zA-Z0-9_-]{3,20}$",
             message = "Login must contains from 3 to 20 latin characters or numbers!")
    @Column(name = "LOGIN", unique = true, nullable = false)
    @XmlElement(required = true)
    private String login;
}

When I write xsd schema with entity and getUserRequest / getUserResponse; maven-jaxb2-plugin generate GetUserRequest.java, GetUserResponse.java and User.java into package along with my User class (duplicate class if I try compile this).

<xs:complexType name="User">
    <xs:sequence>
        <xs:element name="id" type="xs:long" nillable="true"/>
        <xs:element name="login" type="xs:string"/>
    </xs:sequence>
</xs:complexType>

<xs:element name="getUserRequest">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="userId" type="xs:long"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

<xs:element name="getUserResponse">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="user" type="tns:User"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

I want to use my User class and not the generated one. (if I remove generated User and start application all works fine).

It's needed to my spring-ws ednpoint

@Endpoint
public class UserEndpoint {
    @Autowired
    private UserService userService;
    @ResponsePayload
    @PayloadRoot(namespace = SOAP_NAMESPACE, localPart = "getUserRequest")
    public GetUserResponse getUser(@RequestPayload GetUserRequest request) {
        springapp.domain.User user =
                userService.getUser(request.getUserId());
        GetUserResponse response = new GetUserResponse();
        response.setUser(toSchemaType(user));
        return response;
    }
    private springapp.schema.User toSchemaType(springapp.domain.User user) {
        springapp.schema.User schemaUser = new springapp.schema.User();
        if (user.getId() != null) {
            schemaUser.setId(user.getId());
        }
        schemaUser.setLogin(user.getLogin());
        return schemaUser;
    }
}

Thanks to lexicore. I have created domain.xjb:

<jxb:bindings version="1.0"
               xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
               xmlns:xs="http://www.w3.org/2001/XMLSchema"
               xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc">

    <jxb:bindings schemaLocation="users.xsd">
        <jxb:bindings node="//xs:complexType[@name='User']">
            <jxb:class ref="springapp.domain.User"/>
        </jxb:bindings>
    </jxb:bindings>

</jxb:bindings>

and added into maven-jaxb2-plugin configuration:

<bindingDirectory>src/main/resources</bindingDirectory>
<bindingIncludes>
    <include>domain.xjb</include>
</bindingIncludes>

And it works for me.


Solution

  • You can use jaxb:class/@ref binnding to tell XJC you already have a User class. See this question:

    JAXB: Prevent classes from being regenerated

    But I'd personally just write the two classes you need for the endpoint per hand and avoid the schema compilation altogether.