Java EE 5, 6 et les EJBs 3.1 Antonio Goncalves Tours JUG le 11/06/08 1
Agenda Présentation Java EE 5 Java EE 5 vs J2EE 1.4 Java EE 6 EJB 3.1 Encore plus facile Nouvelles fonctionnalités Questions
Agenda Présentation Java EE 5 Java EE 5 vs J2EE 1.4 Java EE 6 EJB 3.1 Encore plus facile Nouvelles fonctionnalités Questions
Antonio Goncalves Consultant / Architecte senior Spécialiste Java / Java EE Ancien de BEA Systems Enseignant à l université du CNAM Expert Group JSR 316 (Java EE 6) JSR 317 (JPA 2.0) JSR 318 (EJB 3.1) Auteur Java EE 5 Co-créateur du Paris JUG
Et vous? J2EE 1.4 Java EE 5 Spring / Hibernate / Struts Java EE 6
Agenda Présentation Java EE 5 Java EE 5 vs J2EE 1.4 Java EE 6 EJB 3.1 Encore plus facile Nouvelles fonctionnalités Questions
Historique de Java EE Facilité de développement (web) Services web Facilité de développement Java EE 5 Java EE 6 Application d entreprise Robustesse J2EE 1.4 J2EE 1.2 J2EE 1.3 Profiles Projet JPE Servlet JSP EJB JMS RMI/IIOP CMP Connecteur Services web Déploiement Annotations EJB 3 Persistance Services web EJB 3.1 JPA 2.0 Servlet 3 JSF 2.0 JAX-RS Mai 1998 Déc 1999 10 specs Sept 2001 13 specs Nov 2003 20 specs Mai 2006 23 specs 2009 ~27 specs
A propos de Java EE 5 Développé sous la JSR 244 Sortie en Mai 2006 (+ GlassFish V1) Facilité de développement EoD (Ease of Development) Compatible avec J2EE 1.4 Le meilleur des deux mondes Spécifications Inspiré de l'open source
Les grandes nouveautés Rupture par rapport à J2EE 1.4 Simplification des EJB et WebServices Nouvelle API de persistance (JPA) Model de développement POJO Injection de dépendance Utilisation des annotations Descripteurs XML optionnel Développement par exception Facilite les applications web avec JSF
Contenu Java EE 5 23 specifications Web : JSF 1.2, JSP 2.1, JSTL 1.2, Servlet 2.5 Enterprise : Common Annotations 1.0, EJB 3.0, JAF 1.1, JavaMail 1.4, JCA 1.5, JMS 1.1, JPA 1.0, JTA 1.1 Web Services : JAX-RPC 1.1, JAX-WS 2.0, JAXB 2.0, SAAJ 1.0, StAX 1.0, Web Services 1.2, Web Services Metadata 2.0 Management & Security : JACC 1.1, Java EE Application Deployment 1.2, Java EE Management 1.1
Agenda Présentation Java EE 5 Java EE 5 vs J2EE 1.4 Java EE 6 EJB 3.1 Encore plus facile Nouvelles fonctionnalités Questions
Stateless EJB 2.1 Home interface public interface HelloHome extends EJBHome { Hello create() throws RemoteException, CreateException; Interface locale public interface Hello extends EJBObject { String sayhello() throws RemoteException; Date today() throws RemoteException; EJB public class HelloBean implements SessionBean { public HelloBean() { public String sayhello() {return "Hello Petstore!"; public Date today() {return new Date(); Descripteur <ejb-jar> <enterprise-beans> <session> <display-name>hellosb</display-name> <ejb-name>hellobean</ejb-name> <home>hellohome</home> <remote>hello</remote> <ejb-class>hellobean</ejb-class> <session-type>stateless</session-type> <transaction-type>container</transaction-type> </session> <assembly-descriptor> <container-transaction> <method> <ejb-name>hellobean</ejb-name> <method-name>*</method-name> </method> <trans-attribute>required</trans-attribute> </container-transaction> </assembly-descriptor> </enterprise-beans> </ejb-jar> public void ejbcreate() throws CreateException { public void setsessioncontext( SessionContext sessioncontext) throws EJBException { public void ejbremove() throws EJBException { public void ejbactivate() throws EJBException { public void ejbpassivate() throws EJBException {
Stateless EJB 3.0 Interface @Remote public interface Hello { String sayhello() throws RemoteException; Date today() throws RemoteException; EJB @Stateless public class HelloBean implements Hello { public String sayhello() {return "Hello Petstore!"; public Date today() {return new Date();
Annotations des EJBs 3.0 @Stateless, @Stateful, @MessageDriven @Local, @Remote. @PostConstruct, @PreDestroy, @PrePassivate... @Ejb, @Resource, @WebServiceRef @TransactionAttribute(REQUIRED) @RolesAllowed, @PermitAll
Entity Bean CMP 2.1 Home interface public interface HelloHome extends EJBHome { Hello create(string cle) throws RemoteException, CreateException; Hello findbyprimarykey(string cle) throws RemoteException, FinderException; Interface locale public interface Hello extends EJBObject { String getcle() throws RemoteException; String getvaleur() throws RemoteException; void setvaleur(string valeur) throws RemoteException; EJB public abstract class HelloBean implements EntityBean { public abstract String getcle() throws RemoteException; public abstract void setcle(string cle) throws RemoteException; public abstract String getvaleur() throws RemoteException; public abstract void setvaleur(string valeur) throws RemoteException; public String ejbcreate(string cle) throws RemoteException, setcle(cle); return null; CreateException { public void ejbpostcreate(string cle) throws CreateException{ public void setentitycontext(entitycontext entitycontext) throws EJBException { public void unsetentitycontext() throws EJBException { public void ejbremove() throws RemoveException, EJBException { public void ejbactivate() throws EJBException { public void ejbpassivate() throws EJBException { public void ejbload() throws EJBException { public void ejbstore() throws EJBException { Descripteur ejb-jar.xml <ejb-jar> <enterprise-beans> <entity> <display-name>helloeb</display-name> <ejb-name>hellobean</ejb-name> <home>hellohome</home> <remote>hello</remote> <ejb-class>hellobean</ejb-class> <persistence-type>container</persistence-type> <prim-key-class>java.lang.string</prim-key-class> <reentrant>false</reentrant> <cmp-version>2.x</cmp-version> <abstract-schema-name>hello</abstract-schema-name>; <cmp-field> <field-name>cle</field-name> </cmp-field> <cmp-field> <field-name>valeur</field-name> </cmp-field> <primkey-field>cle</primkey-field> </entity> </enterprise-beans> </ejb-jar> Descripteur propriétaire <jbosscmp-jdbc> <defaults> <datasource>java:/petstoreds</datasource> <datasource-mapping>mysql</datasource-mapping> </defaults> <enterprise-beans> <entity> <ejb-name>hellobean</ejb-name> <table-name>hello_petstore</table-name> <cmp-field> <field-name>cle</field-name> <column-name>key</column-name> <jdbc-type>varchar</jdbc-type> <sql-type>varchar(10)</sql-type> </cmp-field> <cmp-field> <field-name>valeur</field-name> <column-name>value</column-name> <jdbc-type>varchar</jdbc-type> <sql-type>varchar(50)</sql-type> </cmp-field> </entity> </enterprise-beans> </jbosscmp-jdbc>
Entity JPA POJO @Entity public class Hello { @Id private Long cle; private String valeur; public String getcle() {return cle; public String getvaleur() {return valeur; public void setvaleur() {this.valeur = valeur;
Service Web J2EE 1.4 Service Web public class HelloServiceImpl implements HelloServiceSEI { public String sayhello(string param) throws java.rmi.remoteexception { return Hello + param; package endpoint; import java.rmi.*; public interface HelloServiceSEI extends java.rmi.remote { public String sayhello(string param) throws java.rmi.remoteexception; <?xml version='1.0' encoding='utf-8'?> <webservices xmlns='http://java.sun.com/xml/ns/j2ee' version='1.1'> <webservice-description> <webservice-description-name> HelloService</webservice-description-name> <wsdl-file> WEB-INF/wsdl/HelloService.wsdl</wsdl-file> <jaxrpc-mapping-file> WEB-INF/HelloService-mapping.xml </jaxrpc-mapping-file> <port-component xmlns:wsdlport_ns='urn:helloservice/wsdl'> <port-component-name>helloservice</portcomponent-name> <wsdl-port>wsdlport_ns:helloserviceseiport</wsdl-port> <service-endpoint-interface> endpoint.helloservicesei</service-endpointinterface> <service-impl-bean> <servlet-link>wsservlet_helloservice</servletlink> </service-impl-bean> </port-component> </webservice-description> </webservices> <?xml version='1.0' encoding='utf-8'?> <configuration xmlns='http://java.sun.com/xml/ns/jaxrpc/ri/config'> <service name='helloservice' targetnamespace='urn:helloservice/wsdl' typenamespace='urn:helloservice/types' packagename='endpoint'> <interface name='endpoint.helloservicesei' servantname='endpoint.helloserviceimpl'> </interface> </service> </configuration>
Service Web Java EE 5 package endpoint; import javax.jws.webservice; @WebService public class Hello { public String sayhello(string param) { return Hello + param;
JAXB 1.0 Classe générée // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> // Any modifications to this file will be lost upon recompilation of the source schema. // Generated on: 2005.04.21?? 10:37:56 PDT // package generated.impl; public class PointTypeImpl implements generated.pointtype, com.sun.xml.bind.jaxbobject, generated.impl.runtime.unmarshallableobject, generated.impl.runtime.xmlserializable, generated.impl.runtime.validatableobject { protected boolean has_y; protected float _Y; protected boolean has_x; protected float _X; public final static java.lang.class version = (generated.impl.jaxbversion.class); private static com.sun.msv.grammar.grammar schemafragment; private final static java.lang.class PRIMARY_INTERFACE_CLASS() { return (generated.pointtype.class); public float gety() { return _Y; public void sety(float value) { _Y = value; has_y = true; public float getx() { return _X; public void setx(float value) { _X = value; has_x = true; public generated.impl.runtime.unmarshallingeventhandler createunmarshaller(generated.impl.runtime.unmarshallingcontext context) { return new generated.impl.pointtypeimpl.unmarshaller(context); public void serializebody(generated.impl.runtime.xmlserializer context) throws org.xml.sax.saxexception { if (!has_y) { context.reporterror(com.sun.xml.bind.serializer.util.createmissingobjecterror(this, "Y")); if (!has_x) { context.reporterror(com.sun.xml.bind.serializer.util.createmissingobjecterror(this, "X")); context.startelement("", "x"); context.endnamespacedecls(); context.endattributes(); try { context.text(javax.xml.bind.datatypeconverter.printfloat(((float) _X)), "X"); catch (java.lang.exception e) { generated.impl.runtime.util.handleprintconversionexception(this, e, context); context.endelement(); context.startelement("", "y"); context.endnamespacedecls(); context.endattributes(); try { context.text(javax.xml.bind.datatypeconverter.printfloat(((float) _Y)), "Y"); catch (java.lang.exception e) { generated.impl.runtime.util.handleprintconversionexception(this, e, context); context.endelement(); public void serializeattributes(generated.impl.runtime.xmlserializer context) throws org.xml.sax.saxexception { if (!has_y) { context.reporterror(com.sun.xml.bind.serializer.util.createmissingobjecterror(this, "Y")); if (!has_x) { context.reporterror(com.sun.xml.bind.serializer.util.createmissingobjecterror(this, "X")); public void serializeuris(generated.impl.runtime.xmlserializer context) throws org.xml.sax.saxexception { if (!has_y) { context.reporterror(com.sun.xml.bind.serializer.util.createmissingobjecterror(this, "Y")); if (!has_x) { context.reporterror(com.sun.xml.bind.serializer.util.createmissingobjecterror(this, "X")); public java.lang.class getprimaryinterface() { return (generated.pointtype.class); public com.sun.msv.verifier.documentdeclaration createrawvalidator() { if (schemafragment == null) { schemafragment = com.sun.xml.bind.validator.schemadeserializer.deserialize(( "\u00ac\u00ed\u0000\u0005sr\u0000\u001fcom.sun.msv.grammar.sequenceexp\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0000\u0000xr\u0000\u001dcom.su" +"n.msv.grammar.binaryexp\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0000\u0002l\u0000\u0004exp1t\u0000 Lcom/sun/msv/gra" +"mmar/expression;l\u0000\u0004exp2q\u0000~\u0000\u0002xr\u0000\u001ecom.sun.msv.grammar.expressi" +"on\u00f8\u0018\u0082\u00e8n5~o\u0002\u0000\u0002l\u0000\u0013epsilonreducibilityt\u0000\u0013ljava/lang/boolean;l\u0000\u000b" +"expandedexpq\u0000~\u0000\u0002xpppsr\u0000\'com.sun.msv.grammar.trex.elementpatt" +"ern\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0000\u0001l\u0000\tnameclasst\u0000\u001flcom/sun/msv/grammar/nameclass;" +"xr\u0000\u001ecom.sun.msv.grammar.elementexp\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0000\u0002z\u0000\u001aignoreundecl" +"aredattributesl\u0000\fcontentmodelq\u0000~\u0000\u0002xq\u0000~\u0000\u0003pp\u0000sq\u0000~\u0000\u0000ppsr\u0000\u001bcom.s" +"un.msv.grammar.dataexp\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0000\u0003l\u0000\u0002dtt\u0000\u001florg/relaxng/dataty" +"pe/datatype;l\u0000\u0006exceptq\u0000~\u0000\u0002l\u0000\u0004namet\u0000\u001dlcom/sun/msv/util/string" +"Pair;xq\u0000~\u0000\u0003ppsr\u0000\"com.sun.msv.datatype.xsd.FloatType\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002" +"\u0000\u0000xr\u0000+com.sun.msv.datatype.xsd.floatingnumbertype\u00fc\u00e3\u00b6\u0087\u008c\u00a8 \u00e0\u0002\u0000\u0000" +"xr\u0000*com.sun.msv.datatype.xsd.builtinatomictype\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0000\u0000xr\u0000" +"%com.sun.msv.datatype.xsd.concretetype\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0000\u0000xr\u0000\'com.sun" +".msv.datatype.xsd.xsdatatypeimpl\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0000\u0003l\u0000\fnamespaceurit\u0000" +"\u0012ljava/lang/string;l\u0000\btypenameq\u0000~\u0000\u0014l\u0000\nwhitespacet\u0000.lcom/sun/" +"msv/datatype/xsd/whitespaceprocessor;xpt\u0000 http://www.w3.org/" +"2001/XMLSchemat\u0000\u0005floatsr\u00005com.sun.msv.datatype.xsd.WhiteSpac" +"eprocessor$collapse\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0000\u0000xr\u0000,com.sun.msv.datatype.xsd.w" +"hitespaceprocessor\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0000\u0000xpsr\u00000com.sun.msv.grammar.expre" +"ssion$nullsetexpression\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0000\u0000xq\u0000~\u0000\u0003ppsr\u0000\u001bcom.sun.msv.ut" +"il.stringpair\u00d0t\u001ejb\u008f\u008d\u00a0\u0002\u0000\u0002l\u0000\tlocalnameq\u0000~\u0000\u0014l\u0000\fnamespaceuriq\u0000~\u0000" +"\u0014xpq\u0000~\u0000\u0018q\u0000~\u0000\u0017sr\u0000\u001dcom.sun.msv.grammar.choiceexp\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0000\u0000xq\u0000" +"~\u0000\u0001ppsr\u0000 com.sun.msv.grammar.attributeexp\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0000\u0002l\u0000\u0003expq\u0000" +"~\u0000\u0002l\u0000\005valuexp\u0000psq\u0000~\u0000\u000bppsr\u0000\"com.sun.msv.datatype.xsd.qnametype\u0000\u0000\u0000\u0000" +"\u0000\u0000\u0000\u0001\u0002\u0000\u0000xq\u0000~\u0000\u0011q\u0000~\u0000\u0017t\u0000\u0005qnameq\u0000~\u0000\u001bq\u0000~\u0000\u001dsq\u0000~\u0000\u001eq\u0000~\u0000)q\u0000~\u0000\u0017sr\u0000#com." +"sun.msv.grammar.simplenameclass\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0000\u0002l\u0000\tlocalnameq\u0000~\u0000\u0014l" +"\u0000\fnamespaceuriq\u0000~\u0000\u0014xr\u0000\u001dcom.sun.msv.grammar.nameclass\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001" +"\u0002\u0000\u0000xpt\u0000\u0004typet\u0000)http://www.w3.org/2001/xmlschema-instancesr\u00000" +"com.sun.msv.grammar.expression$epsilonexpression\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0000\u0000x" +"q\u0000~\u0000\u0003sq\u0000~\u0000$\u0001psq\u0000~\u0000+t\u0000\u0001xt\u0000\u0000sq\u0000~\u0000\u0006pp\u0000sq\u0000~\u0000\u0000ppq\u0000~\u0000\u000esq\u0000~\u0000 ppsq\u0000~" +"\u0000\"q\u0000~\u0000%pq\u0000~\u0000&q\u0000~\u0000-q\u0000~\u00001sq\u0000~\u0000+t\u0000\u0001yq\u0000~\u00005sr\u0000\"com.sun.msv.gramma" +"r.expressionpool\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0000\u0001l\u0000\bexptablet\u0000/lcom/sun/msv/gramma" +"r/expressionpool$closedhash;xpsr\u0000-com.sun.msv.grammar.expres" +"sionpool$closedhash\u00d7j\u00d0n\u00ef\u00e8\u00ed\u001c\u0003\u0000\u0003i\u0000\u0005countb\u0000\rstreamversionl\u0000\u0006par" +"entt\u0000$lcom/sun/msv/grammar/expressionpool;xp\u0000\u0000\u0000\u0005\u0001pq\u0000~\u0000\u0005q\u0000~\u0000!" +"q\u0000~\u00008q\u0000~\u0000\nq\u0000~\u00007x")); return new com.sun.msv.verifier.regexp.redocumentdeclaration(schemafragment); public class Unmarshaller extends generated.impl.runtime.abstractunmarshallingeventhandlerimpl { public Unmarshaller(generated.impl.runtime.UnmarshallingContext context) { super(context, "-------"); protected Unmarshaller(generated.impl.runtime.UnmarshallingContext context, int startstate) { this(context); state = startstate; public java.lang.object owner() { return generated.impl.pointtypeimpl.this; public void enterelement(java.lang.string uri, java.lang.string local, java.lang.string qname, org.xml.sax.attributes atts) throws org.xml.sax.saxexception { int attidx; outer: while (true) { switch (state) { case 3 : if (("y" == local)&&("" == uri)) { context.pushattributes( atts, true); state = 4; return ; break; case 0 : if (("x" == local)&&("" == uri)) { context.pushattributes( atts, true); state = 1; return ; break; 308 lignes pour <point><x>1</x><y>2</y></point> 38 fichiers 219 Ko de code
JAXB 2.0 Classe générée @XmlAccessorType(FIELD) @XmlType(name =, proporder = { x, Y ) @XmlRootElement(name = point ) public class Point { protected float x; protected flota y; public float getx() { return x; public void setx(float value) { this.x = value; public float gety() { return y; public void sety(float value) { this.y = value; 62 lignes pour <point><x>1</x><y>2</y></point> 2 fichiers 3 Ko de code
Lookup J2EE 1.4 public class MyEJB implements SessionBean { private DataSource myds; public void ejbcreate() { try { InitialContext ctx = new InitialContext(); myds = (DataSource)ctx.lookup( myds ); catch (NamingException ex) { // Que faire + le descripteur de déploiement XML
Injection en Java EE 5 @Stateless public class MyEJB { @Resource(name= myds ) DataSource myds; @EJB private HelloEJB helloejb;
Moins de lignes de code Adventure Builder J2EE 1.4 67 classes, 3284 lignes de code Java EE 5 43 classes, 2777 lignes de code 36% de classes en moins RosterApp J2EE 1.4 17 classes, 987 lignes de code Java EE 5 7 classes, 716 lignes de code J2EE 1.4 descripteurs XML 9 fichiers, 792 lignes Java EE 5 descripteurs XML 1 fichier, 5 lignes 58% de classes en moins, 89% de fichiers XML en moins
IDEs pour Java EE 5 NetBeans IntelliJ IDEA Eclipse JBuilder JDeveloper JBoss IDE BEA Workshop Studio Sun Java Studio Creator (JSF)
Les serveurs d applications GlassFish & Sun Java System AppServer BEA's WebLogic Server 10 TmaxSoft JEUS 6 SAP Netweaver 7.1 Oracle OC4J 11 Apache Geronimo 2.0 JOnAS 5.0 Websphere 7 JBoss 5.0 beta
Tests Pas de spécification JUnit HTTPUnit Canoo WebTest Mock Plus facile à tester POJO JPA, moins besoin du conteneur (EntityManager) Ejb3Unit (out of container EJB 3.0 testing) JBoss et GlassFish V3 EJB 3 embeddable container
Le déploiement est facilité Descripteurs de déploiement optionnels (ejbjar.xml, application.xml) sauf web.xml, faces-config.xml Utilisation des annotations définir les composants (EJB, WebService ) ORM avec JPA (@Entity, @Id, @Colmumn ) définir sécurité (@DenyAll, @PermitAll ) mode transactionnel (@TransactionAttribute) Pour les clients riches Java Web Start Application Client Container
Packaging Conventions.war pour les applications web.rar pour les ressources Le répertoire lib contient les fichiers jar commun à l application (classpath automatique).jar avec un attribut Main-Class pour les applications clientes (ACC).jar avec une classe annotée @Stateless pour les EJBs.ear pour les applications d entreprise
Packaging
Compatibilité avec J2EE 1.4 Compatibilité ascendante assurée dans la spécification EJB 3.0 peuvent être clients des EJB 2.1 (et inversement) JPQL peut être utilisé dans les méthodes finder() des anciens EJB 2.1 Compatibilité des EL ($, #) entre JSP et JSF JSP 2.0 s exécutent dans un conteneur JSP 2.1
Les patterns? DTO Les Entity JPA peuvent servir de DTO DAO EntityManager pour requêtes simples (CRUD) DAO générique Service Locator Injection, Application Client Container Delegate Injection Action Controller JSF Managed Bean
Java EE 5 et Couche Web Pas autant d améliorations que la couche EJB JSP 2.1, JSF 1.2, JSTL Problèmes maintenus Back-refresh du navigateur Double click, double thread Dialogues/flow => Application, Session, Request => JBoss Seam (future WebBeans avec Java EE 6) Utilisation d autres frameworks Clay, Yahoo UI, Facelets, Seam, Shale, Ajax4JSF, ICEFaces, Avatar Java EE 5 : rupture enterprise, pas web!
Agenda Présentation Java EE 5 Java EE 5 vs J2EE 1.4 Java EE 6 EJB 3.1 Encore plus facile Nouvelles fonctionnalités Questions
A propos de Java EE 6 Développé sous la JSR 316 Sortie Q1 2009 (+ GlassFish V3) Utilisation de profiles Pruning : suppression progressive EJB CMP => JPA JAX-RPC => JAX-WS Servlet 3.0 et JSF 2.0 (annotations) WebBeans 1.0 (inspiré de JBoss Seam) JAX-RS 1.0: RESTful Web Services
~27 specifications Contenu Java EE 6 Web : JSF 2.0, JSP 2.2, JSTL 1.2, Servlet 3.0, JAX- RS 1.0, Web Beans 1.0 Enterprise : Common Annotations 1.0, EJB 3.1, JAF 1.1, JavaMail 1.4, JCA 1.5, JMS 1.1, JPA 2.0, JTA 1.1 Web Services : JAX-RPC 1.1, JAX-WS 2.0, JAXB 2.0, SAAJ 1.0, StAX 1.0, Web Services 2.0, Web Services Metadata 2.0 Management & Security : JACC 1.1, Java EE Application Deployment 1.2, Java EE Management 1.1
Servlet 2.5 Servlet public class SimpleSample extends HttpServlet { public void doget (HttpServletRequest req, HttpServletResponse res){ web.xml <web-app> <servlet> <servlet-name>myservlet</servlet-name> <servlet-class>samples.simplesample</servlet-class> </servlet> <servlet-mapping> <servlet-name>myservlet</servlet-name> <url-pattern>/myapp</url-pattern> </servlet-mapping> </web-app>
Servlet 3.0 @Servlet(urlMapping= MyApp, name= MyServlet ) public class SimpleSample { @Get public void handleget(httpservletrequest req, HttpServletResponse res) {
Servlet 3.0 Développé sous la JSR 315 web.xml (optionel) modulaire Découpé en web-fragment Servlet asynchrone (style Comet) Programmation par exception @Servlet, @ServletFilter, @ServletListener
JSF 2.0 Développé sous la JSR 314 Inspiré par Facelet Facilite la création de composants graphiques Support d'ajax Moins de configuration (faces-config.xml) Comet?
REST REST (REpresentational State Transfer) Architectures orientées ressource Tout est ressource Toute ressource est adressable par une URL Sémantique CRUD GET /articles/123 DELETE /articles/123 Créer Lire Mise à jour Supprimer SQL INSERT SELECT UPDATE DELETE HTTP PUT GET POST DELETE
JAX-RS 1.0 @Remote @Path("orders/{order_id") public class OrderResource { @Get Order getorder(@pathparam("order_id") String id) {...
Web Beans 1.0 Développé sous la JSR 299 Inspiré de JBoss Seam Spec Lead : Gavin King Unifie la couche web et enterprise Glue entre composants (JSF et les EJBs) Contexte conversationel Un composant Web Beans peut être : EJB Managed Bean JSF Entity JPA POJO
Web Beans 1.0 Composant Web Beans public @Component class Hello { public String say(string name) { return "hello " + name; JSF <h:commandbutton value="say Hello" action="#{hello.say"/>
Web Beans 1.0 Composant Web Beans @Stateless public @Component class Hello { public String say(string name) { return "hello " + name; JSF <h:commandbutton value="say Hello" action="#{hello.say"/>
Agenda Présentation Java EE 5 Java EE 5 vs J2EE 1.4 Java EE 6 EJB 3.1 Encore plus facile Nouvelles fonctionnalités Questions
Goals Easier to use New features EJB 3.1 EJB 3.1 - JSR 318 Shipped with Java EE 6 JSR 316 Started in August 2007 ~20 expert members : companies/individuals Early draft in February 2008 JPA has its own spec JSR 317
Still under work APIs might change Q1 2009 Disclaimer
Agenda Présentation Java EE 5 Java EE 5 vs J2EE 1.4 Java EE 6 EJB 3.1 Encore plus facile Nouvelles fonctionnalités Questions
Local interface @EJB private Hello h;... h.sayhello(); @Local public interface Hello { String sayhello(); @Stateless public class HelloBean implements Hello { public String sayhello() { return "Hello Tours JUG!";
Optional local interface Interfaces are not always needed no-interface view Just the bean All methods are exposed Client injection still needed All container services still available Remote interfaces are not optional!
Optional local interface @EJB private HelloBean h;... h.sayhello(); @Stateless public class HelloBean { public String sayhello() { return "Hello Tours JUG";
Packaging in ear file
Packaging EJB ==.ear lib directory has simplified deployment But ear file is still needed to deploy an EJB Even for a simple web application => Deploy an EJB 3.1 in a war file Keeping all EJBs functionalities
Packaging in war file
Java EE 6 profiles Still in discussion!!! Web Servlet 3.0 JSP 2.2 JSR-45 EL 1.2 JSTL 1.2 JSR-250 Web Dev Servlet 3.0 JSP 2.2 JSR-45 EL 1.2 JSTL 1.2 JSR-250 EJB 3.1 (Lite) JTA 1.1 JPA 2.0 JSF 2.0 Web Beans 1.0 Full platform Servlet 3.0 JSP 2.2 JSR-45 EL 1.2 JSTL 1.2 JSR-250 EJB 3.1 JTA 1.1 JPA 2.0 JSF 2.0 Web Beans 1.0 JAX-RS 1.0 Connectors 1.6 JAX-WS 2.2 JAXB 2.2 JSR-109 1.2 JSR-181 1.1 JMS 1.1 JAF 1.1 JavaMail 1.4 JSR-115 JSR-196 JSR-88 1.2 JSR-77 1.1 JAX-RPC1.1 JAXR 1.0
EJB «lite» Subset of the EJB 3.1 API To be used in Web profile Local Session Bean Annotations Injection CMT / BMT Interceptors Security Message Driven Beans EJB Web Service Endpoint RMI/IIOP Interoperability Remote interface EJB 2.x Timer service CMP / BMP
Global JNDI names Client inside a container @EJB Hello h; Client outside a container Context ctx = new InitialContext(); Hello h = (Hello) ctx.lookup(???);
Global JNDI names Not defined in Java EE Vendor specific Not portable No standard syntax mappedname is a partial solution Global JNDI names are not just for EJBs (datasource, connection factories, queues...) Work in progress!!!
Agenda Présentation Java EE 5 Java EE 5 vs J2EE 1.4 Java EE 6 EJB 3.1 Encore plus facile Nouvelles fonctionnalités Questions
Singleton New session bean component Looks like a stateless / stateful no interface view/local/remote interface One single EJB per application per JVM Use to share state in the entire application State not preserved after container shutdown Container initialization startup
Singleton @Singleton public class CachingBean { private Map cache; @PostConstruct void init() { cache =...; public Map getcache() { return cache; public void addtocache(object key, Object val) { cache.put(key, val);
Singleton and concurrency Single thread (default) too restrictive One instance / Multiple threads CMC (Container Managed Concurrency) Concurrency through annotations Exclusive / shared lock Timeout BMC (Bean Managed Concurrency) synchronized keyword
Read-Only Singleton (with CMC) @Singleton public class CachingBean { private Map cache; @ReadOnly public Map getcache() { return cache; public void addtocache(object key, Object val) { cache.put(key, val);
Read-Mostly Singleton (with CMC) @Singleton @ReadOnly public class CachingBean { private Map cache; public Map getcache() { return cache; @ReadWrite public void addtocache(object key, Object val) { cache.put(key, val);
syncronized Singleton (BMC) @Singleton @BeanManagedConcurrency public class CachingBean { private Map cache; public Map getcache() { return cache; synchronized public void addtocache(object key, Object val){ cache.put(key, val);
Singleton Startup Richer lifecycle Container initialization Container shutdown Same callback annotations @PostConstruct / @PreDestroy @Startup Forces initialization at statup
Singleton Startup @Singleton @Startup public class CachingBean { private Map cache; @PostConstruct void init() { cache =...; public Map getcache() { return cache; public void addtocache(object key, Object val) { cache.put(key, val);
Timer Service Added in EJB 2.1 Didn't change in 3.0 Improved in 3.1 Timer Service Programmatic and Calendar based scheduling Cron-like syntax (but nicer)
Timer Service «Last day of the month» «Every Friday at 4pm» «Every five minutes on Monday and Thursday» Cron syntax second [0..59], minute [0..59], hour [0..23], year DayOfMonth [0..31] DayOfWeek [0..7] or [sun, mon, tue..] Month [1..12] or [jan,feb..]
Programmatic Timer Creation @Stateless public class wakeupbean { @Resource TimerService timer; public void createwakeupcall() { // Every weekday at 9 ScheduleExpression expr = new ScheduleExpression(). dayofweek( Mon-Fri ).hour(9); timer.createtimer(expr); @Timeout void wakeup(timer t) {...
Automatic Timer Creation @Stateless public class wakeupbean { @Schedule(dayOfWeek= Mon-Fri, hour= 9 ) void wakeup() {...
Asynchronous call How to have asynchronous call in EJBs? JMS is to send messages not to do asynchronous calls Threads are not allowed (don't integrate well) New model Annotations java.util.concurrent API
Asynchronous call returning void @Stateless public class OrderBean { public void createorder() { Order order = persistorder(); sendemail(order) ; printorder(order); public Order persistorder() {... @Asynchronous public void sendemail(order order) {... @Asynchronous public void printorder(order order) {...
Asynchronous call returning value @Stateless public class OrderBean { public void createorder() { Task task = new Task(...); Future<int> computetask = compute(task);... int result = computetask.get(); @Asynchronous public Future<int> sendemail(task task) { int result =...; return new javax.ejb.asyncresult<int>(result);
Agenda Présentation Java EE 5 Java EE 5 vs J2EE 1.4 Java EE 6 EJB 3.1 Encore plus facile Nouvelles fonctionnalités Questions
Java EE 5 Couvre EJB Stateless, Stateful, MDB (JMS) JPA JSF WebServices Glassfish installation & configuration Pour les développeurs et architectes Inspiré du PetStore de Sun 10 chapitres, développement incrémental
Références Java EE 5 http://java.sun.com/javaee/ http://java.sun.com/javaee/5/docs/tutorial/doc/ GlassFish https://glassfish.dev.java.net/ http://www.glassfishwiki.org/ Livre Java EE 5 http://www.eyrolles.com/ http://www.antoniogoncalves.org
Questions
Java EE 5, 6 et les EJBs 3.1 Antonio Goncalves