java - 如何创建采用 XML 并将一些数据绑定(bind)到 JPA 注释的 POJO 的 Camel 路由?

标签 java xml jpa jaxb apache-camel

我是 Apache Camel 和模拟测试的新手,所以这里是......

我有一个没有 XSD 架构的 XML,我对其没有影响。此 XML 的子元素包含我想绑定(bind)到我的业务 pojo 的数据。这个 POJO (WeatherCurrent) 已经带有 JPA 注释,我正在考虑添加 JAXB 注释,以便拆分的 XML 可以映射到我的 POJO。

因为这个 XML 有一个根元素,我只想要它的子元素 (metData),所以我无法使用 @XmlRootElement,因此无法注释我的 POJO。

此处部分描述:http://camel.apache.org/splitter.html使用 Tokenizer 语言流式处理大型 XML 负载一章。我的 POJO 就像那个例子中的 order xml 元素。我只需要 metData xml 元素中的几个元素来映射到我的 POJO 字段。

http://camel.apache.org/jaxb.html 也有一章部分编码/解码但是没有 JAVA DSL 示例(必须),也没有如何注释 pojo 以使用 XML 片段。

到目前为止我有这个测试代码:

import java.io.File;

import org.apache.camel.EndpointInject;
import org.apache.camel.Exchange;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.converter.jaxb.JaxbDataFormat;
import org.apache.camel.spi.DataFormat;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.junit.Test;

public class WeatherCurrentTest extends CamelTestSupport {

    @EndpointInject(uri = "file:src/test/resources")
    private ProducerTemplate inbox;

    @Override
    protected RouteBuilder createRouteBuilder() throws Exception {
        return new RouteBuilder() {
            @Override
            public void configure() throws Exception {
                DataFormat jaxbDataFormat = new JaxbDataFormat("com.mycompany.model.entities.weather");// WARNING two packages for JaxbDataFormat

                from("file:src/test/resources/?fileName=observation_si_latest.xml&noop=true&idempotent=false")
                .split()
                .tokenizeXML("metData")
                .unmarshal(jaxbDataFormat)
                .to("mock:meteo");          
            }
        };
    }

    @Test
    public void testMetData() throws Exception {
        MockEndpoint mock = getMockEndpoint("mock:meteo");
        mock.expectedMessageCount(9);

        File meteo = new File("src/test/resources/observation_si_latest.xml");
        String content = context.getTypeConverter().convertTo(String.class, meteo);
        inbox.sendBodyAndHeader(content, Exchange.FILE_NAME, "src/test/resources/observation_si_latest.xml");

        mock.assertIsSatisfied();
    }

}

XML (observation_si_latest.xml) 采用这种形式:

<?xml version="1.0" encoding="UTF-8"?>
<data id="MeteoSI_WebMet_observation_xml">
    <language>sl</language>
    <metData>
        <domain_altitude>55</domain_altitude>
        <domain_title>NOVA GORICA</domain_title>
        <domain_shortTitle>BILJE</domain_shortTitle>
        <tsValid_issued>09.03.2012 15:00 CET</tsValid_issued>
        <t_degreesC>15</t_degreesC>
    </metData>
    <metData>
        <domain_meteosiId>KREDA-ICA_</domain_meteosiId>

为简洁起见,我省略了 metData 元素的许多元素。我想将(除其他外)domain_title 映射到我的 JPA 注释 POJO 的站点字段,然后将其保存在数据库中,希望所有这些都在一条智能而短的 Camel route 。

POJO(还没有 JAXB 注释):

@Entity
@Table(name="weather_current")
public class WeatherCurrent implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;

    private String station;

    @Temporal( TemporalType.TIMESTAMP)
    @Column(name="successfully_updated")
    private Date successfullyUpdated;

    private short temperature;

    @Column(name="wind_direction")
    private String windDirection;

}

我还遗漏了很多字段和方法。

因此,我们的想法是将 *domain_title* 的值映射到 WeatherCurrent POJO 的 station 字段,并对每个 metData 元素执行此操作,并将 WeatherCurrent 对象列表保存到数据库。

欢迎就如何实现这一点的最佳方式提出任何建议。

最佳答案

事实证明,我有一个错误的假设,即无法使用@XmlRootElement。在我注释 POJO 并在其旁边添加 jaxb.in​​dex 文件后,路由和测试成功通过。稍后或明天会发布解决方案,因为我现在在火车上。

几小时后...

POJO 上的 JAXB 注释(在 JPA 之上):

@Entity
@Table(name="weather_current")
@XmlRootElement(name = "metData")
@XmlAccessorType(XmlAccessType.FIELD)
public class WeatherCurrent implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;

    @XmlElement(name = "nn_shortText")
    private String conditions;

    @XmlElement(name = "rh")
    private short humidity;

    @XmlElement(name = "msl")
    private short pressure;

    @Column(name="pressure_tendency")
    @XmlElement(name = "pa_shortText")
    private String pressureTendency;

    @Temporal( TemporalType.TIMESTAMP)
    @XmlElement(name = "tsValid_issued")
    private Date published;

    @XmlElement(name = "domain_longTitle")
    private String station;

使我能够获得 WeatherCurrent Exchage 对象的列表。只是为了测试,我将每个路由到我的 EchoBean 以打印出一个属性:

.unmarshal(jaxbDataFormat).bean(EchoBean.class, "printWeatherStation")

和 EchoBean:

public class EchoBean {

    public String printWeatherStation(WeatherCurrent weatherCurrent) {
        return weatherCurrent.getStation();
    }
}

用日志 Camel 组件很好地打印出气象站的名称。

困扰我的一件未记录的事情是我不得不将这个 jaxb.in​​dex 文件放在 WeatherCurrent java 源代码的下一个位置,尽管它位于 http://camel.apache.org/jaxb.html。它清楚地表明 jaxb 上下文是用

初始化的
DataFormat jaxb = new JaxbDataFormat("com.acme.model");

关于java - 如何创建采用 XML 并将一些数据绑定(bind)到 JPA 注释的 POJO 的 Camel 路由?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9702158/

相关文章:

r - 如何在 R 中的 XML 元素中保留换行符

java - JPA,从实体开始与数据库模式

Java Entity Bean 已定义但作为类对象传递

java - Android:如何让屏幕进入待机状态并保持接收到 BLE 通知

java - Spring TransactionSystemException 中的 Hibernate 验证结果

java - 在代码中创建场景大纲示例

java - Android中用ListView显示矩形框

java - 如何实现基于不同条件的集合过滤

xml - 如何使用 Alex 和 Happy 对电子邮件进行 Lex、解析和序列化为 XML

java - hibernate : Difference between @ Embedded annotation technique and @OneToOne annotation Technique