In Chapter 6, Flat File Writer was presented. Among other properties to set, for LineAggregator Summer.Batch.Extra.Template.AbstractTemplateLineAggregator<T>
is dedicated to format the output to an external format file.
The class must be extended by implementing IEnumerable<object> GetParameters(T obj)
that converts the business object used in batch into an enumeration of values.
The template file must have a content like this: Key:Format
, with the Format in C# fashion. Multiple lines of this form can appear with multiple keys and a format can be multi line by repeating colon.
Example 7.23. Example format file
EMPLOYEE: EMPID:{0} EMPNAME:{1}
Example 7.24. More advanced example format file
EMPLOYEE: EMPID:{0} EMPNAME:{1} HEADER :===================================== := Employee List for Date {0:MM/dd/yyyy} = :===================================== FOOTER :===================================== := End Employee List = :=====================================In this example, there are three formats, and two of them span on three lines each.
The following properties are mandatory (need to be set at initialization time):
Template : Reference to resource file containing format;
TemplateId : key to the correct format in file.
Optional properties (Default value is provided, however can set at initialization time):
InputEncoding : template file encoding, defaults to Encoding.Default
;
Culture : template file culture, default to CultureInfo.CurrentCulture
;
LineSeparator : line separator to be used for multi line formats, defaults to Environment.NewLine
.
Configuring the AbstractTemplateLineAggregator
:
Example 7.25. Typical AbstractTemplateLineAggregator
usage
… // Writer - step1/WriteTemplateLine container .StepScopeRegistration<IItemWriter<EmployeeBO>, FlatFileItemWriter<EmployeeBO>>("step1/WriteTemplateLine") .Property("Resource").Resource("#{settings['BA_TEMPLATE_LINE_WRITER.step1.WriteTemplateLine.FILENAME_OUT']}") .Property("Encoding").Value(Encoding.GetEncoding("ASCII")) .Property("LineAggregator") .Reference<ITemplateLineAggregator<EmployeeBO>>("step1/WriteTemplateLine/LineAggregator") .Register(); // Template Line aggregator container.StepScopeRegistration <ITemplateLineAggregator<EmployeeBO>, MyTemplateLineAggregator>("step1/WriteTemplateLine/LineAggregator") .Property("Template") .Resource("#{settings['BA_TEMPLATE_LINE_WRITER.step1.WriteTemplateLine.TEMPLATE.FILENAME_IN']}") .Property("TemplateId").Value("EMPLOYEE") .Register(); …
With a MyTemplateLineAggregator such as:
Example 7.26. Typical TemplateLineAggregator class
public class MyTemplateLineAggregator : AbstractTemplateLineAggregator<EmployeeBO> { protected override IEnumerable<object> GetParameters(EmployeeBO employee) { // Compute a list of the values in EmployeeBO IList<object> parameters = new List<object>(); parameters.Add(employee.Id); parameters.Add(employee.Name); return parameters; } }
Note | |
---|---|
The template line aggregator will be useful with a way to switch between one template Id and another depending on the line to write. This requires a ProcessWriterAdapter, which enables to call the writer in a processor code and have a full control on its use. More details just below. |
With a simple use of the ItemplateLineAggregator
in a writer, as explained above, the TemplateId
is set once and for all in the Unity Loader. This means a multi-format template file would be useful only if several writers are used in the job, and each have a format, all the formats being stored in same template file. However, If a file to write must have several formats depending on the line, a more accurate control on the Template Id must be used. First, the writer with an aggregator must be declared in a process adapter, as explained above in this chapter.
Example 7.27. TemplateLineAggregator unity setup with a ProcessAdapter
… // Process adapter container.StepScopeRegistration<IProcessWriter<object>, ProcessWriterAdapter<object>>("AdapterKey") .Property("StepContextManager").Reference<IContextManager>(BatchConstants.StepContextManagerName) .Property("Adaptee").Reference<IItemWriter<EmployeeBO>>("WriterKey") .Register(); // Template line writer container.StepScopeRegistration<IItemWriter<object>, FlatFileItemWriter<object>>("WriterKey") .Property("Resource").Resource("#{settings['…']}") .Property("Encoding").Value(Encoding.GetEncoding("ASCII")) .Property("LineAggregator").Reference<ITemplateLineAggregator<object>>("AggregatorKey") .Register(); // Template Line aggregator container.StepScopeRegistration<ITemplateLineAggregator<object>, MyTemplateLineAggregator>("AggregatorKey") .Property("Template").Resource("#{settings['…']}") .Property("TemplateId").Value("EMPLOYEE") .Register(); …
With such a setup, even though a default TemplateId is assigned, it becomes possible to change it programmatically and to drive writer at will.
Example 7.28. TemplateLineAggregator usage in a process
… [Dependency("AggregatorKey")] public ITemplateLineAggregator<object> WriteTemplateLineAggregator { get; set; } [Dependency("AdapterKey")] public IProcessWriter<object> WriteTemplateLineWriter { get; set; } public EmployeeBO Process(EmployeeBO employee) { … WriteTemplateLineAggregator.TemplateId = "HEADER"; WriteTemplateLineWriter.WriteInProcess(DateTime.Now); WriteTemplateLineAggregator.TemplateId = "EMPLOYEE"; WriteTemplateLineWriter.WriteInProcess(employee); WriteTemplateLineAggregator.TemplateId = "FOOTER"; WriteTemplateLineWriter.WriteInProcess(null); … } …
Please note that GetParameters
method of the aggregator class must be adapted to handle different types of input objects.
Example 7.29. GetParameters
method for heterogeneous inputs
… protected override IEnumerable<object> GetParameters(object obj) { IList<object> parameters = new List<object>(); if ("HEADER".Equals(TemplateId)) { parameters.Add((DateTime)obj); } else if ("EMPLOYEE".Equals(TemplateId)) { var employee = (EmployeeBO)obj; parameters.Add(employee.Id); parameters.Add(employee.Name); } // Returns an empty list if FOOTER return parameters; } …