2017-10-21 258 views
1

我有用于并行读取员工,地址和联系人文件的用例,并将其转换为beanIO对象并合并beanIO对象以生成完整的employeeDetails对象。Apache Camel:文件到BeanIO并基于ID合并beanIO对象

的Emp文件:

1 Foo Engineer 
2 Bar AssistantEngineer 

的Emp联系人文件:

1 8912345678 [email protected] 
2 7812345678 [email protected] 

的Emp地址文件:

1 city1 1234 
2 city2 2345 
在EmployeeDetailsBeanIODataFormat对象

预计产量在Exchange:

1 Foo Engineer [email protected] city1 1234 
2 Bar AssistantEngineer [email protected] city2 2345 

我有以下路线

from("file://C:/cameltest/employee.txt").to("seda:beanIO"); 
from("file://C:/cameltest/employeeContact.txt").to("seda:beanIOContact"); 
from("file://C:/cameltest/employeeAddress.txt").to("seda:beanIOAddress"); 

每个文件被转换为beanio对象

BeanIODataFormat empFormat = new BeanIODataFormat("beanIO.xml","emp"); 
BeanIODataFormat empContactFormat = new BeanIODataFormat("beanIO.xml", "empContact"); 
BeanIODataFormat empAddressFormat = new BeanIODataFormat("beanIO.xml", "empAddress"); 

from("seda:beanIO").unmarshal(empFormat).log("body - ${body}");   
from("seda:beanIOContact").unmarshal(empContactFormat).log("Contact body ${body}"); 
from("seda:beanIO").unmarshal(empAddressFormat).log("Address body - ${body}");  

输出记录该豆正确的对象。

现在我需要合并对象来形成EmployeeDetails对象。有人可以让我知道如何做到这一点?我已经阅读过,似乎可以使用Aggregators来完成这项工作,但不确定这种方法。

任何有关此示例的想法都会有所帮助。 欢迎提出建议,建议首先根据员工ID合并文件并创建一个对象?在这种情况下,我不想将合并的文件写入磁盘,因为IO会降低性能。

在此先感谢。

回答

1

使用分离器的解组

from("seda:beanIO").unmarshal(empFormat).split(body()).to("seda:aggregate"); 
from("seda:beanIOContact").unmarshal(empContactFormat).split(body()).to("seda:aggregate"); 
from("seda:beanIOAddress").unmarshal(empAddressFormat).split(body()).to("seda:aggregate"); 

后,每封邮件进行分割,然后在这里是一个聚合如何能够样子。 细节对象作为标题存储在olddExchange中。 最重要的参数是以下

  1. correlationExpression:简单( “$ {body.id}”)关联的所有具有相同id的消息(1或2)
  2. completionSize = 3。每个文件一个。 。

    从( “SEDA:总”)骨料(简单( “$ {} body.id”),(oldExchange,newExchange) - > {

    if (oldExchange == null) { 
         EmployeeDetails details = buildDetails(new EmployeeDetails(), newExchange); 
         newExchange.getIn().setHeader("details", details); 
         return newExchange; 
        } 
        EmployeeDetails details = oldExchange.getIn().getHeader("details", EmployeeDetails.class); 
        buildDetails(details, newExchange); 
        oldExchange.getIn().setHeader("details", details); 
        return oldExchange; 
    }).completionSize(3).log("Details - ${header.details}") 
    

而且

private EmployeeDetails buildDetails(EmployeeDetails details, Exchange newExchange) { 
     Object newBody = newExchange.getIn().getBody(); 
     if (newBody instanceof Employee) { 
      details.setId(((Employee) newBody).getId()); 
      details.setName(((Employee) newBody).getName()); 
      details.setJob(((Employee) newBody).getJob()); 
     } else if (newBody instanceof EmployeeContact) { 
      details.setEmail(((EmployeeContact) newBody).getEmail()); 
     } else if (newBody instanceof EmployeeAddress) { 
      details.setCity(((EmployeeAddress) newBody).getCity()); 
      details.setCode(((EmployeeAddress) newBody).getCode()); 
     } 
     return details; 
    } 

那么结果将是2个细节对象

Details - EmployeeDetails(id=1, name=Foo, job=Engineer, [email protected], city=city1, code=1234) 
Details - EmployeeDetails(id=2, name=Bar, job=AssistantEnginee, [email protected], city=city2, code=2345) 
+0

感谢为了答复,我会试试这个,让你知道。 – jack

+0

它工作正常,但EmployeeDetails逐一打印。但是我需要在Exchange主体中最终输出一个EmployeeDetails [],所以我可以在下一个路径上传递它以处理最终列表并将其转换为Avro格式。它是否需要再次聚合? ...... completionSize(3).to(“seda”formList“)会像这样工作,或者有其他选项来组合所有消息。 – jack

+0

您可以再次聚合(虽然这是一个不同的问题)。 setBody(header(“details”))。aggregate(new GroupedExchangeAggregationStrategy())。constant(true).complet ionSize(2)其中2是ids的数量 – ltsallas