无法使用Apache Camel Bindy向文件添加页眉和页脚。

huangapple go评论72阅读模式
英文:

Unable to add header and footer to the file using Apache Camel Bindy

问题

@Component
public class EmployeePackageRoute extends RouteBuilder {

    @Autowired
    private Header header;

    private Trailer footer;

    @SuppressWarnings("deprecation")
    @Override
    public final void configure() {
        System.out.println("fetching employee details from employee api");
        try {

            from("jetty://http://localhost:8084/employee-package/getEmployee")
                .unmarshal().json(JsonLibrary.Jackson, RecurringPaymentResults.class)
                .process(
                    ex -> {
                        System.out.println("+++++++++++++++++ " + ex.getIn().getBody());
                        RecurringPaymentResults result = ex.getIn().getBody(RecurringPaymentResults.class);
                        List<RecurringPaymentsDeduct> employee = result.getResults();
                        ex.getOut().setBody(employee);
                        System.out.println("**** Header ** " + header);
                    })
                .to("seda:employeeFeed");

            final DataFormat bindy = new BindyFixedLengthDataFormat(RecurringPaymentsDeduct.class);

            footer = new Trailer("TRAILER", 3);

            Map<String, Object> headerObjMap = new HashMap<String, Object>();
            headerObjMap.put(Header.class.getName(), header);

            Map<String, Object> footerObjMap = new HashMap<String, Object>();
            footerObjMap.put(Trailer.class.getName(), footer);

            from("seda:employeeFeed")
                .log("process csv")
                .marshal(bindy)
                .log("csv processed")
                .process(
                    ex -> {
                        System.out.println("******************** " + ex.getIn().getBody());

                        //ex.getOut().setHeader("header", header);
                        ex.getOut().setHeader(BindyFixedLengthDataFormat.CAMEL_BINDY_FIXED_LENGTH_HEADER, headerObjMap);
                        ex.getOut().setBody(ex.getIn().getBody());
                        ex.getOut().setHeader(BindyFixedLengthDataFormat.CAMEL_BINDY_FIXED_LENGTH_FOOTER, footerObjMap);

                    }).to("file://C:\\Users\\testfolder?fileName=test.txt")
                .end();

        } catch (Exception e) {
            System.out.println("Error occurred while processing employee data: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

@Data
@Section(number = 2)
@FixedLengthRecord(header = Header.class, footer = Trailer.class)
public class RecurringPaymentsDeduct implements Serializable {

    private static final long serialVersionUID = 1L;

    @DataField(pos = 1, length = 10)
    public String RECTY;

    // Other fields...

}

@Configuration
@EnableConfigurationProperties
@ConfigurationProperties("test")
@Data
@Section(number = 1)
@FixedLengthRecord()
public class Header implements Serializable {

    private static final long serialVersionUID = 1L;

    @DataField(pos = 1, length = 5)
    private String header1;

    // Other fields...

}

@Section(number = 3)
@FixedLengthRecord
public class Trailer implements Serializable {

    private static final long serialVersionUID = 1L;

    @DataField(pos = 1, length = 7)
    private String trailer;

    // Other fields...
}
英文:

I am trying to create a file with header and footer record along with json payload as body.
Header and footer property values will be dynamic based on the timestamp and total number of records
(At the moment I am planning to achieve with static values from properties).
I am using FixedLengthDataFormat to achieve this.
However header and footer records are not being added to the file, the file only has json payload as body.
Can someone help me to achieve this?

I have copied all the class files below.

@Component
public class EmployeePackageRoute extends RouteBuilder {
@Autowired
private Header header;
private Trailer footer;
@SuppressWarnings(&quot;deprecation&quot;)
@Override
public final void configure() {
System.out.println(&quot;fetching employee details from employee api&quot;);
try {
from(&quot;jetty://http://localhost:8084/employee-package/getEmployee&quot;)
.unmarshal().json(JsonLibrary.Jackson, RecurringPaymentResults.class)
.process(
ex -&gt; {
System.out.println(&quot;+++++++++++++++++ &quot;+ex.getIn().getBody());
RecurringPaymentResults result = ex.getIn().getBody(RecurringPaymentResults.class);
List&lt;RecurringPaymentsDeduct&gt; employee = result.getResults();
ex.getOut().setBody(employee);
System.out.println(&quot;**** Header ** &quot;+header);
})
.to(&quot;seda:employeeFeed&quot;);
final DataFormat bindy = new BindyFixedLengthDataFormat(RecurringPaymentsDeduct.class);
footer = new Trailer(&quot;TRAILER&quot;,3);
Map&lt;String, Object&gt; headerObjMap = new HashMap&lt;String,Object&gt;();
headerObjMap.put(Header.class.getName(), header);
Map&lt;String, Object&gt; footerObjMap = new HashMap&lt;String,Object&gt;();
footerObjMap.put(Trailer.class.getName(), footer);
from(&quot;seda:employeeFeed&quot;)
.log(&quot;process csv&quot;)
.marshal(bindy)
.log(&quot;csv processed&quot;)
.process(
ex -&gt; {
System.out.println(&quot;******************** &quot;+ex.getIn().getBody());
//ex.getOut().setHeader(&quot;header&quot;, header);
ex.getOut().setHeader(BindyFixedLengthDataFormat.CAMEL_BINDY_FIXED_LENGTH_HEADER, headerObjMap);
ex.getOut().setBody(ex.getIn().getBody());
ex.getOut().setHeader(BindyFixedLengthDataFormat.CAMEL_BINDY_FIXED_LENGTH_FOOTER, footerObjMap);
}).to(&quot;file://C:\Users\testfolder?fileName=test.txt&quot;)
.end();
} catch(Exception e) {
System.out.println(&quot;Error occurred while processing employee data: &quot;+e.getMessage());
e.printStackTrace();
}
}
}
@Data
@Section(number = 2)
@FixedLengthRecord(header = Header.class, footer = Trailer.class)
public class RecurringPaymentsDeduct implements Serializable {
private static final long serialVersionUID = 1L;
@DataField(pos = 1, length = 10)
public String RECTY;
@DataField(pos = 2, length = 10)
public String CLIID;
@DataField(pos = 3, length = 10)
public String INTCA;
@DataField(pos = 4, length = 10)
public String ORDNO;
@DataField(pos = 5, length = 10)
public String IOPER;
@DataField(pos = 6, length = 10)
public String INFTY;
@DataField(pos = 7, length = 10)
public String SUBTY;
@DataField(pos = 8, length = 10)
public String BEGDA;
@DataField(pos = 9, length = 10)
public String ENDDA;
@DataField(pos = 10, length = 10)
public String OBJPS;
}
@Configuration
@EnableConfigurationProperties
@ConfigurationProperties(&quot;test&quot;)
@Data
@Section(number = 1)
@FixedLengthRecord()
public class Header implements Serializable {
private static final long serialVersionUID = 1L;
@DataField(pos = 1, length = 5)
private String header1;
@DataField(pos = 2, length = 5)
private String header2;
@DataField(pos = 3, length = 15)
private String header3;
@DataField(pos = 4, length = 60)
private String header4;
@DataField(pos = 5, length = 15)
private String header5;
@DataField(pos = 6, length = 30)
private String header6;
@DataField(pos = 7, length = 30)
private String header7;
@DataField(pos = 8, length =  8, pattern = &quot;YYYYMMDD&quot;)
private String header8;
@DataField(pos = 9, length = 6)
private String header9;
@DataField(pos = 10, length = 1)
private String header10;
@DataField(pos = 11, length = 2)
private String header11;
@DataField(pos = 12, length = 10)
private String header12;
@DataField(pos = 13, length = 10)
private String header13;
@DataField(pos = 14, length = 10)
private String header14;
}
@Section(number = 3)
@FixedLengthRecord
public class Trailer implements Serializable {
private static final long serialVersionUID = 1L;
@DataField(pos = 1, length = 7)
private String trailer;
@DataField(pos = 2, length = 2)
private int count;
public String getTrailer() {
return trailer;
}
public void setTrailer(String trailer) {
this.trailer = trailer;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}

答案1

得分: 1

I found the answer. 
This solution had fixed many issues that I had in various stage. 

Issue 1) 使用 BindyFixedLengthDataFormat 向平面文件添加动态头部和尾部正如名称所示它是固定长度的我必须分配最大长度并在生成正文后修剪空白字符。(我可能仍需要使用不同的类或方式来修剪空白字符)。

Issue 2) 我有将管道分隔符替换为 |&quot; 的要求

Issue 3) 不使用 jetty 暴露硬编码的端点 URL而是使用 rest 配置这样主机名将不再是硬编码的并且您可以部署到任何环境

@Component
public class EmployeePackageRoute extends RouteBuilder {
    
    @Autowired
    private Header header;
    
    private Trailer footer;
    
    private String file_name;
    
    @SuppressWarnings("deprecation")
    @Override
    public final void configure() {
        
        System.out.println("fetching employee details from employee api");
        
        final SimpleDateFormat TARGET_DATE_FORMAT = new SimpleDateFormat("YYYYMMDDHHMMSS");
        String date = TARGET_DATE_FORMAT.format(new Date());
        
        String year = date.substring(0, 8);
        String hr = date.substring(9, 13);
        
        try {
            restConfiguration().component("jetty").port(8000).bindingMode(RestBindingMode.json);
            rest("/api/test/getTestResponse")
            .get().consumes(MediaType.APPLICATION_JSON_VALUE).route().setBody().constant("return test response");
            
            rest("/api/bcr/recurringPaymentsDeduct")
            .post().consumes(MediaType.APPLICATION_JSON_VALUE).type(RecurringPaymentResults.class).outType(ResponseEntity.class).route()
            .process(
                    ex -> {
                        
                        RecurringPaymentResults result = ex.getIn().getBody(RecurringPaymentResults.class);
                        List<RecurringPaymentsDeduct> employee = result.getResults();
                        file_name = Constants.FILE_NUMBER_DEV+"_"+date+"_"+Constants.AUMBCR_HRMD+result.getSequenceNumber()+"_"+Constants.DUT8G2I+".SAP";
                        header.setHeader7(Constants.FILE_NUMBER_DEV+"_"+date+"_"+Constants.AUMBCR_HRMD+result.getSequenceNumber()+"_"+Constants.DUT8G2I+".SAP");
                        
                        header.setHeader8(year);
                        header.setHeader9(hr);
                        header.setHeader10(Constants.ENVIRONMENT);
                        
                        footer = new Footer("Footer",(employee.size()+2));
                        
                        ex.getOut().setBody(employee);
                    })
            .to("seda:recurringPaymentsFeed");
            
            final DataFormat recurringPaymentsBindy = new BindyFixedLengthDataFormat(RecurringPaymentsDeduct.class);
            
            from("seda:recurringPaymentsFeed")
            .startupOrder(2)
            .log("add footer to the file")
            .process(
                    ex -> {
                        
                        Map<String, Object> headerObjMap = new HashMap<String,Object>();
                        headerObjMap.put(Header.class.getName(), header);
                        System.out.println(" *** file_name 1 - "+file_name);
                        Map<String, Object> footerObjMap = new HashMap<String,Object>();
                        footerObjMap.put(Footer.class.getName(), footer);
                        
                        ex.getOut().setHeader(BindyFixedLengthDataFormat.CAMEL_BINDY_FIXED_LENGTH_HEADER, headerObjMap);
                        ex.getOut().setBody(ex.getIn().getBody());
                        ex.getOut().setHeader(BindyFixedLengthDataFormat.CAMEL_BINDY_FIXED_LENGTH_FOOTER, footerObjMap);
                        
                    })
            .marshal(recurringPaymentsBindy)
            .convertBodyTo(byte[].class, "iso-8859-1")
            .setBody(body().regexReplaceAll("\\|", "\\|&quot;"))
            .log("csv processed")
            .to("file://app/bcr-files?fileName=recurringPaymentsDeduct.SAP")
            .end();
            
        } catch(Exception e) {
            System.out.println("Error occurred while processing employee data: "+e.getMessage());
            e.printStackTrace();
        }
    }
}

@Data
@Section(number = 2)
@FixedLengthRecord(header = Header.class, footer = Trailer.class)
public class RecurringPaymentsDeduct implements Serializable {

    private static final long serialVersionUID = 1L;
    
    @DataField(pos = 1, length = 10, delimiter = "|", trim = true)
    public String RECTY;
    
    @DataField(pos = 2, length = 10, delimiter = "|", trim = true)
    public String CLIID;

    // Other fields...

}

@Configuration
@EnableConfigurationProperties
@ConfigurationProperties("adp")
@Data
@Section(number = 1)
@FixedLengthRecord()
public class Header implements Serializable {

    private static final long serialVersionUID = 1L;

    @DataField(pos = 1, length = 5, delimiter = "|", trim = true)
    private String header1;
    
    // Other fields...

}

@Data
@Section(number = 3)
@FixedLengthRecord()
public class Footer implements Serializable {

    private static final long serialVersionUID = 1L;

    @DataField(pos = 1, length = 7, delimiter = "|", trim = true)
    private String trailer;

    // Other fields...

}
英文:

I found the answer.
This solution had fixed many issues that I had in various stage.

Issue 1) Added dynamic header and footer to the flat file using BindyFixedLengthDataFormat. As the name suggests it's fixed length. I had to assign maximum length and trim the whitespaces after generating the body. (I still may need to use different class or way to trim the whitespaces).

Issue 2) I had the requirement to replace the pipe delimiter with |".

Issue 3) Instead of using jetty to expose the end point url which will be hard coded I have used rest configuration so that hostname will no longer be hard coded and you can deploy to any environment.

