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.
55.8.1.2 The LogLine and LogFilteredLine ItemsThe 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(); } }55.8.1.4 The Listener Batch Artifacts
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); } ... }55.8.1.5 The Task Step Batch Artifact
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 */ ... }55.8.1.6 The JavaServer Faces Pages
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>55.8.1.7 The Managed Bean
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/
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.3