This chapter describes Batch Applications for the Java Platform (JSR 352), which provides support for defining, implementing, and running batch jobs. Batch jobs are tasks that can be executed without user interaction. The batch framework is composed of a job specification language based on XML, a Java API, and a batch runtime.
Some enterprise applications contain tasks that can be executed without user interaction. These tasks are executed periodically or when resource usage is low, and they often process large amounts of information such as log files, database records, or images. Examples include billing, report generation, data format conversion, and image processing. These tasks are called batch jobs.
Batch processing refers to running batch jobs on a computer system. Java EE includes a batch processing framework that provides the batch execution infrastructure common to all batch applications, enabling developers to concentrate on the business logic of their batch applications. The batch framework consists of a job specification language based on XML, a set of batch annotations and interfaces for application classes that implement the business logic, a batch container that manages the execution of batch jobs, and supporting classes and interfaces to interact with the batch container.
The following topics are addressed here:
A batch job can be completed without user intervention. For example, consider a telephone billing application that reads phone call records from the enterprise information systems and generates a monthly bill for each account. Since this application does not require any user interaction, it can run as a batch job.
The phone billing application consists of two phases: The first phase associates each call from the registry with a monthly bill, and the second phase calculates the tax and total amount due for each bill. Each of these phases is a step of the batch job.
Batch applications specify a set of steps and their execution order. Different batch frameworks may specify additional elements, like decision elements or groups of steps that run in parallel. The following sections describe steps in more detail and provide information about other common characteristics of batch frameworks.
A step is an independent and sequential phase of a batch job. Batch jobs contain chunk-oriented steps and task-oriented steps.
Chunk-oriented steps (chunk steps) process data by reading items from a data source, applying some business logic to each item, and storing the results. Chunk steps read and process one item at a time and group the results into a chunk. The results are stored when the chunk reaches a configurable size. Chunk-oriented processing makes storing results more efficient and facilitates transaction demarcation.
Chunk steps have three parts.
The input retrieval part reads one item at a time from a data source, such as entries on a database, files in a directory, or entries in a log file.
The business processing part manipulates one item at a time using the business logic defined by the application. Examples include filtering, formatting, and accessing data from the item for computing a result.
The output writing part stores a chunk of processed items at a time.
Chunk steps are often long-running because they process large amounts of data. Batch frameworks enable chunk steps to bookmark their progress using checkpoints. A chunk step that is interrupted can be restarted from the last checkpoint. The input retrieval and output writing parts of a chunk step save their current position after the processing of each chunk, and can recover it when the step is restarted.
Figure 55-1 shows the three parts of two steps in a batch job.
Task-oriented steps (task steps) execute tasks other than processing items from a data source. Examples include creating or removing directories, moving files, creating or dropping database tables, configuring resources, and so on. Task steps are not usually long-running compared to chunk steps.
For example, the phone billing application consists of two chunk steps.
In the first step, the input retrieval part reads call records from the registry; the business processing part associates each call with a bill and creates a bill if one does not exist for an account; and the output writing part stores each bill in a database.
In the second step, the input retrieval part reads bills from the database; the business processing part calculates the tax and total amount due for each bill; and the output writing part updates the database records and generates printable versions of each bill.
This application could also contain a task step that cleaned up the files from the bills generated for the previous month.
Batch jobs often process large amounts of data or perform computationally expensive operations. Batch applications can benefit from parallel processing in two scenarios.
Steps that do not depend on each other can run on different threads.
Chunk-oriented steps where the processing of each item does not depend on the results of processing previous items can run on more than one thread.
Batch frameworks provide mechanisms for developers to define groups of independent steps and to split chunk-oriented steps in parts that can run in parallel.
Batch frameworks keep track of a status for every step in a job. The status indicates if a step is running or if it has completed. If the step has completed, the status indicates one of the following.
The execution of the step was successful.
The step was interrupted.
An error occurred in the execution of the step.
In addition to steps, batch jobs can also contain decision elements. Decision elements use the exit status of the previous step to determine the next step or to terminate the batch job. Decision elements set the status of the batch job when terminating it. Like a step, a batch job can terminate successfully, be interrupted, or fail.
Figure 55-2 shows an example of a job that contains chunk steps, task steps and a decision element.
Figure 55-2 Steps and Decision Elements in a Job
Batch applications have the following common requirements.
Define jobs, steps, decision elements, and the relationships between them.
Execute some groups of steps or parts of a step in parallel.
Maintain state information for jobs and steps.
Launch jobs and resume interrupted jobs.
Handle errors.
Batch frameworks provide the batch execution infrastructure that addresses the common requirements of all batch applications, enabling developers to concentrate on the business logic of their applications. Batch frameworks consist of a format to specify jobs and steps, an application programming interface (API), and a service available at runtime that manages the execution of batch jobs.
This section lists the components of the batch processing framework in Java EE and provides an overview of the steps you have to follow to create a batch application.
Java EE includes a batch processing framework that consists of the following elements:
A batch runtime that manages the execution of jobs
A job specification language based on XML
A Java API to interact with the batch runtime
A Java API to implement steps, decision elements, and other batch artifacts
Batch applications in Java EE contain XML files and Java classes. The XML files define the structure of a job in terms of batch artifacts and the relationships between them. (A batch artifact is a part of a chunk-oriented step, a task-oriented step, a decision element, or another component of a batch application). The Java classes implement the application logic of the batch artifacts defined in the XML files. The batch runtime parses the XML files and loads the batch artifacts as Java classes to run the jobs in a batch application.
The process for creating a batch application in Java EE is the following.
Design the batch application.
Identify the input sources, the format of the input data, the desired final result, and the required processing phases.
Organize the application as a job with chunk-oriented steps, task-oriented steps, and decision elements. Determine the dependencies between them.
Determine the order of execution in terms of transitions between steps.
Identify steps that can run in parallel and steps that can run in more than one thread.
Create the batch artifacts as Java classes by implementing the interfaces specified by the framework for steps, decision elements, and so on. These Java classes contain the code to read data from input sources, format items, process items, and store results. Batch artifacts can access context objects from the batch runtime using dependency injection.
Define jobs, steps, and their execution flow in XML files using the Job Specification Language. The elements in the XML files reference batch artifacts implemented as Java classes. The batch artifacts can access properties declared in the XML files, such as names of files and databases.
Use the Java API provided by the batch runtime to launch the batch application.
The following sections describe in detail how to use the components of the batch processing framework in Java EE to create batch applications.
A batch job can contain one or more of the following elements:
Steps
Flows
Splits
Decision elements
Steps are described in Introduction to Batch Processing, and can be chunk-oriented or task-oriented. Chunk-oriented steps can be partitioned steps. In a partitioned chunk step, the processing of one item does not depend on other items, so these steps can run in more than one thread.
A flow is a sequence of steps that execute as a unit. A sequence of related steps can be grouped together into a flow. The steps in a flow cannot transition to steps outside the flow. The flow transitions to the next element when its last step completes.
A split is a set of flows that execute in parallel; each flow runs on a separate thread. The split transitions to the next element when all its flows complete.
Decision elements use the exit status of the previous step to determine the next step or to terminate the batch job.
Jobs and steps can have a number of properties associated with them. You define properties in the job definition file, and batch artifacts access these properties using context objects from the batch runtime. Using properties in this manner enables you to decouple static parameters of the job from the business logic and to reuse batch artifacts in different job definition files.
Specifying properties is described in Using the Job Specification Language, and accessing properties in batch artifacts is described in Creating Batch Artifacts.
Java EE applications can also pass parameters to a job when they submit it to the batch runtime. This enables you to specify dynamic parameters that are only known at runtime. Parameters are also necessary for partitioned steps, since each partition needs to know, for example, what range of items to process.
Specifying parameters when submitting jobs is described in Submitting Jobs to the Batch Runtime. Specifying parameters for partitioned steps and accessing them in batch artifacts is demonstrated in The phonebilling Example Application.
A job definition can have multiple instances, each with different parameters. A job execution is an attempt to run a job instance. The batch runtime maintains information about job instances and job executions, as described in Checking the Status of a Job.
The state of jobs, steps, splits, and flows is represented in the batch runtime as a batch status value. Batch status values are listed Table 55-1. They are represented as strings.
Table 55-1 Batch Status Values
| Value | Description |
|---|---|
|
|
The job has been submitted to the batch runtime. |
|
|
The job is running. |
|
|
The job has been requested to stop. |
|
|
The job has stopped. |
|
|
The job finished executing because of an error. |
|
|
The job finished executing successfully. |
|
|
The job was marked abandoned. |
Java EE applications can submit jobs and access the batch status of a job using the JobOperator
interface, as described in Submitting Jobs to the Batch Runtime. Job definition files can refer to batch status values using the Job Specification Language (JSL), as described in Using the Job Specification Language. Batch artifacts can access batch status values using context objects, as described in Using the Context Objects from the Batch Runtime.
For flows, the batch status is that of its last step. For splits, the batch status is the following:
COMPLETED
: If all its flows have a batch status of COMPLETED
FAILED
: If any flow has a batch status of FAILED
STOPPED
: If any flow has a batch status of STOPPED
, and no flows have a batch status of FAILED
The batch status for jobs, steps, splits, and flows is set by the batch runtime. Jobs, steps, splits, and flows also have an exit status, which is a user-defined value based on the batch status. You can set the exit status inside batch artifacts or in the job definition file. You can access the exit status in the same manner as the batch status, described above. The default value for the exit status is the same as the batch status.
This section demonstrates how to define a simple job using the Job Specification Language (JSL) and how to implement the corresponding batch artifacts. Refer to the rest of the sections in this chapter for detailed descriptions of the elements in the batch framework.
The following job definition specifies a chunk step and a task step as follows:
<?xml version="1.0" encoding="UTF-8"?> <job id="simplejob" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0"> <properties> <property name="input_file" value="input.txt"/> <property name="output_file" value="output.txt"/> </properties> <step id="mychunk" next="mytask"> <chunk> <reader ref="MyReader"></reader> <processor ref="MyProcessor"></processor> <writer ref="MyWriter"></writer> </chunk> </step> <step id="mytask"> <batchlet ref="MyBatchlet"></batchlet> <end on="COMPLETED"/> </step> </job>
In most cases, you have to implement a checkpoint class for chunk-oriented steps. The following class just keeps track of the line number in a text file:
public class MyCheckpoint implements Serializable { private long lineNum = 0; public void increase() { lineNum++; } public long getLineNum() { return lineNum; } }
The following item reader implementation continues reading the input file from the provided checkpoint if the job was restarted. The items consist of each line in the text file (in more complex scenarios, the items are custom Java types and the input source can be a database):
@Dependent @Named("MyReader") public class MyReader implements javax.batch.api.chunk.ItemReader { private MyCheckpoint checkpoint; private BufferedReader breader; @Inject JobContext jobCtx; public MyReader() {} @Override public void open(Serializable ckpt) throws Exception { if (ckpt == null) checkpoint = new MyCheckpoint(); else checkpoint = (MyCheckpoint) ckpt; String fileName = jobCtx.getProperties() .getProperty("input_file"); breader = new BufferedReader(new FileReader(fileName)); for (long i = 0; i < checkpoint.getLineNum(); i++) breader.readLine(); } @Override public void close() throws Exception { breader.close(); } @Override public Object readItem() throws Exception { String line = breader.readLine(); return line; } }
In the following case, the item processor only converts the line to uppercase. More complex examples can process items in different ways or transform them into custom output Java types:
@Dependent @Named("MyProcessor") public class MyProcessor implements javax.batch.api.chunk.ItemProcessor { public MyProcessor() {} @Override public Object processItem(Object obj) throws Exception { String line = (String) obj; return line.toUpperCase(); } }
|
Note: The batch processing API does not support generics. In most cases, you need to cast items to their specific type before processing them. |
The item writer writes the processed items to the output file. It overwrites the output file if no checkpoint is provided; otherwise, it resumes writing at the end of the file. Items are written in chunks:
@Dependent @Named("MyWriter") public class MyWriter implements javax.batch.api.chunk.ItemWriter { private BufferedWriter bwriter; @Inject private JobContext jobCtx; @Override public void open(Serializable ckpt) throws Exception { String fileName = jobCtx.getProperties() .getProperty("output_file"); bwriter = new BufferedWriter(new FileWriter(fileName, (ckpt != null))); } @Override public void writeItems(List<Object> items) throws Exception { for (int i = 0; i < items.size(); i++) { String line = (String) items.get(i); bwriter.write(line); bwriter.newLine(); } } @Override public Serializable checkpointInfo() throws Exception { return new MyCheckpoint(); }
The task step displays the length of the output file. In more complex scenarios, task steps perform any task that does not fit the chunk processing programming model:
@Dependent @Named("MyBatchlet") public class MyBatchlet implements javax.batch.api.chunk.Batchlet { @Inject private JobContext jobCtx; @Override public String process() throws Exception { String fileName = jobCtx.getProperties() .getProperty("output_file"); System.out.println(""+(new File(fileName)).length()); return "COMPLETED"; } }
The Job Specification Language (JSL) enables you to define the steps in a job and their execution order using an XML file. The following example shows how to define a simple job that contains one chunk step and one task step:
<job id="loganalysis" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0"> <properties> <property name="input_file" value="input1.txt"/> <property name="output_file" value="output2.txt"/> </properties> <step id="logprocessor" next="cleanup"> <chunk checkpoint-policy="item" item-count="10"> <reader ref="com.example.pkg.LogItemReader"></reader> <processor ref="com.example.pkg.LogItemProcessor"></processor> <writer ref="com.example.pkg.LogItemWriter"></writer> </chunk> </step> <step id="cleanup"> <batchlet ref="com.example.pkg.CleanUp"></batchlet> <end on="COMPLETED"/> </step> </job>
This example defines the loganalysis
batch job, which consists of the logprocessor
chunk step and the cleanup
task step. The logprocessor
step transitions to the cleanup
step, which terminates the job when completed.
The job
element defines two properties, input_file
and output_file
. Specifying properties in this manner enables you to run a batch job with different configuration parameters without having to recompile its Java batch artifacts. The batch artifacts can access these properties using the context objects from the batch runtime.
The logprocessor
step is a chunk step that specifies batch artifacts for the reader (LogItemReader
), the processor (LogItemProcessor
), and the writer (LogItemWriter
). This step creates a checkpoint for every ten items processed.
The cleanup
step is a task step that specifies the CleanUp
class as its batch artifact. The job terminates when this step completes.
The following sections describe the elements of the Job Specification Language (JSL) in more detail and show the most common attributes and child elements.
The job
element is always the top-level element in a job definition file. Its main attributes are id
and restartable
. The job
element can contain one properties
element and zero or more of each of the following elements: listener
, step
, flow
, and split
. For example:
<job id="jobname" restartable="true"> <listeners> <listener ref="com.example.pkg.ListenerBatchArtifact"/> </listeners> <properties> <property name="propertyName1" value="propertyValue1"/> <property name="propertyName2" value="propertyValue2"/> </properties> <step ...> ... </step> <step ...> ... </step> <decision ...> ... </decision> <flow ...> ... </flow> <split ...> ... </split> </job>
The listener
element specifies a batch artifact whose methods are invoked before and after the execution of the job. The batch artifact is an implementation of the javax.batch.api.listener.JobListener
interface. See The Listener Batch Artifacts for an example of a job listener implementation.
The first step
, flow
, or split
element inside the job
element executes first.
The step
element can be a child of the job
and flow
elements. Its main attributes are id
and next
. The step
element can contain the following elements.
One chunk
element for chunk-oriented steps or one batchlet
element for task-oriented steps.
One properties
element (optional).
This element specifies a set of properties that batch artifacts can access using batch context objects.
One listener
element (optional); one listeners
element if more than one listener is specified.
This element specifies listener artifacts that intercept various phases of step execution.
For chunk steps, the batch artifacts for these listeners can be implementations of the following interfaces: StepListener
, ItemReadListener
, ItemProcessListener
, ItemWriteListener
, ChunkListener
, RetryReadListener
, RetryProcessListener
, RetryWriteListener
, SkipReadListener
, SkipProcessListener
, and SkipWriteListener
.
For task steps, the batch artifact for these listeners must be an implementation of the StepListener
interface.
See The Listener Batch Artifacts for an example of an item processor listener implementation.
One partition
element (optional).
This element is used in partitioned steps which execute in more than one thread.
One end
element if this is the last step in a job.
This element sets the batch status to COMPLETED
.
One stop
element (optional) to stop a job at this step.
This element sets the batch status to STOPPED
.
One fail
element (optional) to terminate a job at this step.
This element sets the batch status to FAILED
.
One or more next
elements if the next
attribute is not specified.
This element is associated with an exit status and refers to another step, a flow, a split, or a decision element.
The following is an example of a chunk step:
<step id="stepA" next="stepB"> <properties> ... </properties> <listeners> <listener ref="MyItemReadListenerImpl"/> ... </listeners> <chunk ...> ... </chunk> <partition> ... </partition> <end on="COMPLETED" exit-status="MY_COMPLETED_EXIT_STATUS"/> <stop on="MY_TEMP_ISSUE_EXIST_STATUS" restart="step0"/> <fail on="MY_ERROR_EXIT_STATUS" exit-status="MY_ERROR_EXIT_STATUS"/> </step>
The following is an example of a task step:
<step id="stepB" next="stepC"> <batchlet ...> ... </batchlet> <properties> ... </properties> <listener ref="MyStepListenerImpl"/> </step>
The chunk
element is a child of the step
element for chunk-oriented steps. The attributes of this element are listed in Table 55-2.
Table 55-2 Attributes of the chunk Element
| Attribute Name | Description | Default Value |
|---|---|---|
|
|
Specifies how to commit the results of processing each chunk:
The checkpoint is updated when the results of a chunk are committed. Every chunk is processed in a global Java EE transaction. If the processing of one item in the chunk fails, the transaction is rolled back and no processed items from this chunk are stored. |
|
|
|
Specifies the number of items to process before committing the chunk and taking a checkpoint. |
10 |
|
|
Specifies the number of seconds before committing the chunk and taking a checkpoint when If |
0 (no limit) |
|
|
Specifies if processed items are buffered until it is time to take a checkpoint. If true, a single call to the item writer is made with a list of the buffered items before committing the chunk and taking a checkpoint. |
true |
|
|
Specifies the number of skippable exceptions to skip in this step during chunk processing. Skippable exception classes are specified with the |
No limit |
|
|
Specifies the number of attempts to execute this step if retryable exceptions occur. Retryable exception classes are specified with the |
No limit |
The chunk
element can contain the following elements.
One reader
element.
This element specifies a batch artifact that implements the ItemReader
interface.
One processor
element.
This element specifies a batch artifact that implements the ItemProcessor
interface.
One writer
element.
This element specifies a batch artifact that implements the ItemWriter
interface.
One checkpoint-algorithm
element (optional).
This element specifies a batch artifact that implements the CheckpointAlgorithm
interface and provides a custom checkpoint policy.
One skippable-exception-classes
element (optional).
This element specifies a set of exceptions thrown from the reader, writer, and processor batch artifacts that chunk processing should skip. The skip-limit
attribute from the chunk
element specifies the maximum number of skipped exceptions.
One retryable-exception-classes
element (optional).
This element specifies a set of exceptions thrown from the reader, writer, and processor batch artifacts that chunk processing will retry. The retry-limit
attribute from the chunk
element specifies the maximum number of attempts.
One no-rollback-exception-classes
element (optional).
This element specifies a set of exceptions thrown from the reader, writer, and processor batch artifacts that should not cause the batch runtime to roll back the current chunk, but to retry the current operation without a rollback instead.
For exception types not specified in this element, the current chunk is rolled back by default when an exception occurs.
The following is an example of a chunk-oriented step:
<step id="stepC" next="stepD"> <chunk checkpoint-policy="item" item-count="5" time-limit="180" buffer-items="true" skip-limit="10" retry-limit="3"> <reader ref="pkg.MyItemReaderImpl"></reader> <processor ref="pkg.MyItemProcessorImpl"></processor> <writer ref="pkg.MyItemWriterImpl"></writer> <skippable-exception-classes> <include class="pkg.MyItemException"/> <exclude class="pkg.MyItemSeriousSubException"/> </skippable-exception-classes> <retryable-exception-classes> <include class="pkg.MyResourceTempUnavailable"/> </retryable-exception-classes> </chunk> </step>
This example defines a chunk step and specifies its reader, processor, and writer artifacts. The step updates a checkpoint and commits each chunk after processing five items. It skips all MyItemException
exceptions and all its subtypes, except for MyItemSeriousSubException
, up to a maximum of ten skipped exceptions. The step retries a chunk when a MyResourceTempUnavailable
exception occurs, up to a maximum of three attempts.
The batchlet
element is a child of the step
element for task-oriented steps. This element only has the ref
attribute, which specifies a batch artifact that implements the Batchlet
interface. The batch
element can contain a properties
element.
The following is an example of a task-oriented step:
<step id="stepD" next="stepE"> <batchlet ref="pkg.MyBatchletImpl"> <properties> <property name="pname" value="pvalue"/> </properties> </batchlet> </step>
This example defines a batch step and specifies its batch artifact.
The partition
element is a child of the step
element. It indicates that a step is partitioned. Most partitioned steps are chunk steps where the processing of each item does not depend on the results of processing previous items. You specify the number of partitions in a step and provide each partition with specific information on which items to process, such as the following.
A range of items. For example, partition 1 processes items 1 through 500, and partition 2 processes items 501 through 1000.
An input source. For example, partition 1 processes the items in input1.txt
and partition 2 processes the items in input2.txt
.
When the number of partitions, the number of items, and the input sources for a partitioned step are known at development or deployment time, you can use partition properties in the job definition file to specify partition-specific information and access these properties from the step batch artifacts. The runtime creates as many instances of the step batch artifacts (reader, processor, and writer) as partitions, and each artifact instance receives the properties specific to its partition.
In most cases, the number of partitions, the number of items, or the input sources for a partitioned step can only be determined at runtime. Instead of specifying partition-specific properties statically in the job definition file, you provide a batch artifact that can access your data sources at runtime and determine how many partitions are needed and what range of items each partition should process. This batch artifact is an implementation of the PartitionMapper
interface. The batch runtime invokes this artifact and then uses the information it provides to instantiate the step batch artifacts (reader, writer, and processor) for each partition and to pass them partition-specific data as parameters.
The rest of this section describes the partition
element in detail and shows two examples of job definition files: one that uses partition properties to specify a range of items for each partition, and one that relies on a PartitionMapper
implementation to determine partition-specific information.
See The Phone Billing Chunk Step in The phonebilling Example Application for a complete example of a partitioned chunk step.
The partition
element can contain the following elements.
One plan
element, if the mapper
element is not specified.
This element defines the number of partitions, the number of threads, and the properties for each partition in the job definition file. The plan
element is useful when this information is known at development or deployment time.
One mapper
element, if the plan
element is not specified.
This element specifies a batch artifact that provides the number of partitions, the number of threads, and the properties for each partition. The batch artifact is an implementation of the PartitionMapper
interface. You use this option when the information required for each partition is only known at runtime.
One reducer
element (optional).
This element specifies a batch artifact that receives control when a partitioned step begins, ends, or rolls back. The batch artifact enables you to merge results from different partitions and perform other related operations. The batch artifact is an implementation of the PartitionReducer
interface.
One collector
element (optional).
This element specifies a batch artifact that sends intermediary results from each partition to a partition analyzer. The batch artifact sends the intermediary results after each checkpoint for chunk steps and at the end of the step for task steps. The batch artifact is an implementation of the PartitionCollector
interface.
One analyzer
element (optional).
This element specifies a batch artifact that analyzes the intermediary results from the partition collector instances. The batch artifact is an implementation of the PartitionAnalyzer
interface.
The following is an example of a partitioned step using the plan
element:
<step id="stepE" next="stepF"> <chunk> <reader ...></reader> <processor ...></processor> <writer ...></writer> </chunk> <partition> <plan partitions="2" threads="2"> <properties partition="0"> <property name="firstItem" value="0"/> <property name="lastItem" value="500"/> </properties> <properties partition="1"> <property name="firstItem" value="501"/> <property name="lastItem" value="999"/> </properties> </plan> </partition> <reducer ref="MyPartitionReducerImpl"/> <collector ref="MyPartitionCollectorImpl"/> <analyzer ref="MyPartitionAnalyzerImpl"/> </step>
In this example, the plan
element specifies the properties for each partition in the job definition file.
The following example uses a mapper
element instead of a plan
element. The PartitionMapper
implementation dynamically provides the same information as the plan
element provides in the job definition file:
<step id="stepE" next="stepF"> <chunk> <reader ...></reader> <processor ...></processor> <writer ...></writer> </chunk> <partition> <mapper ref="MyPartitionMapperImpl"/> <reducer ref="MyPartitionReducerImpl"/> <collector ref="MyPartitionCollectorImpl"/> <analyzer ref="MyPartitionAnalyzerImpl"/> </partition> </step>
Refer to The phonebilling Example Application for an example implementation of the PartitionMapper
interface.
The flow
element can be a child of the job
, flow
, and split
elements. Its attributes are id
and next
. Flows can transition to flows, steps, splits, and decision elements. The flow
element can contain the following elements:
One or more step
elements
One or more flow
elements (optional)
One or more split
elements (optional)
One or more decision
elements (optional)
The last step
in a flow is the one with no next
attribute or next
element. Steps and other elements in a flow cannot transition to elements outside the flow.
The following is an example of the flow
element:
<flow id="flowA" next="stepE"> <step id="flowAstepA" next="flowAstepB">...</step> <step id="flowAstepB" next="flowAflowC">...</step> <flow id="flowAflowC" next="flowAsplitD">...</flow> <split id="flowAsplitD" next="flowAstepE">...</split> <step id="flowAstepE">...</step> </flow>
This example flow contains three steps, one flow, and one split. The last step does not have the next
attribute. The flow transitions to stepE
when its last step completes.
The split
element can be a child of the job
and flow
elements. Its attributes are id
and next
. Splits can transition to splits, steps, flows, and decision elements. The split
element can only contain one or more flow
elements that can only transition to other flow
elements in the split.
The following is an example of a split with three flows that execute concurrently:
<split id="splitA" next="stepB"> <flow id="splitAflowA">...</flow> <flow id="splitAflowB">...</flow> <flow id="splitAflowC">...</flow> </split>
The decision
element can be a child of the job
and flow
elements. Its attributes are id
and next
. Steps, flows, and splits can transition to a decision
element. This element specifies a batch artifact that decides the next step, flow, or split to execute based on information from the execution of the previous step, flow, or split. The batch artifact implements the Decider
interface. The decision
element can contain the following elements.
One or more end
elements (optional).
This element sets the batch status to COMPLETED
.
One or more stop
elements (optional).
This element sets the batch status to STOPPED
.
One or more fail
elements (optional).
This element sets the batch status to FAILED
.
One or more next
elements (optional).
One properties
element (optional).
The following is an example of the decider
element:
<decision id="decisionA" ref="MyDeciderImpl"> <fail on="FAILED" exit-status="FAILED_AT_DECIDER"/> <end on="COMPLETED" exit-status="COMPLETED_AT_DECIDER"/> <stop on="MY_TEMP_ISSUE_EXIST_STATUS" restart="step2"/> </decision>
After you define a job in terms of its batch artifacts using the Job Specification Language (JSL), you create these artifacts as Java classes that implement the interfaces in the javax.batch.api
package and its subpackages.
This section lists the main batch artifact interfaces, demonstrates how to access context objects from the batch runtime, and provides some examples.
The following tables list the interfaces that you implement to create batch artifacts. The interface implementations are referenced from the elements described in Using the Job Specification Language.
Table 55-3 lists the interfaces to implement batch artifacts for chunk steps, task steps, and decision elements.
Table 55-4 lists the interfaces to implement batch artifacts for partitioned steps.
Table 55-5 lists the interfaces to implement batch artifacts for job and step listeners.
Table 55-3 Main Batch Artifact Interfaces
| Package | Interface | Description |
|---|---|---|
|
|
|
Implements the business logic of a task-oriented step. It is referenced from the |
|
|
|
Decides the next step, flow, or split to execute based on information from the execution of the previous step, flow, or split. It is referenced from the |
|
|
|
Implements a custom checkpoint policy for chunk steps. It is referenced from the |
|
|
|
Reads items from an input source in a chunk step. It is referenced from the |
|
|
|
Processes input items to obtain output items in chunk steps. It is referenced from the |
|
|
|
Writes output items in chunk steps. It is referenced from the |
Table 55-4 Partition Batch Artifact Interfaces
| Package | Interface | Description |
|---|---|---|
|
|
|
Provides details on how to execute a partitioned step, such as the number of partitions, the number of threads, and the parameters for each partition. This artifact is not referenced directly from the job definition file. |
|
|
|
Provides a |
|
|
|
Receives control when a partitioned step begins, ends, or rolls back. It is referenced from the |
|
|
|
Sends intermediary results from each partition to a partition analyzer. It is referenced from the |
|
|
|
Processes data and final results from each partition. It is referenced from the |
Table 55-5 Listener Batch Artifact Interfaces
| Package | Interface | Description |
|---|---|---|
|
|
|
Intercepts job execution before and after running a job. It is referenced from the |
|
|
|
Intercepts step execution before and after running a step. It is referenced from the |
|
|
|
Intercepts chunk processing in chunk steps before and after processing each chunk, and on errors. It is referenced from the |
|
|
|
Intercepts item reading in chunk steps before and after reading each item, and on errors. It is referenced from the |
|
|
|
Intercepts item processing in chunk steps before and after processing each item, and on errors. It is referenced from the |
|
|
|
Intercepts item writing in chunk steps before and after writing each item, and on errors. It is referenced from the |
|
|
|
Intercepts retry item reading in chunk steps when an exception occurs. It is referenced from the |
|
|
|
Intercepts retry item processing in chunk steps when an exception occurs. It is referenced from the |
|
|
|
Intercepts retry item writing in chunk steps when an exception occurs. It is referenced from the |
|
|
|
Intercepts skippable exception handling for item readers in chunk steps. It is referenced from the |
|
|
|
Intercepts skippable exception handling for item processors in chunk steps. It is referenced from the |
|
|
|
Intercepts skippable exception handling for item writers in chunk steps. It is referenced from the |
To ensure that Contexts and Dependency Injection (CDI) works in your batch artifacts, follow these steps.
Define your batch artifact implementations as CDI named beans using the Named
annotation.
For example, define an item reader implementation in a chunk step as follows:
@Named("MyItemReaderImpl") public class MyItemReaderImpl implements ItemReader { /* ... Override the ItemReader interface methods ... */ }
Provide a public, empty, no-argument constructor for your batch artifacts.
For example, provide the following constructor for the artifact above:
public MyItemReaderImpl() {}
Specify the CDI name for the batch artifacts in the job definition file, instead of using the fully qualified name of the class.
For example, define the step for the artifact above as follows:
<step id="stepA" next="stepB"> <chunk> <reader ref="MyItemReaderImpl"></reader> ... </chunk> </step>
This example uses the CDI name (MyItemReaderImpl
) instead of the fully qualified name of the class (com.example.pkg.MyItemReaderImpl
) to specify a batch artifact.
Ensure that your module is a CDI bean archive by annotating your batch artifacts with the javax.enterprise.context.Dependent
annotation or by including an empty beans.xml
deployment description with your application. For example, the following batch artifact is annotated with @Dependent
:
@Dependent @Named("MyItemReaderImpl") public class MyItemReaderImpl implements ItemReader { ... }
For more information on bean archives, see Packaging CDI Applications in Chapter 25, "Contexts and Dependency Injection for Java EE: Advanced Topics".
|
Note: Contexts and Dependency Injection (CDI) is required in order to access context objects from the batch runtime in batch artifacts. |
You may encounter the following errors if you do not follow this procedure.
The batch runtime cannot locate some batch artifacts.
The batch artifacts throw null pointer exceptions when accessing injected objects.
The batch runtime provides context objects that implement the JobContext
and StepContext
interfaces in the javax.batch.runtime.context
package. These objects are associated with the current job and step, respectively, and enable you to do the following:
Get information from the current job or step, such as its name, instance ID, execution ID, batch status, and exit status
Set the user-defined exit status
Store user data
Get property values from the job or step definition
You can inject context objects from the batch runtime inside batch artifact implementations like item readers, item processors, item writers, batchlets, listeners, and so on. The following example demonstrates how to access property values from the job definition file in an item reader implementation:
@Dependent @Named("MyItemReaderImpl") public class MyItemReaderImpl implements ItemReader { @Inject JobContext jobCtx; public MyItemReaderImpl() {} @Override public void open(Serializable checkpoint) throws Exception { String fileName = jobCtx.getProperties() .getProperty("log_file_name"); ... } ... }
See Dependency Injection in Batch Artifacts for instructions on how to define your batch artifacts to use dependency injection.
|
Note: Do not access batch context objects inside artifact constructors. Because the job does not run until you submit it to the batch runtime, the batch context objects are not available when CDI instantiates your artifacts upon loading your application. The instantiation of these beans fails and the batch runtime cannot find your batch artifacts when your application submits the job. |
The JobOperator
interface in the javax.batch.operations
package enables you to submit jobs to the batch runtime and obtain information about existing jobs. This interface provides the following functionality.
Obtain the names of all known jobs.
Start, stop, restart, and abandon jobs.
Obtain job instances and job executions.
The BatchRuntime
class in the javax.batch.runtime
package provides the getJobOperator
factory method to obtain JobOperator
objects.
The following example code demonstrates how to obtain a JobOperator
object and submit a batch job:
JobOperator jobOperator = BatchRuntime.getJobOperator(); Properties props = new Properties(); props.setProperty("parameter1", "value1"); ... long execID = jobOperator.start("simplejob", props);
The first argument of the JobOperator.start
method is the name of the job as specified in its job definition file. The second parameter is a Properties
object that represents the parameters for this job execution. You can use job parameters to pass to a job information that is only known at runtime.
The JobExecution
interface in the javax.batch.runtime
package provides methods to obtain information about submitted jobs. This interface provides the following functionality.
Obtain the batch and exit status of a job execution.
Obtain the time the execution was started, updated, or ended.
Obtain the job name.
Obtain the execution ID.
The following example code demonstrates how to obtain the batch status of a job using its execution ID:
JobExecution jobExec = jobOperator.getJobExecution(execID); String status = jobExec.getBatchStatus().toString();
The component from which you invoke the batch runtime depends on the architecture of your particular application. For example, you can invoke the batch runtime from an enterprise bean, a servlet, a managed bean, and so on.
See The webserverlog Example Application and The phonebilling Example Application for details on how to invoke the batch runtime from a managed bean driven by a JavaServer Faces user interface.
Job definition files and batch artifacts do not require separate packaging and can be included in any Java EE application.
Package the batch artifact classes with the rest of the classes of your application, and include the job definition files in one of the following directories:
META-INF/batch-jobs/
for jar
packages
WEB-INF/classes/META-INF/batch-jobs/
for war
packages
The name of each job definition file must match its job ID. For example, if you define a job as follows, and you are packaging your application as a WAR file, include the job definition file in WEB-INF/classes/META-INF/batch-jobs/simplejob.xml
:
<job id="simplejob" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0"> ... </job>
The webserverlog
example application, located in the tut-install/examples/batch/webserverlog/
directory, demonstrates how to use the batch framework in Java EE to analyze the log file from a web server. This example application reads a log file and finds what percentage of page views from tablet devices are product sales.
The webserverlog
example application consists of the following elements.
A job definition file (webserverlog.xml
) that uses the Job Specification Language (JSL) to define a batch job with a chunk step and a task step. The chunk step acts as a filter, and the task step calculates statistics on the remaining entries.
A log file (log1.txt
) that serves as input data to the batch job.
Two Java classes (LogLine
and LogFilteredLine
) that represent input items and output items for the chunk step.
Three batch artifacts (LogLineReader
, LogLineProcessor
, and LogFilteredLineWriter
) that implement the chunk step of the application. This step reads items from the web server log file, filters them by the web browser used by the client, and writes the results to a text file.
Two batch artifacts (InfoJobListener
and InfoItemProcessListener
) that implement two simple listeners.
A batch artifact (MobileBatchlet.java
) that calculates statistics on the filtered items.
Two Facelets pages (index.xhtml
and jobstarted.xhtml
) that provide the front end of the batch application. The first page shows the log file that will be processed by the batch job, and the second page enables the user to check on the status of the job and shows the results.
A managed bean (JsfBean
) that is accessed from the Facelets pages. The bean submits the job to the batch runtime, checks on the status of the job, and reads the results from a text file.
The webserverlog.xml
job definition file is located in the WEB-INF/classes/META-INF/batch-jobs/
directory. The file specifies seven job-level properties and two steps:
<?xml version="1.0" encoding="UTF-8"?> <job id="webserverlog" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0"> <properties> <property name="log_file_name" value="log1.txt"/> <property name="filtered_file_name" value="filtered1.txt"/> <property name="num_browsers" value="2"/> <property name="browser_1" value="Tablet Browser D"/> <property name="browser_2" value="Tablet Browser E"/> <property name="buy_page" value="/auth/buy.html"/> <property name="out_file_name" value="result1.txt"/> </properties> <listeners> <listener ref="InfoJobListener"/> </listeners> <step id="mobilefilter" next="mobileanalyzer"> ... </step> <step id="mobileanalyzer"> ... </step> </job>
The first step is defined as follows:
<step id="mobilefilter" next="mobileanalyzer"> <listeners> <listener ref="InfoItemProcessListeners"/> </listeners> <chunk checkpoint-policy="item" item-count="10"> <reader ref="LogLineReader"></reader> <processor ref="LogLineProcessor"></processor> <writer ref="LogFilteredLineWriter"></writer> </chunk> </step>
This step is a normal chunk step that specifies the batch artifacts that implement each phase of the step. The batch artifact names are not fully qualified class names, so the batch artifacts are CDI beans annotated with @Named
.
The second step is defined as follows:
<step id="mobileanalyzer"> <batchlet ref="MobileBatchlet"></batchlet> <end on="COMPLETED"/> </step>
This step is a task step that specifies the batch artifact that implements it. This is the last step of the job.
The LogLine
class represents entries in the web server log file and it is defined as follows:
public class LogLine { private final String datetime; private final String ipaddr; private final String browser; private final String url; /* ... Constructor, getters, and setters ... */ }
The LogFileteredLine
class is similar to this class but only has two fields: the IP address of the client and the URL.
The first step is composed of the LogLineReader
, LogLineProcessor
, and LogFilteredLineWriter
batch artifacts.
The LogLineReader
artifact reads records from the web server log file:
@Dependent @Named("LogLineReader") public class LogLineReader implements ItemReader { private ItemNumberCheckpoint checkpoint; private String fileName; private BufferedReader breader; @Inject private JobContext jobCtx; public LogLineReader() { } /* ... Override the open, close, readItem, and * checkpointInfo methods ... */ }
The open
method reads the log_file_name
property and opens the log file with a buffered reader. In this example, the log file has been included with the application under webserverlog/WEB-INF/classes/log1.txt
:
fileName = jobCtx.getProperties().getProperty("log_file_name"); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); InputStream iStream = classLoader.getResourceAsStream(fileName); breader = new BufferedReader(new InputStreamReader(iStream));
If a checkpoint object is provided, the open
method advances the reader up to the last checkpoint. Otherwise, this method creates a new checkpoint object. The checkpoint object keeps track of the line number from the last committed chunk.
The readItem
method returns a new LogLine
object or null at the end of the log file:
@Override public Object readItem() throws Exception { String entry = breader.readLine(); if (entry != null) { checkpoint.nextLine(); return new LogLine(entry); } else { return null; } }
The LogLineProcessor
artifact obtains a list of browsers from the job properties and filters the log entries according to the list:
@Override public Object processItem(Object item) { /* Obtain a list of browsers we are interested in */ if (nbrowsers == 0) { Properties props = jobCtx.getProperties(); nbrowsers = Integer.parseInt(props.getProperty("num_browsers")); browsers = new String[nbrowsers]; for (int i = 1; i < nbrowsers + 1; i++) browsers[i - 1] = props.getProperty("browser_" + i); } LogLine logline = (LogLine) item; /* Filter for only the mobile/tablet browsers as specified */ for (int i = 0; i < nbrowsers; i++) { if (logline.getBrowser().equals(browsers[i])) { return new LogFilteredLine(logline); } } return null; }
The LogFilteredLineWriter
artifact reads the name of the output file from the job properties. The open
method opens the file for writing. If a checkpoint object is provided, the artifact continues writing at the end of the file; otherwise, it overwrites the file if it exists. The writeItems
method writes filtered items to the output file:
@Override public void writeItems(List<Object> items) throws Exception { /* Write the filtered lines to the output file */ for (int i = 0; i < items.size(); i++) { LogFilteredLine filtLine = (LogFilteredLine) items.get(i); bwriter.write(filtLine.toString()); bwriter.newLine(); } }
The InfoJobListener
batch artifact implements a simple listener that writes log messages when the job starts and when it ends:
@Dependent @Named("InfoJobListener") public class InfoJobListener implements JobListener { ... @Override public void beforeJob() throws Exception { logger.log(Level.INFO, "The job is starting"); } @Override public void afterJob() throws Exception { ... } }
The InfoItemProcessListener
batch artifact implements the ItemProcessListener
interface for chunk steps:
@Dependent @Named("InfoItemProcessListener") public class InfoItemProcessListener implements ItemProcessListener { ... @Override public void beforeProcess(Object o) throws Exception { LogLine logline = (LogLine) o; llogger.log(Level.INFO, "Processing entry {0}", logline); } ... }
The task step is implemented by the MobileBatchlet
artifact, which computes what percentage of the filtered log entries are purchases:
@Override public String process() throws Exception { /* Get properties from the job definition file */ ... /* Count from the output of the previous chunk step */ breader = new BufferedReader(new FileReader(fileName)); String line = breader.readLine(); while (line != null) { String[] lineSplit = line.split(", "); if (buyPage.compareTo(lineSplit[1]) == 0) pageVisits++; totalVisits++; line = breader.readLine(); } breader.close(); /* Write the result */ ... }
The index.xhtml
page contains a text area that shows the web server log. The page provides a button for the user to submit the batch job and navigate to the next page:
<body> ... <textarea cols="90" rows="25" readonly="true">#{jsfBean.getInputLog()}</textarea> <p> </p> <h:form> <h:commandButton value="Start Batch Job" action="#{jsfBean.startBatchJob()}" /> </h:form> </body>
This page calls the methods of the managed bean to show the log file and submit the batch job.
The jobstarted.xhtml
page provides a button to check the current status of the batch job and displays the results when the job finishes:
<p>Current Status of the Job: <b>#{jsfBean.jobStatus}</b></p> <p>#{jsfBean.showResults()}</p> <h:form> <h:commandButton value="Check Status" action="jobstarted" rendered="#{jsfBean.completed==false}" /> </h:form>
The JsfBean
managed bean submits the job to the batch runtime, checks on the status of the job, and reads the results from a text file.
The startBatchJob
method submits the job to the batch runtime:
/* Submit the batch job to the batch runtime. * JSF Navigation method (return the name of the next page) */ public String startBatchJob() { jobOperator = BatchRuntime.getJobOperator(); execID = jobOperator.start("webserverlog", null); return "jobstarted"; }
The getJobStatus
method checks the status of the job:
/* Get the status of the job from the batch runtime */ public String getJobStatus() { return jobOperator.getJobExecution(execID).getBatchStatus().toString(); }
The showResults
method reads the results from a text file.
You can use either NetBeans IDE or Maven to build, package, deploy, and run the webserverlog
example application.
Make sure that GlassFish Server has been started (see Starting and Stopping GlassFish Server).
From the File menu, choose Open Project.
In the Open Project dialog box, navigate to:
tut-install/examples/batch
Select the webserverlog
folder.
Click Open Project.
In the Projects tab, right-click the webserverlog
project and select Run.
This command builds and packages the application into a WAR file, webserverlog.war
, located in the target/
directory; deploys it to the server; and launches a web browser window at the following URL:
http://localhost:8080/webserverlog/
Make sure that GlassFish Server has been started (see Starting and Stopping GlassFish Server).
In a terminal window, go to:
tut-install/examples/batch/webserverlog/
Enter the following command to deploy the application:
mvn install
Open a web browser window at the following URL:
http://localhost:8080/webserverlog/
The phonebilling
example application, located in the tut-install/examples/batch/phonebilling/
directory, demonstrates how to use the batch framework in Java EE to implement a phone billing system. This example application processes a log file of phone calls and creates a bill for each customer.
The phonebilling
example application consists of the following elements.
A job definition file (phonebilling.xml
) that uses the Job Specification Language (JSL) to define a batch job with two chunk steps. The first step reads call records from a log file and associates them with a bill. The second step computes the amount due and writes each bill to a text file.
A Java class (CallRecordLogCreator
) that creates the log file for the batch job. This is an auxiliary component that does not demonstrate any key functionality in this example.
Two Java Persistence API (JPA) entities (CallRecord
and PhoneBill
) that represent call records and customer bills. The application uses a JPA entity manager to store instances of these entities in a database.
Three batch artifacts (CallRecordReader
, CallRecordProcessor
, and CallRecordWriter
) that implement the first step of the application. This step reads call records from the log file, associates them with a bill, and stores them in a database.
Four batch artifacts (BillReader
, BillProcessor
, BillWriter
, and BillPartitionMapper
) that implement the second step of the application. This step is a partitioned step that gets each bill from the database, calculates the amount due, and writes it to a text file.
Two Facelets pages (index.xhtml
and jobstarted.xhtml
) that provide the front end of the batch application. The first page shows the log file that will be processed by the batch job, and the second page enables the user to check on the status of the job and shows the resulting bill for each customer.
A managed bean (JsfBean
) that is accessed from the Facelets pages. The bean submits the job to the batch runtime, checks on the status of the job, and reads the text files for each bill.
The phonebilling.xml
job definition file is located in the WEB-INF/classes/META-INF/batch-jobs/
directory. The file specifies three job-level properties and two steps:
<?xml version="1.0" encoding="UTF-8"?> <job id="phonebilling" xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="1.0"> <properties> <property name="log_file_name" value="log1.txt"/> <property name="airtime_price" value="0.08"/> <property name="tax_rate" value="0.07"/> </properties> <step id="callrecords" next="bills"> ... </step> <step id="bills"> ... </step> </job>
The first step is defined as follows:
<step id="callrecords" next="bills"> <chunk checkpoint-policy="item" item-count="10"> <reader ref="CallRecordReader"></reader> <processor ref="CallRecordProcessor"></processor> <writer ref="CallRecordWriter"></writer> </chunk> </step>
This step is a normal chunk step that specifies the batch artifacts that implement each phase of the step. The batch artifact names are not fully qualified class names, so the batch artifacts are CDI beans annotated with @Named
.
The second step is defined as follows:
<step id="bills"> <chunk checkpoint-policy="item" item-count="2"> <reader ref="BillReader"> <properties> <property name="firstItem" value="#{partitionPlan['firstItem']}"/> <property name="numItems" value="#{partitionPlan['numItems']}"/> </properties> </reader> <processor ref="BillProcessor"></processor> <writer ref="BillWriter"></writer> </chunk> <partition> <mapper ref="BillPartitionMapper"/> </partition> <end on="COMPLETED"/> </step>
This step is a partitioned chunk step. The partition plan is specified through the BillPartitionMapper
artifact instead of using the plan
element.
The CallRecord
entity is defined as follows:
@Entity public class CallRecord implements Serializable { @Id @GeneratedValue private Long id; @Temporal(TemporalType.DATE) private Date datetime; private String fromNumber; private String toNumber; private int minutes; private int seconds; private BigDecimal price; public CallRecord() { } public CallRecord(String datetime, String from, String to, int min, int sec) throws ParseException { ... } public CallRecord(String jsonData) throws ParseException { ... } /* ... Getters and setters ... */ }
The id
field is generated automatically by the JPA implementation to store and retrieve CallRecord
objects to and from a database.
The second constructor creates a CallRecord
object from an entry of JSON data in the log file using the JSON Processing API. Log entries look as follows:
{"datetime":"03/01/2013 04:03","from":"555-0101", "to":"555-0114","length":"03:39"}
The PhoneBill
entity is defined as follows:
@Entity public class PhoneBill implements Serializable { @Id private String phoneNumber; @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST) @OrderBy("datetime ASC") private List<CallRecord> calls; private BigDecimal amountBase; private BigDecimal taxRate; private BigDecimal tax; private BigDecimal amountTotal; public PhoneBill() { } public PhoneBill(String number) { this.phoneNumber = number; calls = new ArrayList<>(); } public void addCall(CallRecord call) { calls.add(call); } public void calculate(BigDecimal taxRate) { ... } /* ... Getters and setters ... * }
The OneToMany
annotation defines the relationship between a bill and its call records. The FetchType.EAGER
attribute specifies that the collection should be retrieved eagerly. The CascadeType.PERSIST
attribute indicates that the elements in the call list should be automatically persisted when the phone bill is persisted. The OrderBy
annotation defines an order for retrieving the elements of the call list from the database.
The batch artifacts use instances of these two entities as items to read, process, and write.
For more information on the Java Persistence API, see Chapter 37, "Introduction to the Java Persistence API". For more information on the JSON Processing API, see Chapter 19, "JSON Processing".
The first step is composed of the CallRecordReader
, CallRecordProcessor
, and CallRecordWriter
batch artifacts.
The CallRecordReader
artifact reads call records from the log file:
@Dependent @Named("CallRecordReader") public class CallRecordReader implements ItemReader { private ItemNumberCheckpoint checkpoint; private String fileName; private BufferedReader breader; @Inject JobContext jobCtx; /* ... Override the open, close, readItem, * and checkpointInfo methods ... */ }
The open
method reads the log_filename
property and opens the log file with a buffered reader:
fileName = jobCtx.getProperties().getProperty("log_file_name"); breader = new BufferedReader(new FileReader(fileName));
If a checkpoint object is provided, the open
method advances the reader up to the last checkpoint. Otherwise, this method creates a new checkpoint object. The checkpoint object keeps track of the line number from the last committed chunk.
The readItem
method returns a new CallRecord
object or null at the end of the log file:
@Override public Object readItem() throws Exception { /* Read a line from the log file and * create a CallRecord from JSON */ String callEntryJson = breader.readLine(); if (callEntryJson != null) { checkpoint.nextItem(); return new CallRecord(callEntryJson); } else return null; }
The CallRecordProcessor
artifact obtains the airtime price from the job properties, calculates the price of each call, and returns the call object. This artifact overrides only the processItem
method.
The CallRecordWriter
artifact associates each call record with a bill and stores the bill in the database. This artifact overrides the open
, close
, writeItems
, and checkpointInfo
methods. The writeItems
method looks like this:
@Override public void writeItems(List<Object> callList) throws Exception { for (Object callObject : callList) { CallRecord call = (CallRecord) callObject; PhoneBill bill = em.find(PhoneBill.class, call.getFromNumber()); if (bill == null) { /* No bill for this customer yet, create one */ bill = new PhoneBill(call.getFromNumber()); bill.addCall(call); em.persist(bill); } else { /* Add call to existing bill */ bill.addCall(call); } } }
The second step is composed of the BillReader
, BillProcessor
, BillWriter
, and BillPartitionMapper
batch artifacts. This step gets the phone bills from the database, computes the tax and total amount due, and writes each bill to a text file. Since the processing of each bill is independent of the others, this step can be partitioned and run in more than one thread.
The BillPartitionMapper
artifact specifies the number of partitions and the parameters for each partition. In this example, the parameters represent the range of items each partition should process. The artifact obtains the number of bills in the database to calculate these ranges. It provides a partition plan object that overrides the getPartitions
and getPartitionProperties
methods of the PartitionPlan
interface. The getPartitions
method looks like this:
@Override public Properties[] getPartitionProperties() { /* Assign an (approximately) equal number of elements * to each partition. */ long totalItems = getBillCount(); long partItems = (long) totalItems / getPartitions(); long remItems = totalItems % getPartitions(); /* Populate a Properties array. Each Properties element * in the array corresponds to a partition. */ Properties[] props = new Properties[getPartitions()]; for (int i = 0; i < getPartitions(); i++) { props[i] = new Properties(); props[i].setProperty("firstItem", String.valueOf(i * partItems)); /* Last partition gets the remainder elements */ if (i == getPartitions() - 1) { props[i].setProperty("numItems", String.valueOf(partItems + remItems)); } else { props[i].setProperty("numItems", String.valueOf(partItems)); } return props; }
The BillReader
artifact obtains the partition parameters as follows:
@Dependent @Named("BillReader") public class BillReader implements ItemReader { @Inject @BatchProperty(name = "firstItem") private String firstItemValue; @Inject @BatchProperty(name = "numItems") private String numItemsValue; private ItemNumberCheckpoint checkpoint; @PersistenceContext private EntityManager em; private Iterator iterator; @Override public void open(Serializable ckpt) throws Exception { /* Get the range of items to work on in this partition */ long firstItem0 = Long.parseLong(firstItemValue); long numItems0 = Long.parseLong(numItemsValue); if (ckpt == null) { /* Create a checkpoint object for this partition */ checkpoint = new ItemNumberCheckpoint(); checkpoint.setItemNumber(firstItem0); checkpoint.setNumItems(numItems0); } else { checkpoint = (ItemNumberCheckpoint) ckpt; } /* Adjust range for this partition from the checkpoint */ long firstItem = checkpoint.getItemNumber(); long numItems = numItems0 - (firstItem - firstItem0); ... } ... }
This artifact also obtains an iterator to read items from the JPA entity manager:
/* Obtain an iterator for the bills in this partition */ String query = "SELECT b FROM PhoneBill b ORDER BY b.phoneNumber"; Query q = em.createQuery(query).setFirstResult((int) firstItem) .setMaxResults((int) numItems); iterator = q.getResultList().iterator();
The BillProcessor
artifact iterates over the list of call records in a bill and calculates the tax and total amount due for each bill.
The BillWriter
artifact writes each bill to a plain text file.
The index.xhtml
page contains a text area that shows the log file of call records. The page provides a button for the user to submit the batch job and navigate to the next page:
<body> <h1>The Phone Billing Example Application</h1> <h2>Log file</h2> <p>The batch job analyzes the following log file:</p> <textarea cols="90" rows="25" readonly="true">#{jsfBean.createAndShowLog()}</textarea> <p> </p> <h:form> <h:commandButton value="Start Batch Job" action="#{jsfBean.startBatchJob()}" /> </h:form> </body>
This page calls the methods of the managed bean to show the log file and submit the batch job.
The jobstarted.xhtml
page provides a button to check the current status of the batch job and displays the bills when the job finishes:
<p>Current Status of the Job: <b>#{jsfBean.jobStatus}</b></p> <h:dataTable var="_row" value="#{jsfBean.rowList}" border="1" rendered="#{jsfBean.completed}"> <!-- ... show results from jsfBean.rowList ... --> </h:dataTable> <!-- Render the check status button if the job has not finished --> <h:form> <h:commandButton value="Check Status" rendered="#{jsfBean.completed==false}" action="jobstarted" /> </h:form>
The JsfBean
managed bean submits the job to the batch runtime, checks on the status of the job, and reads the text files for each bill.
The startBatchJob
method of the bean submits the job to the batch runtime:
/* Submit the batch job to the batch runtime. * JSF Navigation method (return the name of the next page) */ public String startBatchJob() { jobOperator = BatchRuntime.getJobOperator(); execID = jobOperator.start("phonebilling", null); return "jobstarted"; }
The getJobStatus
method of the bean checks the status of the job:
/* Get the status of the job from the batch runtime */ public String getJobStatus() { return jobOperator.getJobExecution(execID).getBatchStatus().toString(); }
The getRowList
method of the bean creates a list of bills to be displayed on the jobstarted.xhtml
JSF page using a table.
You can use either NetBeans IDE or Maven to build, package, deploy, and run the phonebilling
example application.
Make sure that GlassFish Server has been started (see Starting and Stopping GlassFish Server).
From the File menu, choose Open Project.
In the Open Project dialog box, navigate to:
tut-install/examples/batch
Select the phonebilling
folder.
Click Open Project.
In the Projects tab, right-click the phonebilling
project and select Run.
This command builds and packages the application into a WAR file, phonebilling.war
, located in the target/
directory; deploys it to the server; and launches a web browser window at the following URL:
http://localhost:8080/phonebilling/
Make sure that GlassFish Server has been started (see Starting and Stopping GlassFish Server).
In a terminal window, go to:
tut-install/examples/batch/phonebilling/
Enter the following command to deploy the application:
mvn install
Open a web browser window at the following URL:
http://localhost:8080/phonebilling/


The Tragedy of MacBeth
by William Shakespeare
Act 5, Scene 1
Additional Information
- Year Published: 1607
- Language: English
- Country of Origin: England
- Source: Richard Grant White, ed. The Complete Works of William Shakespeare (New York: Sully and Kleinteich)
-
Readability:
- Flesch–Kincaid Level: 11.0
- Word Count: 666
- Genre: Tragedy
- Keywords: betrayal, envy, murder, power, revenge, tragedy
- ✎ Cite This
Downloads
SCENE. Dunsinane. Ante-room in the castle.
(Enter a Doctor of Physic and a Waiting-Gentlewoman)
Doctor
I have two nights watched with you, but can perceive
no truth in your report. When was it she last walked?
Gentlewoman
Since his majesty went into the field, I have seen
her rise from her bed, throw her night-gown upon
her, unlock her closet, take forth paper, fold it,
write upon't, read it, afterwards seal it, and again
return to bed; yet all this while in a most fast sleep.
Doctor
A great perturbation in nature, to receive at once
the benefit of sleep, and do the effects of
watching! In this slumbery agitation, besides her
walking and other actual performances, what, at any
time, have you heard her say?
Gentlewoman
That, sir, which I will not report after her.
Doctor
You may to me: and 'tis most meet you should.
Gentlewoman
Neither to you nor any one; having no witness to
confirm my speech.
(Enter LADY MACBETH, with a taper)
Lo you, here she comes! This is her very guise;
and, upon my life, fast asleep. Observe her; stand close.
Doctor
How came she by that light?
Gentlewoman
Why, it stood by her: she has light by her
continually; 'tis her command.

Gentlewoman
Ay, but their sense is shut.
Doctor
What is it she does now? Look, how she rubs her hands.
Gentlewoman
It is an accustomed action with her, to seem thus
washing her hands: I have known her continue in
this a quarter of an hour.
LADY MACBETH
Yet here's a spot.
Doctor
Hark! she speaks: I will set down what comes from
her, to satisfy my remembrance the more strongly.
LADY MACBETH
Out, damned spot! out, I say!—One: two: why,
then, 'tis time to do't.—Hell is murky!—Fie, my
lord, fie! a soldier, and afeard? What need we
fear who knows it, when none can call our power to
account?—Yet who would have thought the old man
to have had so much blood in him.
Doctor
Do you mark that?
LADY MACBETH
The thane of Fife had a wife: where is she now?—
What, will these hands ne'er be clean?—No more o'
that, my lord, no more o' that: you mar all with
this starting.
Doctor
Go to, go to; you have known what you should not.
Gentlewoman
She has spoke what she should not, I am sure of
that: heaven knows what she has known.
 Oh, oh, oh!
Doctor
What a sigh is there! The heart is sorely charged.
Gentlewoman
I would not have such a heart in my bosom for the
dignity of the whole body.
Doctor
Well, well, well,—
Gentlewoman
Pray God it be, sir.
Doctor
This disease is beyond my practise: yet I have known
those which have walked in their sleep who have died
holily in their beds.

Doctor
Even so?
 What's
done cannot be undone.—To bed, to bed, to bed!
(Exit)
Doctor
Will she go now to bed?
Gentlewoman
Directly.
Doctor
Foul whisperings are abroad: unnatural deeds
Do breed unnatural troubles: infected minds
To their deaf pillows will discharge their secrets:
More needs she the divine than the physician.
God, God forgive us all! Look after her;
Remove from her the means of all annoyance,
And still keep eyes upon her. So, good night:
My mind she has mated, and amazed my sight.
I think, but dare not speak.
Gentlewoman
Good night, good doctor.
(Exeunt)


fit_tipcurve_data¶
-
Data_Reduction.tipping.
fit_tipcurve_data
(elev, Tsys, Tatm=250, method='linear')¶ fits system temperatures to airmass
The length of ‘elev’ and the first axis of ‘Tsys’ must be the same
If the Tsys array has two or more dimensions then a fit is done on the data over the first index for all the values of the other indices and the results will have the same shape as the indices 1..N
If Tatm is given, the radiative transfer equation will be used and K/am will be Tatm*tau(zenith). If it is not given, the straight-line low-tau equation is used and Tatm*tau(zenith) will be the slope of the line.
:param elev : 1D array of elevations :type elev : list or 1D numpy.array of float
:param Tsys : ND array of system temperatures :type Tsys : list or numpy.array of float
:param Tatm : mean air temperature along path :type Tatm : float
:param linear : use the linear (low tau) approximation :type linear : True


[§269-8.5] Annual financial reports. All annual financial reports required to be filed with the commission by public utilities shall include a certification that such report conforms with the applicable uniform system of accounts adopted by the commission. [L 1977, c 15, §1]


◆ BlindSeedNtHash()
| nthash::BlindSeedNtHash::BlindSeedNtHash |
( |
const char * |
seq, |
|
|
const std::vector< std::string > & |
seeds, |
|
|
typedefs::NUM_HASHES_TYPE |
num_hashes_per_seed, |
|
|
typedefs::K_TYPE |
k, |
|
|
ssize_t |
pos = 0 |
|
) |
| |
Construct an ntHash object for hashing spaced seeds on-the-fly.
- Parameters
-
| seq | C-string of the data. Only the first k characters will be used, starting from pos . |
| seeds | Vector of parsed spaced seed patterns (vectors of don't care positions) |
| num_hashes_per_seed | Number of hashes to generate per seed |
| k | K-mer size |
| pos | Position in seq to start hashing from |
◆ get_forward_hash()
| uint64_t * nthash::BlindSeedNtHash::get_forward_hash |
( |
| ) |
const |
|
inline |
Get the hash values of the forward strand.
- Returns
- Array of forward hash value arrays for each seed
◆ get_hash_num()
| unsigned nthash::BlindSeedNtHash::get_hash_num |
( |
| ) |
const |
|
inline |
◆ get_hash_num_per_seed()
| typedefs::NUM_HASHES_TYPE nthash::BlindSeedNtHash::get_hash_num_per_seed |
( |
| ) |
const |
|
inline |
Get the number of hashes generated per seed.
- Returns
- Number of hashes per seed
◆ get_k()
| typedefs::K_TYPE nthash::BlindSeedNtHash::get_k |
( |
| ) |
const |
|
inline |
Get the length of the k-mers.
- Returns
k
◆ get_pos()
| ssize_t nthash::BlindSeedNtHash::get_pos |
( |
| ) |
const |
|
inline |
Get the position of last hashed k-mer or the k-mer to be hashed if roll() has never been called on this NtHash object.
- Returns
- Position of the most recently hashed k-mer's first base-pair
◆ get_reverse_hash()
| uint64_t * nthash::BlindSeedNtHash::get_reverse_hash |
( |
| ) |
const |
|
inline |
Get the hash values of the reverse strand.
- Returns
- Array of reverse-complement hash value arrays for each seed
◆ hashes()
| const uint64_t * nthash::BlindSeedNtHash::hashes |
( |
| ) |
const |
|
inline |
Get the array of current hash values (length = get_hash_num()
)
- Returns
- Pointer to the hash array
◆ roll()
| void nthash::BlindSeedNtHash::roll |
( |
char |
char_in | ) |
|
Like the NtHash::roll() function, but instead of advancing in the sequence BlindSeedNtHash object was constructed on, the provided character char_in
is used as the next base.
◆ roll_back()
| void nthash::BlindSeedNtHash::roll_back |
( |
char |
char_in | ) |
|
The documentation for this class was generated from the following file:


{% extends "base.html" %} {% block content %}
Manage Mode
You must enter an item name.
You must select a category.


--- layout: project categories: projects client: Titanium Falcon client_url: http://www.titaniumfalcon.com client_color: 72cbc9 video_title: "Introducing the Talon" video_id: 138032895 video_thumb: titanium-falcon.png featured: false ---
Director — Cole Mueller
Producer — Cole Mueller, nus Kumar, Juan Guo
Cinematographer — Grant Gilkeson
Editor — Cole Mueller


This test runs in the browser's console, so please open dev-tools and choose "console" to watch.
It should prompt you to login and load your profile as a string


Favourite Band
This is a project involving my favourite band in Kenya.
I create stylish,clean and creative websites.
A software developer student at Moringa School who is very enthusiastic about designing and creating creative detailed and usable websites.I love software development because it enables me to create anything I want and also develop problem solving skills.If you don't find me polishing up on my skills,then I am probably somewhere playing soccer or designing outfits.
This is a project involving my favourite band in Kenya.
This is a project involving Anita's Kitchen Menu.
This is a project involving a school website.
This is a project involving my snearkers collection.


Dominic Panzino
I use this simple website as a repository of some of my project documentation and for showcasing my personal projects. I have tried to keep it as simple as possible, to get right to the point. Not shown are projects done for school or classes, or for work purposes; only personal hobby projects are shown here.
I can be contacted at<EMAIL_ADDRESS>Last Updated: Sep 25, 2020
Shop capabilities
Tools and Machines
Building a Touch Probe: (Summer 2020) Making my own contact probe for a CMM or for our CNC machine.
Turbomolecular Pump: (Spring 2020) Designing and making a turbomolecular pump to obtain extremely low vaccuums for future projects.
Building a Rotary Broach holder: (Winter 2019-2020) Building a rotary broach holder and broaches.
Manual Tool Setter: (Winter 2019-2020) Building a setup to hold a dial test indicator for setting Z-offsets on old CNC machines.
Turbo Spindle MkI: (Summer 2018) A small air turbine designed for high-RPM tools like carbide burs.
Peerless Watchmaking Lathe Rebuild: (Winter 2016-2017) I add a carriage, cross-slide, toolpost, leadscrews, and dials to an old watchmaking lathe.
Gyroscope and Gimbals: (Fall 2016) A cute gyroscope and gimbal set built as fun toy.
Refurbishing a 1948 Farquhar Sawmill: (2016-2017) A 60" circular sawmill. Salvaged after being abandoned in a collapsed building and rebuilt.
Other
New Storage Building Construction: (Spring 2020-Spring 2021) Construction of a storage barn and a building to cover the sawmill.
Steam Launch: (Jan 2019) A 25ft steam-powered boat. Will build the engine and boiler soon.
Player Piano MIDI Upgrade: (Fall & Winter 2019) Modifying an 1910s-era pnumatic player piano to be able to also be played by a computer via MIDI file.
Mead Brewing: (Fall 2019) Making wine from honey in the comfort of my dorm room.


The Users tab displays all content in the DB2AUTH.USERS table except the password. The query for this tab display is displayed in the 'Ad hoc SQL' tab to the right.
The 'Users' tab next to the 'Ad hoc SQL' tab is the actual Users tab that the module pulls up. If the tab has not loaded properly, you have not installed the plug-in, are not connected to the proper database, or do not have the proper privileges. In that case, click here for a sample view.
There are three menu options:
You will also see three action icons:


|
Order number
|
Date
|
Customer name
|
Customer location
|
Amount of items
|
Items cost
|
Shipping cost
|
|---|
|
ID
|
Name
|
Sell by
|
Amount sold
|
Price per unit
|
Total cost
|
Part of discount
|
|---|


{# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -#} {% extends "admin/base.html" %} {% import "admin/utils/pagination.html" as pagination %} {% macro render_field(label, field, input_id, placeholder=None, class=None) %}
| Attribute | Value |
|---|---|
| Upload limit | {% if project.upload_limit %} {{ project.upload_limit|filesizeformat(binary=True) }} {% else %} Default ({{ MAX_FILESIZE|filesizeformat(binary=True) }}) {% endif %} |
| User | Role | |
|---|---|---|
| {{ role.user.username }} | {{ role.role_name }} |
|
| Release version | Created | Uploader | Author email | {% for release in releases %}
|---|---|---|---|
| {{ release.project.name }}-{{ release.version }} | {{ release.created }} | {% if release.uploader %} {{ release.uploader.username }} {% endif %} | {{ release.author_email }} |
| name | version | date | submitted_by | submitted_from | action |
|---|---|---|---|---|---|
| {{ entry.name }} | {{ entry.version }} | {{ entry.submitted_date }} | {{ entry.submitted_by.username }} | {{ entry.submitted_from }} | {{ entry.action }} |
| name | created |
|---|---|
| {{ project.normalized_name }} | {{ project.created }} |
| name | created |
|---|---|
| {{ project.normalized_name }} | {{ project.created }} |


The man who inspired many people with his intellect
"Albert Einstein was a very intelligent man"
Here's a timeline of Albert Einstein's life
1879 - Born in Germany
1880 - Moved to Munich with his family where Einstein's father and his uncle Jakob founded a company that manufactured electrical equipment based on direct current
1892 - At age 13, Einstein was introduced to Kant's Critique of Pure Reason, and Kant became his favorite philosopher
1896 - At 17, he enrolled in the four-year mathematics and physics teaching diploma program at the Zürich Polytechnic
1908 - He was recognized as a leading scientist and was appointed lecturer at the University of Bern
1933 - In February 1933, while on a visit to the United States, Einstein knew he could not return to Germany with the rise to power of the Nazis under Germany's new chancellor
1955 - On 17 April 1955, Einstein experienced internal bleeding caused by the rupture of an abdominal aortic aneurysm, which had previously been reinforced surgically by Rudolph Nissen in 1948
"Albert Einstein was a theoretical physicist who published the special and general theories of relativity and contributed in other areas of physics. He won the Nobel Prize in physics for his explanation of the photoelectric effect."


--- layout: archive title: Zulip Chat Archive permalink: /stream/113488-general/topic/recursive.20split.html ---
Do we have a recursive split tactic? My goal looks likes a ∧ b ∧ c ∧ d
and I would like to write one word and get four non-nested goals.
There's only one “word” in refine ⟨_, _, _, _⟩
. :wink:
Obviously, this is not exactly as readable as I hoped for, but at least this indeed does the trick.
repeat { any_goals { split } }
:)
...which at least is a bit more general and could be extracted into a new tactic
Isn't ther also a rcases
in mathlib that does this?
that destructs hypotheses
repeat { any_goals { split } }
:smiley:
How efficient is that? For g1 ∧ g2 ∧ g3 ∧ g4
, I'm guessing that's 4 applications of any_goals
, but any_goals
would also test all previously split
goals each time, right? I suppose it could be improved by “remembering” that split
failed for a visited goal.
How big are your conjunctions that you expect this to be a problem :frowning: ? split
isn't exactly an expensive tactic.
I like that this version seems easy to turn into a new tactic.
You can also use constructor_matching* _ ∧ _
to make sure it only splits conjunctions
Yes, hidden in subset image. After much effort, I managed to minimize to:
example (α β : Type) (f : α → β) (s : set α) (s' : set β) (x : β) : f '' s ⊆ s' ∧ x ∈ f '' s := begin -- refine ⟨_, _⟩, repeat { all_goals { split } }, end
Last updated: Apr 24 2020 at 19:02 UTC


My
8-year old was proud to remind me that today was the two-year anniversary of
9/11. I was surprised that he knew and grateful to his school for taking the
time to discuss it. He then went on to tell me how cool he thought the
explosions were, which left me less pleased with his school. When I told him
about my own experiences that day and how many people died, it immediately took
all of the "coolness" right out of the day for him.
George Bullock, a
colleague at MS who's birthday happens to fall on 9/11, has also had the
"coolness" taken out of the day for him and sent around a mail that starts this
way:
"Let us pause on 9/11 to remember and honor the thousands killed, maimed, put out of work, and traumatized two years ago; also to honor the heroic, living and dead, who rose to the occasion on that terrible day. May God rest their souls and keep and protect their loved ones. May God also keep and protect our men and women serving here and abroad. Yes, there is much difference of opinion about what's happening in the world today; nevertheless, I think we all support the men and women of our armed forces and wish them a safe return home. They sacrifice a lot to serve their country."
Personally, I try very hard not to let the terrorists get to me. Unfortunately, they have. Even time I get the anal probe treatment at the airport or a personal freedom is taken away by the Patriot Act or my sister-in-law is afraid to fly (and flat out refuses to fly on that day), they win. More subtly, ever time a US politician uses "terrorism" to push their own agenda, they also win. Please don't let them win. Have courage. Try to understand what it was that drove them to terrorism to attract our attention. Compare their lives to ours. But don't let them win. Don't let them take the right to the pursuit of happiness out of our lives.


Arctic adventurers struggle as climate change thins ice
Oslo: Two men trying to cross the Arctic Ocean on skis have run into difficulty as unusually thin ice has lengthened their journey and cut into their rations, their team said Saturday.
South African Mike Horn, 53, and Borge Ousland of Norway, 57 -- both experienced adventurers -- left Nome, Alaska by sailboat on August 25.
Since September 12, when they reached the sea ice, they have been travelling on skis pulling sleds with supplies.
They had planned to complete their journey by reaching the edge of the sea ice by mid-November.
"Because of climate change the ice is thinner than usual, which is more prone to drift," a spokesman for the expedition, Lars Ebbesen, told AFP.
Normally there would be a positive drift of a few extra kilometres per day, "but the winds are pushing the ice toward Greenland and they have gone backwards three to five kilometres per day," he said.
The team now hopes to reach their goal within 10 or 12 days, which is how long their rations will last.
"There is no danger, no huge drama. But it is touch and go -- a mad dash to reach the goal."
"We are considering how to get more food to them in case it takes longer."
He said weather patterns were now changing and more favourable northerly winds were forecast.
The pair have not asked to be evacuated.
A spokesman for the Joint Rescue Coordination Centre in Northern Norway, Bard Mortensen, told AFP rescuers were exploring possibilities and "considering precautionary plans at this point" in case an evacuation were to become necessary.
"There is no evacuation underway ... they are determined at this point to make it on their own," Mortensen said.
A helicopter in Longyearbyen, the main town in Norway's Svalbard archipelago, would be able to rescue the pair, or a ship, he said.
Ebbesen said Horn and Ousland were in "surprisingly good condition" considering their feat.
"They have a little frostbite but that's quite normal."
Horn's 26-year-old daughter, Annika Horn, meanwhile told French newspaper Le Parisien that she had heard from her father and he sounded very downbeat.
"His morale is very low. I've never seen him like that, in such an extreme state of fatigue... My sister Jessica and I just want him to come home soon," she said.


The Department of Information technology at Jeppiaar Engineering College is renowned for cutting edge research and for imparting state of the art education. We attract some of the brightest students and faculty. We invite you to join us in the excitement and be an active participant in the growth of the department.
The Department of Information Technology at Jeppiaar Engineering College is actively seeking applications for faculty positions at all levels in all areas of Information Technology. Applications for sabbatical and short-term positions are also welcome. For more information please direct all enquiries to head [AT] jeppiaar/it.in or see the latest faculty advertisement.
In addition to its already strong and well known undergraduate programme, IT at JEC has also emerged as a leading department for research and graduate studies in Information Technology in India. Following are some reasons as to why jec@it is an attractive place to join as a faculty member.
Strong Research
The department has a strong faculty, all Ph. D.'s from leading universities and active in research. The department also attracts a regular stream of visiting faculty members. This provides excellent opportunities for collaboration and joining existing research groups.
The department has a strong focus on research and provides an excellent research environment. The department already has strong groups in many research areas and is looking to grow in other areas of IT.
The department regularly publishes in leading Journals and Conferences in IT. Check out the sample list of publications.
The department carries out a significant number of sponsored projects funded by both industry and government agencies. With a large number of multinational and technology giants opening up operations in India, the opportunities for sponsored research and consultancy assignments are excellent. The department provides encouragement and support to new faculty members to build up research activity through these channels.
The department promotes and encourages inter-disciplinary research, both within the department and outside.
Finally, the department has excellent infrastructure with laboratories supported by Microsoft, Cisco, Philips, Oracle and RedHat.
Strong Graduate
The department has one of the strongest Ph. D. programmes in IT in the country with a growing number of Ph. D. students. Our graduates have done extremely well. Click here to see where some of our PhD graduates are working. Highlights of some achievements of our Ph. D. students can be seen here and also check out the sample Ph. D. publications.
The department runs a 2-year Masters by Research (MSR) programme for students with exceptionally strong background in IT. With only a semester of course work, the student spends about an year and a half on a thesis under the supervision of a faculty member.
The department runs a two year M. Tech. in CSE in with a full year of thesis work
Finally our undergraduates also have a strong tradition of carrying out research in the B. Tech. programme. Check out the sample undergraduate publications.
Faculty Benefits
Faculty members at JEC enjoy several benefits. Some of these are...
On-campus housing with free broadband Internet connections and telephone bill reimbursements.
Contingency grants which may be used to pay membership of professional societies or for buying books.
Flexibility to take up Industrial consultancy assignments
Quality Of Campus Living
JEPPIAAR ENGINEERING COLLEGE has an excellent, green, spacious and peaceful campus right in the heart of CHENNAI with all the amenities of the city easily accessible.
The campus has excellent facilities which include shopping centres, a well equipped health centre and sports facilities which include tenniS, badminton, table tennis, gymnasiums, jogging tracks and cricket, football and hockey grounds,volley ball court.
The campus has regular cultural events which include music and dance programmes, movies and various other activities organized by students.