开发运行环境:NetBeans7.3.1。
关于Batch 1.0,请参考《JavaEE7 十大新特性》。
1. SalesReader.java
SalesReader.java是ItemReader,每次读取sales.csv的一行数据。
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.glassfish.movieplex7.batch;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Serializable;
import javax.batch.api.chunk.AbstractItemReader;
import javax.enterprise.context.Dependent;
import javax.inject.Named;
/**
*
* @author pmma
*/
@Named
@Dependent
public class SalesReader extends AbstractItemReader {
private BufferedReader reader;
@Override
public void open(Serializable checkpoint) throws Exception {
reader = new BufferedReader(
new InputStreamReader(
Thread.currentThread()
.getContextClassLoader()
.getResourceAsStream("META-INF/sales.csv")));
}
@Override
public String readItem() {
String string = null;
try {
string = reader.readLine();
} catch (IOException ex) {
ex.printStackTrace();
}
return string;
}
}
2. SalesProcessor.java
SalesProcessor.java是ItemProcessor,每次分析读取SalesReader提供的Item数据,即读取的sales.csv的一行数据,把电影id和金额信息保存到Sales Entity中。
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.glassfish.movieplex7.batch;
import java.util.StringTokenizer;
import javax.batch.api.chunk.ItemProcessor;
import javax.enterprise.context.Dependent;
import javax.inject.Named;
import org.glassfish.movieplex7.entities.Sales;
/**
*
* @author pmma
*/
@Named
@Dependent
public class SalesProcessor implements ItemProcessor {
@Override
public Sales processItem(Object s) {
Sales sales = new Sales();
StringTokenizer tokens = new StringTokenizer((String) s, ",");
sales.setId(Integer.parseInt(tokens.nextToken()));
sales.setAmount(Float.parseFloat(tokens.nextToken()));
return sales;
}
}
关于Batch 1.0,请参考《JavaEE7 十大新特性》。
1. SalesReader.java
SalesReader.java是ItemReader,每次读取sales.csv的一行数据。
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.glassfish.movieplex7.batch;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Serializable;
import javax.batch.api.chunk.AbstractItemReader;
import javax.enterprise.context.Dependent;
import javax.inject.Named;
/**
*
* @author pmma
*/
@Named
@Dependent
public class SalesReader extends AbstractItemReader {
private BufferedReader reader;
@Override
public void open(Serializable checkpoint) throws Exception {
reader = new BufferedReader(
new InputStreamReader(
Thread.currentThread()
.getContextClassLoader()
.getResourceAsStream("META-INF/sales.csv")));
}
@Override
public String readItem() {
String string = null;
try {
string = reader.readLine();
} catch (IOException ex) {
ex.printStackTrace();
}
return string;
}
}
2. SalesProcessor.java
SalesProcessor.java是ItemProcessor,每次分析读取SalesReader提供的Item数据,即读取的sales.csv的一行数据,把电影id和金额信息保存到Sales Entity中。
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.glassfish.movieplex7.batch;
import java.util.StringTokenizer;
import javax.batch.api.chunk.ItemProcessor;
import javax.enterprise.context.Dependent;
import javax.inject.Named;
import org.glassfish.movieplex7.entities.Sales;
/**
*
* @author pmma
*/
@Named
@Dependent
public class SalesProcessor implements ItemProcessor {
@Override
public Sales processItem(Object s) {
Sales sales = new Sales();
StringTokenizer tokens = new StringTokenizer((String) s, ",");
sales.setId(Integer.parseInt(tokens.nextToken()));
sales.setAmount(Float.parseFloat(tokens.nextToken()));
return sales;
}
}
3. SalesWriter.java
SalesWriter.java是ItemWriter,批量提交多个每次分析读取SalesProcessor提供的Item数据,即把多个Sales Entities一次提交到数据库中。
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.glassfish.movieplex7.batch;
import java.util.List;
import javax.batch.api.chunk.AbstractItemWriter;
import javax.enterprise.context.Dependent;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
import org.glassfish.movieplex7.entities.Sales;
/**
*
* @author pmma
*/
@Named
@Dependent
public class SalesWriter extends AbstractItemWriter {
@PersistenceContext
EntityManager em;
@Override
@Transactional
public void writeItems(List list) {
for (Sales s : (List) list) {
em.persist(s);
}
}
}
说明:
(1)在writeItems上有 @Transactional批注,说明该方法是带事务的,这是JPA 2.1的新特性,即支持在任意一个POJO类上加事务。
4. Job XML配置文件:eod-sales.xml
<job id="endOfDaySales" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
<job id="endOfDaySales" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
version="1.0">
<step id="populateSales">
<chunk item-count="3" skip-limit="5">
<reader ref="salesReader"/>
<processor ref="salesProcessor"/>
<writer ref="salesWriter"/>
<skippable-exception-classes>
<include class="java.lang.NumberFormatException"/>
</skippable-exception-classes>
</chunk>
</step>
</job>
说明:
(1)endOfDaySales Job有一个Step,该Step有一个Chunk。
(2)在Chunk中,item-count="3",在这里表明一次处理3行销售数据。
(3)skippable-exception-classes:java.lang.NumberFormatException表明忽略该异常。
(4)skip-limit="5",表明最多忽略5次异常。
5. SalesBean.java
SalesBean.java是一个Managed Bean,负责启动Job,其中使用了JobOperator。
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.glassfish.movieplex7.batch;
import java.util.List;
import java.util.Properties;
import javax.batch.operations.JobOperator;
import javax.batch.operations.JobStartException;
import javax.batch.runtime.BatchRuntime;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import org.glassfish.movieplex7.entities.Sales;
/**
*
* @author pmma
*/
@Named
@RequestScoped
public class SalesBean {
@PersistenceUnit
EntityManagerFactory emf;
public void runJob() {
try {
JobOperator jo = BatchRuntime.getJobOperator();
long jobId = jo.start("eod-sales", new Properties());
System.out.println("Started job: with id: " + jobId);
} catch (JobStartException ex) {
ex.printStackTrace();
}
}
public List getSalesData() {
return emf.createEntityManager().createNamedQuery("Sales.findAll",
Sales.class).getResultList();
}
}
SalesBean.java是一个Managed Bean,负责启动Job,其中使用了JobOperator。
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.glassfish.movieplex7.batch;
import java.util.List;
import java.util.Properties;
import javax.batch.operations.JobOperator;
import javax.batch.operations.JobStartException;
import javax.batch.runtime.BatchRuntime;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import org.glassfish.movieplex7.entities.Sales;
/**
*
* @author pmma
*/
@Named
@RequestScoped
public class SalesBean {
@PersistenceUnit
EntityManagerFactory emf;
public void runJob() {
try {
JobOperator jo = BatchRuntime.getJobOperator();
long jobId = jo.start("eod-sales", new Properties());
System.out.println("Started job: with id: " + jobId);
} catch (JobStartException ex) {
ex.printStackTrace();
}
}
public List
return emf.createEntityManager().createNamedQuery("Sales.findAll",
Sales.class).getResultList();
}
}
6. sales.xhtml
Table绑定#{salesBean.salesData},用于显示电影售票情况;按钮绑定#{salesBean.runJob()},点击启动Job。
Table绑定#{salesBean.salesData},用于显示电影售票情况;按钮绑定#{salesBean.runJob()},点击启动Job。
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<body>
<ui:composition template="./../WEB-INF/template.xhtml">
<ui:define name="content">
<h1>Movie Sales</h1>
<h:form>
<h:dataTable value="#{salesBean.salesData}" var="s" border="1">
<h:column>
<f:facet name="header">
<h:outputText value="Show ID" />
</f:facet>
#{s.id}
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Sales" />
</f:facet>
#{s.amount}
</h:column>
</h:dataTable>
<h:commandButton value="Run Job" action="sales"
actionListener="#{salesBean.runJob()}"/>
<h:commandButton value="Refresh" action="sales" />
</h:form>
</ui:define>
</ui:composition>
</body>
</html>
Project 下载:5.movieplex7(Batch).7z
没有评论:
发表评论