Template facility
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 the 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.
Controlling Template ID¶
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();
…
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;
}
…