如何从 XSD 模式生成 JAXB 数据格式?
How to generate JAXB data format from XSD schema?
当我尝试使用 JAXB 并提供 XSD 模式编组从 Apache Camel 中的数据库获取的数据时,出现错误
java.io.org.apache.camel.NoTypeConversionAvailableException: No type converter available to convert from type: java.util.LinkedHashMap to the required type: java.io.InputStream with value {id=5, number=5599, type=B3, ... }
当我尝试将消息发送到 ActiveMQ 时。我是集成新手,这是我的实习骆驼项目。当我将消息编组到 json 时,一切正常。我考虑过将消息转换为 json,然后再转换为 XML,但在我看来这不是我应该做的。我已经准备好 XSD 架构,如下所示:
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:pc="com.release11.packages"
targetNamespace="com.release11.materials">
<xs:import schemaLocation="packages.xsd"
namespace="com.release11.packages"/>
<xs:simpleType name="materialTypeType">
<xs:restriction base="xs:string">
<xs:enumeration value="A1"/>
<xs:enumeration value="A2"/>
<xs:enumeration value="A3"/>
<xs:enumeration value="B1"/>
<xs:enumeration value="B2"/>
<xs:enumeration value="B3"/>
<xs:enumeration value="C1"/>
<xs:enumeration value="C2"/>
<xs:enumeration value="C3"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="materialType">
<xs:sequence>
<xs:element name="Id" type="xs:integer"/>
<xs:element name="Number" type="xs:integer"/>
<xs:element name="Type" type="materialTypeType"/>
<xs:element name="Name" type="xs:string"/>
<xs:element name="Description" type="xs:string"/>
<xs:element name="Is_deleted" type="xs:boolean"/>
<xs:element ref="pc:Packages" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="materialsType">
<xs:sequence>
<xs:element name="Material" type="materialType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="Materials" type="materialsType"/>
</xs:schema>
我试图在网上找到答案,但没有找到任何有用的答案,或者我无法理解答案,所以我需要有人向我解释一下。请帮助我。
这是我的代码:
public class InputAdapter {
public static void main(String[] args) throws Exception {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/Packages");
dataSource.setUsername("uname");
dataSource.setPassword("passwd");
SimpleRegistry registry = new SimpleRegistry();
registry.bind("dataSource", dataSource);
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory();
activeMQConnectionFactory.setBrokerURL("tcp://127.0.0.1:61616");
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("MESSAGES_RAW");
MessageProducer producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
CamelContext context = new DefaultCamelContext(registry);
context.addComponent("activemq", JmsComponent.jmsComponentAutoAcknowledge(activeMQConnectionFactory));
context.addRoutes(new RouteBuilder() {
@Override
public void configure() {
JaxbDataFormat dataFormat = new JaxbDataFormat();
dataFormat.setSchemaLocation("material.xsd");
from("timer://foo?repeatCount=1")
.setBody(constant("SELECT * FROM material;"))
.to("jdbc:dataSource")
.split(body())
.marshal(dataFormat)
.to("activemq:queue:MESSAGES_RAW");
}
});
context.start();
Thread.sleep(1000);
context.stop();
}
}
使用 CLI 工具从 XSD 生成 classes
你可以使用 pre-installed 附带的 xjc command-line 工具 JDK 8 来生成 jaxb classes.
示例:
xjc material.xsd
# With groupId
xjc -p <groupId> material.xsd
# With groupId and bindings configuration file
xjc -p <groupId> -b bindings.xjb material.xsd
使用 Maven 插件从 XSD 生成 classes
或者你可以使用 maven 插件来做同样的事情。默认情况下,插件将从 src/main/xsd
中查找模式 xsd 文件,并从 src/main/xjb
中查找绑定 xjb 文件
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>2.5.0</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<packageName>com.example.group</packageName>
</configuration>
</plugin>
</plugins>
</build>
如果您使用的是 JDK 11 或更高版本,您还必须包含一些不再包含在 JDK.
中的相关依赖项
<dependencies>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-xjc</artifactId>
<version>2.3.6</version>
</dependency>
</dependencies>
使用这些 Maven 应该在 运行 mvn clean install
之后生成 classes 到 target/generated-sources/jaxb
文件夹。使用 Maven 插件,您最好为这些创建单独的 api-project 并将其添加为您的骆驼集成项目的依赖项。
骆驼中的用法
您可以通过使用 JAXBContext 实例创建 JaxbDataFormat 来将 jaxb 与 camel 一起使用。
JAXBContext jaxbContext = JAXBContext.newInstance(Materials.class);
JaxbDataFormat jaxbDataformat = new JaxbDataFormat(jaxbContext);
from("direct:marshalMaterials")
.routeId("marshalMaterials")
.marshal(jaxbDataformat)
.log("${body}");
由于您要查询的数据库默认为 returns 地图列表,因此您必须将其转换为适当的 Jaxb 对象。您可以使用 generated ObjectFactory
class 来生成不同的 jaxb class 实例。
对于 JDK 11,您可能还需要以下依赖项
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>2.3.3</version>
</dependency>
<!-- versions obtained from dependency-management camel-bom -->
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
</dependency>
命名空间从 javax 更改为 jakarta
较新版本的 jaxb 使用 jakarta 命名空间而不是 javax 但是在撰写本文时使用 jakarta 命名空间有点问题,因为 jaxb2-maven-plugin 3.0.0+ 版本在 Maven 中央存储库中尚不可用,虽然有一些替代方案,但它们仍在进行中。
如果 xsd 不经常更改,则可能只生成 classes 并手动将命名空间更改为 jakarta。
绑定 XJB 文件
通过绑定 xjb 文件,您可以调整 classes 的生成方式,例如更改 class 或 属性 名称,防止嵌套 class 混乱等
示例:空绑定文件模板
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.1"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd">
...
</jaxb:bindings>
当我尝试使用 JAXB 并提供 XSD 模式编组从 Apache Camel 中的数据库获取的数据时,出现错误
java.io.org.apache.camel.NoTypeConversionAvailableException: No type converter available to convert from type: java.util.LinkedHashMap to the required type: java.io.InputStream with value {id=5, number=5599, type=B3, ... }
当我尝试将消息发送到 ActiveMQ 时。我是集成新手,这是我的实习骆驼项目。当我将消息编组到 json 时,一切正常。我考虑过将消息转换为 json,然后再转换为 XML,但在我看来这不是我应该做的。我已经准备好 XSD 架构,如下所示:
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:pc="com.release11.packages"
targetNamespace="com.release11.materials">
<xs:import schemaLocation="packages.xsd"
namespace="com.release11.packages"/>
<xs:simpleType name="materialTypeType">
<xs:restriction base="xs:string">
<xs:enumeration value="A1"/>
<xs:enumeration value="A2"/>
<xs:enumeration value="A3"/>
<xs:enumeration value="B1"/>
<xs:enumeration value="B2"/>
<xs:enumeration value="B3"/>
<xs:enumeration value="C1"/>
<xs:enumeration value="C2"/>
<xs:enumeration value="C3"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="materialType">
<xs:sequence>
<xs:element name="Id" type="xs:integer"/>
<xs:element name="Number" type="xs:integer"/>
<xs:element name="Type" type="materialTypeType"/>
<xs:element name="Name" type="xs:string"/>
<xs:element name="Description" type="xs:string"/>
<xs:element name="Is_deleted" type="xs:boolean"/>
<xs:element ref="pc:Packages" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="materialsType">
<xs:sequence>
<xs:element name="Material" type="materialType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="Materials" type="materialsType"/>
</xs:schema>
我试图在网上找到答案,但没有找到任何有用的答案,或者我无法理解答案,所以我需要有人向我解释一下。请帮助我。
这是我的代码:
public class InputAdapter {
public static void main(String[] args) throws Exception {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/Packages");
dataSource.setUsername("uname");
dataSource.setPassword("passwd");
SimpleRegistry registry = new SimpleRegistry();
registry.bind("dataSource", dataSource);
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory();
activeMQConnectionFactory.setBrokerURL("tcp://127.0.0.1:61616");
Connection connection = activeMQConnectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("MESSAGES_RAW");
MessageProducer producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
CamelContext context = new DefaultCamelContext(registry);
context.addComponent("activemq", JmsComponent.jmsComponentAutoAcknowledge(activeMQConnectionFactory));
context.addRoutes(new RouteBuilder() {
@Override
public void configure() {
JaxbDataFormat dataFormat = new JaxbDataFormat();
dataFormat.setSchemaLocation("material.xsd");
from("timer://foo?repeatCount=1")
.setBody(constant("SELECT * FROM material;"))
.to("jdbc:dataSource")
.split(body())
.marshal(dataFormat)
.to("activemq:queue:MESSAGES_RAW");
}
});
context.start();
Thread.sleep(1000);
context.stop();
}
}
使用 CLI 工具从 XSD 生成 classes
你可以使用 pre-installed 附带的 xjc command-line 工具 JDK 8 来生成 jaxb classes.
示例:
xjc material.xsd
# With groupId
xjc -p <groupId> material.xsd
# With groupId and bindings configuration file
xjc -p <groupId> -b bindings.xjb material.xsd
使用 Maven 插件从 XSD 生成 classes
或者你可以使用 maven 插件来做同样的事情。默认情况下,插件将从 src/main/xsd
中查找模式 xsd 文件,并从 src/main/xjb
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>2.5.0</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<packageName>com.example.group</packageName>
</configuration>
</plugin>
</plugins>
</build>
如果您使用的是 JDK 11 或更高版本,您还必须包含一些不再包含在 JDK.
中的相关依赖项<dependencies>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-xjc</artifactId>
<version>2.3.6</version>
</dependency>
</dependencies>
使用这些 Maven 应该在 运行 mvn clean install
之后生成 classes 到 target/generated-sources/jaxb
文件夹。使用 Maven 插件,您最好为这些创建单独的 api-project 并将其添加为您的骆驼集成项目的依赖项。
骆驼中的用法
您可以通过使用 JAXBContext 实例创建 JaxbDataFormat 来将 jaxb 与 camel 一起使用。
JAXBContext jaxbContext = JAXBContext.newInstance(Materials.class);
JaxbDataFormat jaxbDataformat = new JaxbDataFormat(jaxbContext);
from("direct:marshalMaterials")
.routeId("marshalMaterials")
.marshal(jaxbDataformat)
.log("${body}");
由于您要查询的数据库默认为 returns 地图列表,因此您必须将其转换为适当的 Jaxb 对象。您可以使用 generated ObjectFactory
class 来生成不同的 jaxb class 实例。
对于 JDK 11,您可能还需要以下依赖项
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>2.3.3</version>
</dependency>
<!-- versions obtained from dependency-management camel-bom -->
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
</dependency>
命名空间从 javax 更改为 jakarta
较新版本的 jaxb 使用 jakarta 命名空间而不是 javax 但是在撰写本文时使用 jakarta 命名空间有点问题,因为 jaxb2-maven-plugin 3.0.0+ 版本在 Maven 中央存储库中尚不可用,虽然有一些替代方案,但它们仍在进行中。
如果 xsd 不经常更改,则可能只生成 classes 并手动将命名空间更改为 jakarta。
绑定 XJB 文件
通过绑定 xjb 文件,您可以调整 classes 的生成方式,例如更改 class 或 属性 名称,防止嵌套 class 混乱等
示例:空绑定文件模板
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.1"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd">
...
</jaxb:bindings>