50 new features of java ee 7 in 50 minutes
DESCRIPTION
This 50 minutes talk covers the novelties of Java EE 7 (easier to understand if you already know Java EE 6). It comes from the talk I gave with Arun Gupta at JavaOne 2013TRANSCRIPT
50 new features of Java EE 7 in 50 minutes
by antonio goncalves@agoncal
2 @agoncal
Antonio Goncalves
Java EE 7(for Java EE 6 developers)
4 @agoncal
What's new? What has been updated?
JAX-RS 2.0
JSON-P 1.0Web Socket 1.0Servlet 3.1
JSF 2.2EL 3.0JSP JSTL
Bea
n V
alid
atio
n 1
.1
Inte
rcep
tors
1.2
CD
I 1.1
Con
curr
enc
y 1.
0
JPA 2.1
JTA 1.2 EJB 3.2 JMS 2.0Batch 1.0
JCA 1.7
Java EE 7
JavaMail 1.5
CDI 1.1(JSR 346)
6 @agoncal
#01: Default enabling
<beans ... version="1.1" bean-discovery-mode="all"> <alternatives> <class>org.agoncal.book.MockGenerator</class> </alternatives></beans>
Finer scanning control
● Possible values: all, annotated, none
● all behaves like in Java EE 6 (default if not set)
7 @agoncal
#02: @Vetoed
@Vetoedpublic class NonProcessedBean { ...}
package-info.java@Vetoedpackage com.non.processed.package;
Veto the processing of the class or package
Bean Validation 1.1(JSR 349)
9 @agoncal
#03: Constructor & method validation
public class CardValidator {
public CardValidator(@NotNull Algorithm algo) { this.algo = algo; }
@AssertTrue public Boolean validate(@NotNull CreditCard cc) { return algorithm.validate(cc.getNumber()); }}
Pre/post conditions on method and constructors
10 @agoncal
#04: CDI in validators
public class ZipCodeValidator implements ConstraintValidator<ZipCode, String> {
@Inject @USA ZipCodeChecker checker = new ZipCodeChecker();
public boolean isValid(String value, ConstraintValidatorContext context) {
return checker.isZipCodeValid(value); }}
Injection in validators is now possible
Interceptor 1.2(JSR 318)
12 @agoncal
#05: AroundConstruct
public class LoggingInterceptor {
@AroundConstruct private void init(InvocationContext ic) ...{ logger.fine("Entering constructor"); ic.proceed(); logger.fine("Exiting constructor"); }
@AroundInvoke public Object logMethod(InvocationContext ic) ... { ... }}
Interceptor associated with a constructor
13 @agoncal
#06: @Priority
@Interceptor@Loggable@Priority(Interceptor.Priority.LIBRARY_BEFORE + 10)public class LoggingInterceptor {
@AroundInvoke ...}
Prioritizing interceptor bindings
● PLATFORM_BEFORE (0), LIBRARY_BEFORE (1000), APPLICATION (2000), LIBRARY_AFTER (3000), PLATFORM_AFTER (4000)
Concurrency Utilities 1.0(JSR 236)
15 @agoncal
#07: ManagedExecutorUse threads in Java EE applications
● Java EE applications cannot use:● java.util.concurrent.ThreadPoolExecutor
● java.lang.Thread
● java.util.Timer
● In managed environment, use:● javax.enterprise.concurrent.ManagedExecutorService
● implements java.util.concurrent.ExecutorService
16 @agoncal
#07: ManagedExecutor
public class MyTask implements Runnable { public void run() { ... }}
@ResourceManagedExecutorService executor;
executor.execute(new MyTask());
Use threads in Java EE applications
17 @agoncal
#08: ManagedThreadFactory
@ResourceManagedThreadFactory factory;
Thread thread = factory.newThread(new MyTask());thread.start();
Create managed threads for Java EE environment
18 @agoncal
#09: ManagedScheduledExecutorServ
@ResourceManagedScheduledExecutorService executor;
executor.schedule(new MyTask(), 5, TimeUnit.SECONDS);
executor.scheduleAtFixedRate(new MyTask(), 2, 3, TimeUnit.SECONDS);
executor.scheduleWithFixedDelay(new MyTask(), 2, 3, TimeUnit.SECONDS);
Submit delayed or periodic tasks
JPA 2.1(JSR 338)
20 @agoncal
#10: Schema Generation
<persistence ... version="2.1"> <persistence-unit ...> <properties> <property name="javax.persistence.schema-generation.scripts.action" value="drop-and-create"/> <property name="javax.persistence.schema-generation.scripts.create-target" value="create.ddl"/> <property name="javax.persistence.sql-load-script-source" value="insert.sql"/> </properties></persistence-unit>
Standardized database schema generation
21 @agoncal
#11: @Index
@Entity@Table(indexes = { @Index(columnList = "ISBN"), @Index(columnList = "NBOFPAGE")})public class Book {
@Id @GeneratedValue private Long id; private String isbn; private Integer nbOfPage; ...}
Defines additional indexes in schema generation
22 @agoncal
#12: Stored Procedure
@Entity@NamedStoredProcedureQuery(name = "archiveOldBooks", procedureName = "sp_archive_books", parameters = { @StoredProcedureParameter(name = ”date", mode = IN, type = Date.class), @StoredProcedureParameter(name = "warehouse", mode = IN, type = String.class)})public class Book {...}
Declaring and calling a stored procedure
23 @agoncal
#13: CDI in listeners
public class AgeCalculationListener {
@Inject private AgeCalculator ageCalculator;
@PostLoad @PostPersist @PostUpdate public void calculateAge(Customer c) { customer.setAge(ageCalculator.calc(c.getBirth)); }}
Injection is now possible into event listeners
24 @agoncal
#14: Converters
@Converterpublic class CreditCardEnumConverter implements AttributeConverter<CreditCard, String> { public String convertToDatabaseColumn(CreditCard attr) {...} public CreditCard convertToEntityAttribute(String data){...}}
@Entitypublic class Order {
@Convert(converter = CreditCardEnumConverter.class) private CreditCard creditCard;}
Classes that convert between database and attributes
JTA 1.2(JSR 907)
26 @agoncal
#15: @Transactional
@Path("book")@Transactional(value = Transactional.TxType.REQUIRED, rollbackOn = {SQLException.class, JMSException.class}, dontRollbackOn = SQLWarning.class)public class BookRestService {
@PersistenceContext private EntityManager em;
@POST @Consumes(MediaType.APPLICATION_XML) public Response createBook(Book book) {...}}
Tx management on Managed Beans as CDI interceptor
27 @agoncal
#16: @TransactionScoped
@TransactionScopedpublic class BookBean {...}
@WebServletpublic class TxServlet extends HttpServlet { @Inject BookBean b1; @Inject BookBean b2;
protected void processRequest(...) { tx.begin(); out.println(b1.getReference()); out.println(b2.getReference()); tx.commit(); }}
CDI scope whose lifecycle is scoped to the current tx
EJB 3.2(JSR 345)
29 @agoncal
#17: Disable passivation of stateful
@Stateful(passivationCapable = false)public class ShoppingCart { ...}
In some cases increases performance
30 @agoncal
#18: Async + Non-persistent timer
@Statelesspublic class OrderEJB {
@Asynchronous public void sendEmail (Order order) { // Very Long task } @Schedule(hour="2", persistent=false) public void createDailyReport() { // ... }}
EJB Lite includes asynchronous calls and Timer Service
JMS 2.0(JSR 343)
32 @agoncal
#19: JMSContext API
JMSContext ctx = connectionFactory.createContext()
ctx.createProducer().send(queue, "Text msg sent");
ctx.createConsumer(queue).receiveBody(String.class);
ctx.createProducer() .setPriority(2) .setTimeToLive(1000) .setDeliveryMode(DeliveryMode.NON_PERSISTENT) .send(queue, message);
New simplified API to produce and consume messages
33 @agoncal
#20: Runtime Exceptions
RuntimeException JMSRuntimeException IllegalStateRuntimeException InvalidClientIDRuntimeException InvalidDestinationRuntimeException InvalidSelectorRuntimeException JMSSecurityRuntimeException MessageFormatRuntimeException MessageNotWriteableRuntimeException ResourceAllocationRuntimeException TransactionInProgressRuntimeException TransactionRolledBackRuntimeException
A set of new unchecked exceptions have been created
34 @agoncal
#21: Autocloseable
try (JMSContext ctx = connectionFactory.createContext()){ ctx.createProducer().send(queue, "Text message sent");}
Several JMS interfaces implement Autocloseable
35 @agoncal
#22: JMSConnectionFactoryDefinition
@Stateless@JMSConnectionFactoryDefinition( name = "java:app/jms/MyConnectionFactory", interfaceName = "javax.jms.TopicConnectionFactory")
public class ExpensiveOrderEJB { ...}
A ConnectionFactory can be defined using an annotation
36 @agoncal
#23: JMSDestinationDefinition
@Stateless@JMSConnectionFactoryDefinition( name = "java:app/jms/MyConnectionFactory", interfaceName = "javax.jms.TopicConnectionFactory")@JMSDestinationDefinition( name = "java:app/jms/MyTopic", interfaceName = "javax.jms.Topic")public class ExpensiveOrderEJB { ...}
A JMS queue or topic can be defined using an annotation
Servlet 3.1(JSR 340)
38 @agoncal
#24: Non-blocking IO
public interface ReadListener extends EventListener { public void onDataAvailable() throws IOException; public void onAllDataRead() throws IOException; public void onError(Throwable t);}
public interface WriteListener extends EventListener { public void onWritePossible() throws IOException; public void onError(Throwable t);}
New interfaces
39 @agoncal
#24: Non-blocking IONew methods on existing APIs
● javax.servlet.ServletInputStream
● public abstract boolean isFinished()
● public abstract boolean isReady()
● public abstract void setReadListener(ReadListener l)
● javax.servlet.ServletOutputStream
● public abstract boolean isReady()
● public abstract setWriteListener(WriteListener l)
40 @agoncal
#24: Non-blocking IO
@WebServlet(“/test”)public class TestServlet extends HttpServlet { protected void doPost(HttpServletRequest req, HttpServletResponse res) ... { AsyncContext ac = req.startAsync(); ... ServletInputStream input = req.getInputStream(); ReadListener readListener = new ReadListenerImpl(input, output, ac); input.setReadListener(readListener);}
Example
41 @agoncal
#25: Improved Security
@WebServlet(“/test”)@ServletSecurity(@HttpConstraint(rolesAllowed={“**”}))public class TestServlet extends HttpServlet { ...}
Any authenticated users
42 @agoncal
#25: Improved Security
<web-app . . . version="3.1">
<security-constraint> <web-resource-collection> <url-pattern>/account/*</url-pattern> <http-method>GET</http-method> </web-resource-collection> </security-constraint>
</web-app>
All HTTP Methods except GET are uncovered
43 @agoncal
#25: Improved Security
<web-app . . . version="3.1">
<security-constraint> <deny-uncovered-http-methods/> <web-resource-collection> <url-pattern>/account/*</url-pattern> <http-method>GET</http-method> </web-resource-collection> </security-constraint>
</web-app>
The container denies any HTTP protocol method
44 @agoncal
#26: Protocol UpgradeNew interfaces and methods on existing APIs
● Add two new interfaces● javax.servlet.http.HttpUpgradeHandler
● javax.servlet.http.WebConnection
● Add a method to HttpServletRequest● upgrade(Class<T> handlerClass)
45 @agoncal
#26: Protocol Upgrade
@WebServlet(“/upgrade”)public class UpgradeServlet extends HttpServlet protected void doGet(HttpServletRequest req, HttpServletResponse res) ... { ... if (decideToUpgrade) { MyHttpUpgradeHandler handler = request.upgrade(MyHttpUpgradeHandler.class); } }}
Example
Web Socket 1.0(JSR 356)
47 @agoncal
#27: Annotated server endpoint
@javax.websocket.server.ServerEndpoint("/chat")public class ChatServer {
@OnMessage public String chat(String name, Session session) { for (Session peer : client.getOpenSessions()) { peer.getBasicRemote().sendObject(message); } }}
Bi-directional communication over single TCP connection
48 @agoncal
#28: Annotated client endpoint
@javax.websocket.ClientEndpointpublic class ChatClient {
@OnOpen public void open(Session session) { ... }}
Bi-directional communication over single TCP connection
49 @agoncal
#29: Lifecycle callbacks
@OnMessagepublic String chat(String name, Session session) {..}
@OnOpenpublic void open(Session s) {...}
@OnClosepublic void close(CloseReason c) {...}
@OnErrorpublic void error(Throwable t) {...}
Allows you to act on lifecycle events
Expression Language 3.0(JSR 341)
51 @agoncal
#30: ELProcessor
ELProcessor el = new ELProcessor();
assert ((Integer)el.eval("a = [1, 2]; a[1]")) == 2;
el.defineBean("employee", new Employee("John"));assert (el.eval("employee.name")).equals("John");
Use EL in a stand-alone environment
52 @agoncal
#31: Lambda expression
ELProcessor el = new ELProcessor();
assert ((Integer)(el.eval ("((x,y) -> x+y)(4, 5)"))) == 9;
Use lambdas before Java SE 8
JSF 2.2(JSR 344)
54 @agoncal
#32: Faces Flow
./src/main/webapp/flow1 /flow1.xhtml /flow1a.xhtml /flow1b.xhtml./src/main/webapp/flow2 /flow2-flow.xml /flow2.xhtml /flow2a.xhtml /flow2b.xhtml /index.xhtml
Navigate in a flow using convention over configuration
55 @agoncal
#32: Faces Flow
@Named@FlowScoped("flow1")public class Flow1Bean implements Serializable { ...}
New CDI flow scope
56 @agoncal
#33: Resource Library Contract
index-blue.xhtmlindex-red.xhtmlWEB-INF/lib/mycontracts-1.0.jar /META-INF/contracts/blue /style.css /javax.faces.contract.xml /template.xhtml /META-INF/contracts/red /style.css /javax.faces.contract.xml /template.xhtml
Reusable and interchange templates
57 @agoncal
#33: Resource Library Contract
<f:view contracts=”red”> <ui:composition template="/template.xhtml"> . . . </ui:composition></f:view>
Reusable and interchange templates
58 @agoncal
#34: Pass-through Attributes
<input type="email" placeholder="[email protected]">
<html xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:p="http://xmlns.jcp.org/jsf/passthrough">
<h:inputText p:type="email" p:placeholder="[email protected]" value="#{bean.email}"/></html>
HTML5-Friendly Markup
59 @agoncal
#35: File upload
<h:form enctype="multipart/form-data"> <h:inputFile value="#{fileUploadBean.file}"/> <h:commandButton value="Upload"/></h:form>
@Named @RequestScoped public class FileUploadBean { private Part file; ...}
Use the Servlet 3.0 Part
JAX-RS 2.0(JSR 339)
61 @agoncal
#36: Client API
Client client = ClientBuilder.newClient();WebTarget target = client.target("http://www.foo.com/book");Invocation invocation = target.request(TEXT_PLAIN).get();Response response = invocation.invoke();
Response response = ClientBuilder.newClient() .target("http://www.foo.com/book") .request(MediaType.TEXT_PLAIN) .get();
String body = ClientBuilder.newClient() .target("http://www.foo.com/book") .request() .get(String.class);
New API to consume rest services
62 @agoncal
#37: Async client
Future<String> future = ClientBuilder.newClient() .target("http://www.foo.com/book") .request() .async() .get(String.class);
try { String body = future.get(1, TimeUnit.MINUTES);} catch (InterruptedException |ExecutionException e){ ...}
The client API also supports asynchronous invocation
63 @agoncal
#38: Async server
@Path("/async")public class AsyncResource {
@GET public void asyncGet(@Suspended AsyncResponse resp){ new Thread(new Runnable() {
public void run() { String result = veryExpensiveOperation(); resp.resume(result); } }).start(); }}
Asynchronous request processing on the server
64 @agoncal
#39: Message FilterProcess incoming/outgoing request/response headers
● Filters on client side● javax.ws.rs.client.ClientRequestFilter
● javax.ws.rs.client.ClientResponseFilter
● Filters on server side● javax.ws.rs.container.ContainerRequestFilter
● javax.ws.rs.container.ContainerResponseFilter
65 @agoncal
#39: Message FilterProcess incoming/outgoing request/response headers
public class LogginFilter implements ClientRequestFilter{
public void filter(ClientRequestContext ctx) ... { System.out.println(ctx.getMethod()); System.out.println(ctx.getUri()); }}
66 @agoncal
#40: Entity InterceptorsMarshalling and unmarshalling HTTP message bodies
● Intercepts inbound stream (read from the “wire”)● javax.ws.rs.ext.ReaderInterceptor
● Intercepts outbound stream (written to the “wire”)● javax.ws.rs.ext.WriterInterceptor
67 @agoncal
#40: Entity InterceptorsMarshalling and unmarshalling HTTP message bodies
public class ZipInterceptor implements WriterInterceptor{
public void aroundWriteTo(WriterInterceptorContext ctx){ OutputStream os = ctx.getOutputStream(); ctx.setOutputStream(new GZIPOutputStream(os)); ctx.proceed(); }}
JSON-P 1.0(JSR 353)
69 @agoncal
#41: JSON Builder
JsonObject value = Json.createObjectBuilder() .add("id", "1234") .add("date", "19/09/2012") .add("total_amount", "93.48") .add("customer", Json.createObjectBuilder() .add("first_name", "James") .add("last_name", "Rorrison") .add("email", "[email protected]") .add("phoneNumber", "+44 1234 1234") ) .build();
Builds an object model in memory by adding elements
70 @agoncal
#42: JSON Parser
JsonParser parser = Json.createParser( new FileReader(“order.json"));
while (parser.hasNext()) { JsonParser.Event event = parser.next();
if (event.equals(JsonParser.Event.KEY_NAME) && parser.getString().matches("email")) { parser.next(); email = parser.getString(); }}
Event-based parser reading JSON data from a stream
Batch 1.0(JSR 352)
72 @agoncal
#43: Jobs and stepsBatch uses jobs and steps to do the work
73 @agoncal
#44: Workflow
<split id="split1" next=" . . . "> <flow id="flow1" next="step3"> <step id="step1" next="step2"> . . . </step> <step id="step2"> . . . </step> </flow> <flow id="flow2”> <step id="stepA”> . . . </step> </flow></split><step id="step3"> . . . </step>
Flow, step, decision... to create workflows
74 @agoncal
#45: Chunk-style processing
<step id=”sendStatements”> <chunk item-count=“3”> <reader ref=”accountReader”/> <processor ref=”accountProcessor”/> <writer ref=”emailWriter”/></step>
Item-oriented way of processing
...implements ItemWriter {public void writeItems(List accounts) { // use JavaMail to send email}
...implements ItemProcessor {public Object processItems(Object account) { // read Account, return Statement}
...implements ItemReader {public Object readItem() { // read account using JPA}
75 @agoncal
#46: Batchlet-style processing
<step id=”transferFile”> <batchlet ref=“MyFileTransfer” /></step>
Task-oriented way of processing
...implements Batchlet {@Overridepublic void process() { // Transfer file}
JavaMail 1.5(JSR 919)
77 @agoncal
#47: MailSessionDefinition
@MailSessionDefinition(name = "java:comp/myMailSession", properties = { "mail.smtp.host=smtp.gmail.com", "mail.smtp.ssl.enable=true", "mail.smtp.auth=true", "mail.transport.protocol=smtp", "mail.debug=true" })
@Resource(lookup = "java:comp/myMailSession")Session session;
A mail session can be defined using an annotation
JCA 1.7(JSR 322)
79 @agoncal
#48: Connector definition
@ConnectionDefinition( connection="MyConnection.class", connectionImpl="MyConnectionImpl.class", connectionFactory="MyConnectionFactory.class", connectionFactoryImpl="MyConnectionFactoryImpl.class")
@AdministeredObjectDefinition( className="MyQueueImpl.class", name="java:comp/MyQueue", resourceAdapter="myAdapter",)
A connector can be defined using an annotation
Java EE 7(JSR 342)
81 @agoncal
#49: Default Resources
@Resource(lookup="java:comp/DefaultDataSource")private DataSource myDS;
@Resourceprivate DataSource myDS;
Default datasource
82 @agoncal
#49: Default Resources
@Resource(lookup="java:comp/DefaultJMSConnectionFactory") private ConnectionFactory myCF;
@Resourceprivate ConnectionFactory myCF;
Default JMS factory
83 @agoncal
#49: Default Resources
@Resource(lookup="java:comp/DefaultManagedExecutorService") private ManagedExecutorService mes; @Resource(lookup="java:comp/DefaultManagedScheduledExecutorService") private ManagedScheduledExecutorService mses; @Resource(lookup="java:comp/DefaultManagedThreadFactory") private ManagedThreadFactory mtf; @Resource(lookup="java:comp/DefaultContextService") private ContextService cs;
@Resourceprivate ManagedExecutorService mes; @Resourceprivate ManagedScheduledExecutorService mses; @Resourceprivate ManagedThreadFactory mtf; @Resourceprivate ContextService cs;
Default Concurrency Utilities objects
84 @agoncal
#50: Get more information ;o)
Q & A
87 @agoncal
Thanks
● Arun Gupta @arungupta● From our talk at JavaOne 2013
88 @agoncal
Creative Commons
● Attribution — You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work).
● Noncommercial — You may not use this work for commercial purposes.
● Share Alike — If you alter, transform, or build upon this work, you may distribute the resulting work only under the same or similar license to this one.