    @Component
public class EmployeePackageRoute extends RouteBuilder {
@Autowired
private Header header;
private Trailer footer;
private String file_name;
@SuppressWarnings(&quot;deprecation&quot;)
@Override
public final void configure() {
System.out.println(&quot;fetching employee details from employee api&quot;);
final SimpleDateFormat TARGET_DATE_FORMAT = new SimpleDateFormat(&quot;YYYYMMDDHHMMSS&quot;);
String date = TARGET_DATE_FORMAT.format(new Date());
String year = date.substring(0, 8);
String hr = date.substring(9, 13);
try {
restConfiguration().component(&quot;jetty&quot;).port(8000).bindingMode(RestBindingMode.json);
rest(&quot;/api/test/getTestResponse&quot;)
.get().consumes(MediaType.APPLICATION_JSON_VALUE).route().setBody().constant(&quot;return test response&quot;);
rest(&quot;/api/bcr/recurringPaymentsDeduct&quot;)
.post().consumes(MediaType.APPLICATION_JSON_VALUE).type(RecurringPaymentResults.class).outType(ResponseEntity.class).route()
.process(
ex -&gt; {
RecurringPaymentResults result = ex.getIn().getBody(RecurringPaymentResults.class);
List&lt;RecurringPaymentsDeduct&gt; employee = result.getResults();
file_name = Constants.FILE_NUMBER_DEV+&quot;_&quot;+date+&quot;_&quot;+Constants.AUMBCR_HRMD+result.getSequenceNumber()+&quot;_&quot;+Constants.DUT8G2I+&quot;.SAP&quot;;
header.setHeader7(Constants.FILE_NUMBER_DEV+&quot;_&quot;+date+&quot;_&quot;+Constants.AUMBCR_HRMD+result.getSequenceNumber()+&quot;_&quot;+Constants.DUT8G2I+&quot;.SAP&quot;);
header.setHeader8(year);
header.setHeader9(hr);
header.setHeader10(Constants.ENVIRONMENT);
footer = new Footer(&quot;Footer&quot;,(employee.size()+2));
ex.getOut().setBody(employee);
})
.to(&quot;seda:recurringPaymentsFeed&quot;);
final DataFormat recurringPaymentsBindy = new BindyFixedLengthDataFormat(RecurringPaymentsDeduct.class);
from(&quot;seda:recurringPaymentsFeed&quot;)
.startupOrder(2)
.log(&quot;add footer to the file&quot;)
.process(
ex -&gt; {
Map&lt;String, Object&gt; headerObjMap = new HashMap&lt;String,Object&gt;();
headerObjMap.put(Header.class.getName(), header);
System.out.println(&quot; *** file_name 1 - &quot;+file_name);
Map&lt;String, Object&gt; footerObjMap = new HashMap&lt;String,Object&gt;();
footerObjMap.put(Footer.class.getName(), footer);
ex.getOut().setHeader(BindyFixedLengthDataFormat.CAMEL_BINDY_FIXED_LENGTH_HEADER, headerObjMap);
ex.getOut().setBody(ex.getIn().getBody());
ex.getOut().setHeader(BindyFixedLengthDataFormat.CAMEL_BINDY_FIXED_LENGTH_FOOTER, footerObjMap);
})
.marshal(recurringPaymentsBindy)
.convertBodyTo(byte[].class, &quot;iso-8859-1&quot;)
.setBody(body().regexReplaceAll(&quot;\\|&quot;, &quot;\\|\&quot;&quot;))
.log(&quot;csv processed&quot;)
.to(&quot;file://app/bcr-files?fileName=recurringPaymentsDeduct.SAP&quot;)
.end();
} catch(Exception e) {
System.out.println(&quot;Error occurred while processing employee data: &quot;+e.getMessage());
e.printStackTrace();
}
}
}
@Data
@Section(number = 2)
@FixedLengthRecord(header = Header.class, footer = Trailer.class)
public class RecurringPaymentsDeduct implements Serializable {
private static final long serialVersionUID = 1L;
@DataField(pos = 1, length = 10, delimiter = &quot;|&quot;, trim = true)
public String RECTY;
@DataField(pos = 2, length = 10, delimiter = &quot;|&quot;, trim = true)
public String CLIID;
@DataField(pos = 3, length = 10, delimiter = &quot;|&quot;, trim = true)
public String INTCA;
@DataField(pos = 4, length = 10, delimiter = &quot;|&quot;, trim = true)
public String ORDNO;
@DataField(pos = 5, length = 10, delimiter = &quot;|&quot;, trim = true)
public String IOPER;
@DataField(pos = 6, length = 10, delimiter = &quot;|&quot;, trim = true)
public String INFTY;
@DataField(pos = 7, length = 10, delimiter = &quot;|&quot;, trim = true)
public String SUBTY;
@DataField(pos = 8, length = 10, delimiter = &quot;|&quot;, trim = true)
public String BEGDA;
@DataField(pos = 9, length = 10, delimiter = &quot;|&quot;, trim = true)
public String ENDDA;
@DataField(pos = 10, length = 10, trim = true)
public String OBJPS;
}
@Configuration
@EnableConfigurationProperties
@ConfigurationProperties(&quot;adp&quot;)
@Data
@Section(number = 1)
@FixedLengthRecord()
public class Header implements Serializable {
private static final long serialVersionUID = 1L;
@DataField(pos = 1, length = 5, delimiter = &quot;|&quot;, trim = true)
private String header1;
@DataField(pos = 2, length = 5, delimiter = &quot;|&quot;, trim = true)
private String header2;
@DataField(pos = 3, length = 15, delimiter = &quot;|&quot;, trim = true)
private String header3;
@DataField(pos = 4, length = 60, delimiter = &quot;|&quot;, trim = true)
private String header4;
@DataField(pos = 5, length = 15, delimiter = &quot;|&quot;, trim = true)
private String header5;
@DataField(pos = 6, length = 30, delimiter = &quot;|&quot;, trim = true)
private String header6;
@DataField(pos = 7, length = 30, delimiter = &quot;|&quot;, trim = true)
private String header7;
@DataField(pos = 8, length =  8, pattern = &quot;YYYYMMDD&quot;, delimiter = &quot;|&quot;, trim = true)
private String header8;
@DataField(pos = 9, length = 6, delimiter = &quot;|&quot;, trim = true)
private String header9;
@DataField(pos = 10, length = 1, delimiter = &quot;|&quot;, trim = true)
private String header10;
@DataField(pos = 11, length = 2, delimiter = &quot;|&quot;, trim = true)
private String header11;
@DataField(pos = 12, length = 10, delimiter = &quot;|&quot;, trim = true)
private String header12;
@DataField(pos = 13, length = 10, delimiter = &quot;|&quot;, trim = true)
private String header13;
@DataField(pos = 14, length = 10, align = &quot;L&quot;, trim = true)
private String header14;
}
@Data
@Section(number = 3)
@FixedLengthRecord()
public class Footer implements Serializable {
private static final long serialVersionUID = 1L;
@DataField(pos = 1, length = 7, delimiter = &quot;|&quot;, trim = true)
private String trailer;
@DataField(pos = 2, length = 5, align = &quot;L&quot;, trim = true)
private int count;
public Footer() {
}
public Footer(String trailer, int count) {
this.trailer = trailer;
this.count = count;
}
}

huangapple
  • 本文由 发表于 2020年9月12日 23:23:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/63861877.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定