bbc*_*per 8 java xml jpa jaxb apache-camel
我是Apache Camel和模拟测试的新手,所以在这里......
我有一个没有XSD架构的XML,我没有影响.此XML的子元素包含我想要绑定到我的业务pojo的数据.这个POJO(WeatherCurrent)已经注释了JPA,我正在考虑添加JAXB注释,因此可以将拆分的XML映射到我的POJO.
由于这个XML有一个根元素,我只想要它的子元素(metData),我有一个问题如何注释我的POJO因为我不能使用@XmlRootElement.
这部分描述如下:http://camel.apache.org/splitter.html 使用Tokenizer语言章节在Streaming大XML有效负载上.我的POJO就像那个例子中的order xml元素.我只需要metData xml元素中的一些元素来映射到我的POJO字段.
在http://camel.apache.org/jaxb.html上还有一章Partial marshalling/unmarshalling,但没有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();
}
}
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
为简洁起见,我遗漏了许多metData元素的元素.我想将(除其他人之外)domain_title映射到我的JPA注释POJO的站点字段,然后保存它数据库,希望所有这些都在一个智能和短的Camel路由中.
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;
}
Run Code Online (Sandbox Code Playgroud)
我也遗漏了很多领域和方法.
因此,我们的想法是将*domain_title*的值映射到WeatherCurrent POJO的站点字段,并为每个metData元素执行此操作,并将WeatherCurrent对象列表保存到数据库.
关于如何实现这一点的最佳方式的任何建议都是受欢迎的.
事实证明,我有一个错误的假设,即无法使用 @XmlRootElement。在我注释 POJO 并在其旁边添加 jaxb.index 文件后,路由和测试成功通过。稍后或明天发布解决方案,因为我现在在火车上。
几个小时以后...
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;
Run Code Online (Sandbox Code Playgroud)
使我能够获取 WeatherCurrent Exchange 对象的列表。为了进行测试,我将每一个路由到我的 EchoBean 以打印出一个属性:
.unmarshal(jaxbDataFormat).bean(EchoBean.class, "printWeatherStation")
Run Code Online (Sandbox Code Playgroud)
和 EchoBean:
public class EchoBean {
public String printWeatherStation(WeatherCurrent weatherCurrent) {
return weatherCurrent.getStation();
}
}
Run Code Online (Sandbox Code Playgroud)
使用 log Camel 组件很好地打印出气象站的名称。
困扰我的一件未记录的事情是我必须将此 jaxb.index 文件放在 WeatherCurrent java 源下,尽管在http://camel.apache.org/jaxb.html上它清楚地表明 jaxb 上下文是用
DataFormat jaxb = new JaxbDataFormat("com.acme.model");
Run Code Online (Sandbox Code Playgroud)