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 2013
#01: Default enabling
Finer scanning control
●
Possible values: all, annotated, none
●
all behaves like in Java EE 6 (default if not set)
<beans ... version="1.1" bean-discovery-mode="all">
<alternatives>
<class>org.agoncal.book.MockGenerator</class>
</alternatives>
</beans>
@agoncal
6
#02: @Vetoed
Veto the processing of the class or package
@Vetoed
public class NonProcessedBean {
...
}
package-info.java
@Vetoed
package com.non.processed.package;
@agoncal
7
#03: Constructor & method validation
Pre/post conditions on method and constructors
public class CardValidator {
public CardValidator(@NotNull Algorithm algo) {
this.algo = algo;
}
@AssertTrue
public Boolean validate(@NotNull CreditCard cc) {
return algorithm.validate(cc.getNumber());
}
}
@agoncal
9
#04: CDI in validators
Injection in validators is now possible
public class ZipCodeValidator implements
ConstraintValidator<ZipCode, String> {
@Inject @USA
ZipCodeChecker checker = new ZipCodeChecker();
public boolean isValid(String value,
ConstraintValidatorContext context) {
return checker.isZipCodeValid(value);
}
}
@agoncal
10
#07: ManagedExecutor
Use threads in Java EE applications
●
Java EE applications cannot use:
●
●
java.lang.Thread
●
●
java.util.concurrent.ThreadPoolExecutor
java.util.Timer
In managed environment, use:
●
javax.enterprise.concurrent.ManagedExecutorService
●
implements java.util.concurrent.ExecutorService
@agoncal
15
#07: ManagedExecutor
Use threads in Java EE applications
public class MyTask implements Runnable {
public void run() {
...
}
}
@Resource
ManagedExecutorService executor;
executor.execute(new MyTask());
@agoncal
16
#08: ManagedThreadFactory
Create managed threads for Java EE environment
@Resource
ManagedThreadFactory factory;
Thread thread = factory.newThread(new MyTask());
thread.start();
@agoncal
17
#11: @Index
Defines additional indexes in schema generation
@Entity
@Table(indexes = {
@Index(columnList = "ISBN"),
@Index(columnList = "NBOFPAGE")
})
public class Book {
@Id @GeneratedValue
private Long id;
private String isbn;
private Integer nbOfPage;
...
}
@agoncal
21
#12: Stored Procedure
Declaring and calling a 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 {...}
@agoncal
22
#13: CDI in listeners
Injection is now possible into event listeners
public class AgeCalculationListener {
@Inject
private AgeCalculator ageCalculator;
@PostLoad
@PostPersist
@PostUpdate
public void calculateAge(Customer c) {
customer.setAge(ageCalculator.calc(c.getBirth));
}
}
@agoncal
23
#14: Converters
Classes that convert between database and attributes
@Converter
public class CreditCardEnumConverter implements
AttributeConverter<CreditCard, String> {
public String convertToDatabaseColumn(CreditCard attr) {...}
public CreditCard convertToEntityAttribute(String data){...}
}
@Entity
public class Order {
@Convert(converter = CreditCardEnumConverter.class)
private CreditCard creditCard;
}
@agoncal
24
#17: Disable passivation of stateful
In some cases increases performance
@Stateful(passivationCapable = false)
public class ShoppingCart {
...
}
@agoncal
29
#18: Async + Non-persistent timer
EJB Lite includes asynchronous calls and Timer Service
@Stateless
public class OrderEJB {
@Asynchronous
public void sendEmail (Order order) {
// Very Long task
}
@Schedule(hour="2", persistent=false)
public void createDailyReport() {
// ...
}
}
@agoncal
30
#19: JMSContext API
New simplified API to produce and consume messages
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);
@agoncal
32
#20: Runtime Exceptions
A set of new unchecked exceptions have been created
RuntimeException
JMSRuntimeException
IllegalStateRuntimeException
InvalidClientIDRuntimeException
InvalidDestinationRuntimeException
InvalidSelectorRuntimeException
JMSSecurityRuntimeException
MessageFormatRuntimeException
MessageNotWriteableRuntimeException
ResourceAllocationRuntimeException
TransactionInProgressRuntimeException
TransactionRolledBackRuntimeException
@agoncal
33
#22: JMSConnectionFactoryDefinition
A ConnectionFactory can be defined using an annotation
@Stateless
@JMSConnectionFactoryDefinition(
name = "java:app/jms/MyConnectionFactory",
interfaceName = "javax.jms.TopicConnectionFactory")
public class ExpensiveOrderEJB {
...
}
@agoncal
35
#23: JMSDestinationDefinition
A JMS queue or topic can be defined using an annotation
@Stateless
@JMSConnectionFactoryDefinition(
name = "java:app/jms/MyConnectionFactory",
interfaceName = "javax.jms.TopicConnectionFactory")
@JMSDestinationDefinition(
name = "java:app/jms/MyTopic",
interfaceName = "javax.jms.Topic")
public class ExpensiveOrderEJB {
...
}
@agoncal
36
#26: Protocol Upgrade
New 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)
@agoncal
44
#26: Protocol Upgrade
Example
@WebServlet(“/upgrade”)
public class UpgradeServlet extends HttpServlet
protected void doGet(HttpServletRequest req,
HttpServletResponse res) ... {
...
if (decideToUpgrade) {
MyHttpUpgradeHandler handler =
request.upgrade(MyHttpUpgradeHandler.class);
}
}
}
@agoncal
45
#27: Annotated server endpoint
Bi-directional communication over single TCP connection
@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);
}
}
}
@agoncal
47
#28: Annotated client endpoint
Bi-directional communication over single TCP connection
@javax.websocket.ClientEndpoint
public class ChatClient {
@OnOpen
public void open(Session session) {
...
}
}
@agoncal
48
#29: Lifecycle callbacks
Allows you to act on lifecycle events
@OnMessage
public String chat(String name, Session session) {..}
@OnOpen
public void open(Session s) {...}
@OnClose
public void close(CloseReason c) {...}
@OnError
public void error(Throwable t) {...}
@agoncal
49
#30: ELProcessor
Use EL in a stand-alone environment
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");
@agoncal
51
#31: Lambda expression
Use lambdas before Java SE 8
ELProcessor el = new ELProcessor();
assert ((Integer)(el.eval
("((x,y) -> x+y)(4, 5)"))) == 9;
@agoncal
52
#35: File upload
Use the Servlet 3.0 Part
<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;
...
}
@agoncal
59
#36: Client API
New API to consume rest services
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);
@agoncal
61
#37: Async client
The client API also supports asynchronous invocation
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){
...
}
@agoncal
62
#38: Async server
Asynchronous request processing on the 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();
}}
@agoncal
63
#39: Message Filter
Process 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
@agoncal
64
#39: Message Filter
Process 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());
}
}
@agoncal
65
#40: Entity Interceptors
Marshalling 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
@agoncal
66
#40: Entity Interceptors
Marshalling 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();
}
}
@agoncal
67
#47: MailSessionDefinition
A mail session can be defined using an annotation
@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;
@agoncal
77
#48: Connector definition
A connector can be defined using an annotation
@ConnectionDefinition(
connection="MyConnection.class",
connectionImpl="MyConnectionImpl.class",
connectionFactory="MyConnectionFactory.class",
connectionFactoryImpl="MyConnectionFactoryImpl.class"
)
@AdministeredObjectDefinition(
className="MyQueueImpl.class",
name="java:comp/MyQueue",
resourceAdapter="myAdapter",
)
@agoncal
79
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.
@agoncal
88