ServingXML
works as an "inversion of control" container for assembling components
and making them work together to process records and XML.
New elements may be added by implementing the contracts in the extension API's.
See Serving XML: Inversion of Control Container for an overview.
This section provides templates for custom record reader, filter, and writer elements that can be used in ServingXML resources scripts, as illustrated below.
<sx:resources xmlns:sx="http://www.servingxml.com/core" xmlns:myns="myurl"> <sx:service id="countries"> <sx:recordStream> <sx:recordReader ref="myFileReader"/> <myns:myRecordFilter myAttribute="xxx"/> <myns:myRecordWriter myAttribute="xxx"/> <sx:discardHandler> <sx:log message="{$sx:message}"/> </sx:discardHandler> </sx:recordStream> </sx:service> <sx:flatFileReader id="myFileReader"> <sx:flatFile ref="countriesFile"/> </sx:flatFileReader> </sx:resources>
package mypackage; import com.servingxml.app.ParameterDescriptor; import com.servingxml.components.recordio.RecordReaderFactory; import com.servingxml.components.recordio.RecordReaderFactoryPrefilter; import com.servingxml.util.ServingXmlException; public class MyRecordReaderFactoryAssembler { private ParameterDescriptor[] parameterDescriptors = ParameterDescriptor.EMPTY_ARRAY; private String myAttribute = "myDefault"; public void setMyAttribute(String myAttribute) { this.myAttribute = myAttribute; } public void injectComponent(ParameterDescriptor[] parameterDescriptors) { this.parameterDescriptors = parameterDescriptors; } public RecordReaderFactory assemble(ConfigurationContext context) { RecordReaderFactory readerFactory = new MyRecordReaderFactory(/* args */); if (parameterDescriptors.length > 0) { readerFactory = new RecordReaderFactoryPrefilter(readerFactory,parameterDescriptors); } return readerFactory; } }
package mypackage; import com.servingxml.app.Flow; import com.servingxml.app.ServiceContext; import com.servingxml.components.recordio.AbstractRecordReaderFactory; import com.servingxml.components.recordio.RecordReader; import com.servingxml.util.record.Record; import com.servingxml.util.ServingXmlException; public class MyReaderFactory extends AbstractRecordReaderFactory implements RecordReaderFactory { public MyReaderFactory(/* args */) { } protected RecordReader createRecordReader(ServiceContext context, Flow flow) { RecordReader recordReader = new MyRecordReader(/* args */); return recordReader; } }
package mypackage; import com.servingxml.app.Flow; import com.servingxml.app.ServiceContext; import com.servingxml.components.recordio.AbstractRecordReader; import com.servingxml.components.recordio.RecordReader; import com.servingxml.util.record.Record; import com.servingxml.util.ServingXmlException; public class MyReaderReader extends AbstractRecordReader implements RecordReader { // Per pipeline execution state public MyReaderReader(/* args */) { } public void readRecords(final ServiceContext context, final Flow flow) { try { startRecordStream(context, flow); // For each record { RecordBuilder recordBuilder = new RecordBuilder(); // Build record Record newRecord = recordBuilder.toRecord(); Flow newFlow = flow.replaceRecord(context, newRecord, ++lineNumber); try { writeRecord(context, newFlow); } catch (ServingXmlException e) { super.discardRecord(context, newFlow, e); } } endRecordStream(context, flow); } finally { close(); } } }
package mypackage; import com.servingxml.app.ParameterDescriptor; import com.servingxml.components.recordio.RecordWriterFactory; import com.servingxml.components.recordio.RecordWriterFactoryPrefilter; import com.servingxml.util.ServingXmlException; public class MyRecordWriterFactoryAssembler { private ParameterDescriptor[] parameterDescriptors = ParameterDescriptor.EMPTY_ARRAY; private String myAttribute = "myDefault"; public void setMyAttribute(String myAttribute) { this.myAttribute = myAttribute; } public void injectComponent(ParameterDescriptor[] parameterDescriptors) { this.parameterDescriptors = parameterDescriptors; } public RecordWriterFactory assemble(ConfigurationContext context) { RecordWriterFactory recordWriterFactory = new MyRecordWriterFactory(/* args */); if (parameterDescriptors.length > 0) { recordWriterFactory = new RecordWriterFactoryPrefilter(recordWriterFactory,parameterDescriptors); } return recordWriterFactory; } }
package mypackage; import com.servingxml.app.Flow; import com.servingxml.app.ServiceContext; import com.servingxml.components.recordio.AbstractRecordWriterFactory; import com.servingxml.components.recordio.RecordWriter; import com.servingxml.util.record.Record; import com.servingxml.util.ServingXmlException; public class MyRecordWriterFactory extends AbstractRecordWriterFactory implements RecordWriterFactory { public MyRecordWriterFactory(/* args */) { } public RecordWriter createRecordWriter(ServiceContext context, Flow flow) { RecordWriter recordWriter = new MyRecordWriter(); return recordWriter; } }
package mypackage; import com.servingxml.app.Flow; import com.servingxml.app.ServiceContext; import com.servingxml.components.recordio.AbstractRecordWriter; import com.servingxml.components.recordio.RecordWriter; import com.servingxml.util.record.Record; import com.servingxml.util.ServingXmlException; public class MyRecordWriter extends AbstractRecordWriter implements RecordWriter { // Per pipeline execution state public MyRecordWriter(/* args */) { } public void startRecordStream(ServiceContext context, Flow flow) { // Set up state } public void writeRecord(ServiceContext context, Flow flow) { Record record = flow.getRecord(); // Write the record } public void endRecordStream(ServiceContext context, Flow flow) { // Tear down state } public void close() { // Close all remaining open resources. The framework will call close() // even if there is a fault, so close() may be called even if startRecordStream() // has not been called, or in the successful case, after resources have already // been disposed of in endRecordStream(). } }
package mypackage; import com.servingxml.app.ParameterDescriptor; import com.servingxml.components.recordio.RecordFilterAppender; import com.servingxml.components.recordio.RecordFilterAppenderPrefilter; import com.servingxml.util.ServingXmlException; public class MyRecordFilterAppenderAssembler { private ParameterDescriptor[] parameterDescriptors = ParameterDescriptor.EMPTY_ARRAY; private String myAttribute = "myDefault"; public void setMyAttribute(String myAttribute) { this.myAttribute = myAttribute; } public void injectComponent(ParameterDescriptor[] parameterDescriptors) { this.parameterDescriptors = parameterDescriptors; } public RecordFilterAppender assemble(ConfigurationContext context) { RecordFilterAppender recordFilterAppender = new MyRecordFilterAppender(/* args */); if (parameterDescriptors.length > 0) { recordFilterAppender = new RecordFilterAppenderPrefilter(recordFilterAppender,parameterDescriptors); } return recordFilterAppender; } }
package mypackage; import com.servingxml.app.Flow; import com.servingxml.app.ServiceContext; import com.servingxml.components.recordio.AbstractRecordFilterAppender; import com.servingxml.components.recordio.RecordFilterAppender; import com.servingxml.components.recordio.RecordPipeline; import com.servingxml.util.record.Record; import com.servingxml.util.ServingXmlException; public class MyRecordFilterAppender extends AbstractRecordFilterAppender implements RecordFilterAppender { public MyRecordFilterAppender(/* args */) { } public void appendToRecordPipeline(ServiceContext context, Flow flow, RecordPipeline pipeline) { RecordFilter filter = new MyRecordFilter(); pipeline.addRecordFilter(filter); } }
package mypackage; import com.servingxml.app.Flow; import com.servingxml.app.ServiceContext; import com.servingxml.components.recordio.AbstractRecordFilter; import com.servingxml.util.RecordBuilder; import com.servingxml.util.ServingXmlException; public class MyRecordFilter extends AbstractRecordFilter implements RecordFilter { // Per pipeline execution state public MyRecordFilter(/* args */) { } public void startRecordStream(ServiceContext context, Flow flow) { // Acquire resources (input streams, SQL connections, etc.) super.startRecordStream(context, flow); } public void writeRecord(ServiceContext context, Flow flow) { try { Record record = flow.getRecord(); RecordBuilder recordBuilder = new RecordBuilder(record); // Modify record Record newRecord = recordBuilder.toRecord(); Flow newFlow = flow.replaceRecord(context, newRecord); super.writeRecord(context, newFlow); } catch (Exception e) { ServingXmlException reason = new ServingXmlException(e.getMessage(), e); super.discardRecord(context, flow, reason); } } public void endRecordStream(ServiceContext context, Flow flow) { // Finish up super.endRecordStream(context, flow); } public void close() { // Close all remaining open resources. The framework will call close() // even if there is a fault, so close() may be called even if startRecordStream() // has not been called, or in the successful case, after resources have already // been disposed of in endRecordStream(). } }
This section provides templates for custom serializer elements that can be used in ServingXML resources scripts.
package mypackage; import com.servingxml.app.ParameterDescriptor; import com.servingxml.components.property.OutputProperty; import com.servingxml.app.xmlpipeline.SerializerFactory; import com.servingxml.app.xmlpipeline.SerializerFactoryPrefilter; import com.servingxml.ioc.components.ConfigurationContext; import com.servingxml.util.ServingXmlException; public class MySerializerFactoryAssembler { private ParameterDescriptor[] parameterDescriptors = ParameterDescriptor.EMPTY_ARRAY; private OutputProperty[] outputProperties = new OutputProperty[0]; public void injectComponent(ParameterDescriptor[] parameterDescriptors) { this.parameterDescriptors = parameterDescriptors; } public void injectComponent(OutputProperty[] outputProperties) { this.outputProperties = outputProperties; } public SaxSinkFactory assemble(ConfigurationContext context) { SaxSinkFactory saxSinkFactory = new MySerializerFactory(outputProperties); if (parameterDescriptors.length > 0) { saxSinkFactory = new SerializerFactoryPrefilter(saxSinkFactory, parameterDescriptors); } return saxSinkFactory; } }
package mypackage; import java.util.Properties; import org.xml.sax.ContentHandler; import com.servingxml.app.Flow; import com.servingxml.app.ServiceContext; import com.servingxml.io.saxsink.SaxSink; import com.servingxml.app.xmlpipeline.SerializerFactory; import com.servingxml.util.ServingXmlException; public class MySerializerFactory implements SaxSinkFactory { public MySerializerFactory(/* args */) { } public Serializer createSerializer(ServiceContext context, Flow flow, Properties outputProperties) { ContentHandler handler = new MyContentHandler(/* args */); Serializer serializer = new MySerializer(handler, /* other args */); return serializer; } }
package mypackage; import org.xml.sax.ContentHandler; import com.servingxml.io.saxsink.SaxSink; public class MySerializer implements SaxSink { private final ContentHandler handler; public MySerializer(ContentHandler handler, /* other args */) { this.handler = handler; } public ContentHandler getContentHandler() { return handler; } public void setOutputProperties(Properties outputProperties) { // Called by the framework to set output properties on the SAX sink } public void close() { // Close output streams } }