mai
2009
Une nouveauté qui sera présenté à la JavaOne et dont le brouillon final sera livré d’ici la fin de la semaine.
Des nouveautés qui permettront de facilité le développement.
L’interaction avec le fichier de configuration sera moindre avec l’apparition d’annotations :
@WebServlet
@WebServletContextListener
@ServletFilter
@InitParam
Pour les annotations, je vais vous donner une série d’exemple de code qui vous permettra de comprendre mieux ce que les annotations pourraient apporter et pourquoi, les servlet 3.0 sont une série de nouveautés majeur tel que l’on connu les EJB 3.0.
Pour @WebServlet, il suffit de faire :
import javax.servlet.annotation.InitParam;
import javax.servlet.annotation.WebServlet;
@WebServlet(
name = "SimpleServlet",
urlPatterns = {"/simple"},
initParams = {
@InitParam(name = "param1", value = "value1"),
@InitParam(name = "param2", value = "value2")}
)
public class SimpleServlet {
}
Ceci reviendrait à faire :
<servlet-name>SimpleServlet</servlet-name>
<servlet-class>com.developpez.x-plode.newfeatures.SimpleServlet</servlet-class>
<init-param>
<param-name>param1</param-name>
<param-value>value1</param-value>
</init-param>
<init-param>
<param-name>param2</param-name>
<param-value>value2</param-value>
</init-param>
</servlet>
<servlet-mapping>
<url-pattern>/simple</url-pattern>
<servlet-name>SimpleServlet</servlet-name>
</servlet-mapping>
Un exemple pour @WebServletContextListener :
import javax.servlet.ServletContextEvent;
import javax.servlet.annotation.WebServletContextListener;
@WebServletContextListener()
public class SimpleServletContextListener {
public void contextInitialized(ServletContextEvent event){
}
public void contextDestroyed(ServletContextEvent event){
}
}
Ceci reviendrait à faire dans le web.xml :
<listener>
<listener-class> com.developpez.x-plode.newfeatures.SimpleServletContextListener
</listener-class>
</listener>
</web-app>
Enfin @ServletFilter,
import javax.servlet.annotation.InitParam;
import javax.servlet.annotation.ServletFilter;
@ServletFilter(
filterName = "SimpleFilter",
urlPatterns = "/simple",
initParams =
{@InitParam(name = "param1", value = "value1"),
@InitParam(name = "param2", value = "value2")}
)
public class SimpleFilter {
}
Le web.xml,
<filter-name>SimpleFilter</filter-name>
<filter-class> com.developpez.x-plode.newfeatures.SimpleFilter</filter-class>
<init-param>
<param-name>param1</param-name>
<param-value>value1</param-value>
</init-param>
<init-param>
<param-name>param2</param-name>
<param-value>value2</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>SimpleFilter</filter-name>
<url-pattern>/simple</url-pattern>
<filter-mapping>
L’intégration des frameworks
Le web.xml tel que nous le connaissons à l’heure actuelle :
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
</web-app>
Le problème, ici, est qu’il n’est pas modulable. Tous la configuration à propos d’une application est inclus dans un fichier unique le web.xml. Le problème qui apparaît est que si nous souhaitons utilisé un ou plusieurs frameworks, il n’y a aucun moyen pour charger la Servlet Container pour l’usage d’un framework spécifique. La seule option que nous pourrions faire, serait d’éditer le descripteur de déploiement.
Pour ce faire, les Servlets 3.0 apportent une nouveauté les web fragments.
Web fragments, web fragments, … Qu’est ce que c’est encore ?
Ok, démonstration d’une déclaration d’un web fragment
<servlet>
<servlet-name>myservlet</servlet-name>
<servlet-class>samples.MyServlet</servlet-class>
</servlet>
<listener>
<listener-class>samples.MyListener</listener-class>
</listener>
</web-fragment>
En fait, un web fragment, peut être considéré comme un web.xml à part entière.
Durant le démarrage de l’application, il est de la responsabilité du Container de scanner les informations trouvées dans le fichier /META-INF/web-fragment.xml.
Enfin, la nouvelle API autorise la déclaration d’une servlet, de classes filtres ou de l’url de mappings de ces dernières.
Par l’exemple :
public class MyListener {
public void contextInitialized (ServletContextEvent sce) {
ServletContext sc = sce.getServletContext();
//Declaration d’une servlet et du mappage de servlet
sc.addServlet("myServlet", "Sample servlet", "samples.MyServlet", null, -1);
sc.addServletMapping("myServlet", new String[] {"/urlpattern/*"});
//Declaration du filtre et du mappage du filtre
sc.addFilter("myFilter", "Sample Filter", " samples.MyFilter", null);
sc.addFilterMapping("myFilter", new String[] {"/urlpattern/*"}, "myServlet",DispatcherType.REQUEST, false);
}
}
Les requêtes asynchrones
Voici un petit schéma explicatif :
Et par le code ?
import java.io.IOException;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.ServletRequest;
public class SimpleAsyncListener implements AsyncListener{
public void onComplete(AsyncEvent event) throws IOException {
}
public void onTimeout(AsyncEvent event) throws IOException {
}
}
On ajoute ainsi le listener à la requête de l’objet :
request.addAsyncListener(new SimpleAsyncListener());
La même chose peut être fait par les annotations Web Servlet et la Servlet Filtre par les attributs asyncSupported et asyncTimout.
import javax.servlet.annotation.InitParam;
import javax.servlet.annotation.WebServlet;
@WebServlet(
name = "SimpleServlet",
urlPatterns = {"/simple"},
initParams = {
@InitParam(name = "param1", value = "value1"),
@InitParam(name = "param2", value = "value2")},
asyncSupported = true,
asyncTimeout = 3000
)
public class SimpleServlet {
}
Je tiens à remercier Rajiv Mordani ( responsable de la spec JSR 315 ), pour les informations qu’il m’a transmise afin de pouvoir réaliser cet article.
10 Commentaires + Ajouter un commentaire
Articles récents
- Nouvelle du jour : ce blog reprend vie :)
- Google acquiert les brevets applicatifs de Cuil
- 12 Méthodes d’analyse des liens qui auraient pu changer au sein de Google en février 2012
- Nouveautés chez Google dans les outils pour les webmasters
- Google fait un rappel important sur le prestataire pour l’hébergement de votre site internet
Commentaires récents
- Pourquoi Oracle devrait continuer à aider Netbeans ? dans
- Soirée GlassFish & Groovy à l’INSA avec le JUG de Lyon dans
- Une annonce de James Gosling (le créateur de Java) pour les membres de Developpez.com dans
- Une annonce de James Gosling (le créateur de Java) pour les membres de Developpez.com dans
- Session : Monitoring and Troubleshooting Glassfish application server in the wild dans
J’avais ouvert le débat sur l’utilisation massive des annotations.
Ici, cela me semble largement justifié de faire une annotation ! Plus clair, plus simple, dans le même fichier que ce que l’on veut manipuler.
En ce qui me concerne, je n’utilise presque jamais d’accès direct aux Servlets, tout passe par des JSP qui appellent des beans : c’est un peu plus propre pour relancer du xml. Mais pour une requête qui n’envoie pas un max de XML, c’est plutôt sympa !
C’est bien ce que je dis. Un initParam en annotation est comme une constante mais en moins pratique.
Je pense qu’il faut plus prendre l’initParam comme une valeur par défaut. Je n’ai pas vérifier mais j’ose espérer que l’on peut surcharger le comportement via le xml.
Je n’ai pas « tout » lu mais je suis entièremment d’accord benwit on se retrouve lié avec des apis.
Et devoir écrire une api d’annotations vides.. j’ai vraiment du mal à voir l’avantage.
Ce qui me chatouille le plus dans ces nouvelles annotations ce sont les « initParam ». Je pense que justement des paramètres d’initialisation sont la pour influencer le comportement d’une Servlet sans avoir à la recompiler. Mais si il faut aller dans la classe pour modifier un paramètre je ne vois plus du tout l’intérêt. Ca me semble alors être la même chose qu’une constante mais en moins pratique (il faut tester et typer le paramètre)
je n’ai plus de source en ce qui concerne le débat google guice, mais en gros, la ou spring utilisait le xml et donc avait des beans totalement non dépendant du framework spring lui même (pur pojo quoi), guice se reposait sur l’annotation @Inject. Donc en gros, ca disait, guice c’est mal parce que les pojo ne sont plus des pojos, et qu’ils sont liés (via l’annotation) au framework guice.
la réponse (que je trouve valide) est que les annotations ne sont « que » des annotations. au pire, tu refaits l’annotation dont tu dépends a la compilation dans ton code (un genre de mock d’annotation), avec une portée compilation, et hop.
Donc de meme pour l’api servlet : si tu ne veux pas en dépendre, mais que ton code se repose dessus : tu peux te faire un petit jar dans lesquels tu colles un javax.servlet.annotation.WebServlet home made qui ne fait rien du tout, et utiliser ta servlet dans un serveur d’application pas JEE qui utilise une autre approche que l’api servlet.
Salut,
je ne sais pas si la spécification a été complétée (peut être as-tu la réponse) mais, en décembre, un des problèmes était que lors de l’utilisation de plusieurs filtres, la spécification n’adresse pas la question de l’ordre d’exécution.
Bonjour,
Sur le sujet plus général des annotations, il y a un débat plutôt actif ici : http://www.developpez.net/forums/d722147/java/communaute-java/debats/multiplication-annotations/
Je ne suis pas certain de bien te comprendre.
J’aimerai que tu m’en dises plus sur les « annotations vides qui ne te serviront que a la compilation. ». De même, as tu un lien pour le débat sur google guice ?
Dans le cas des servlets, je ne trouve pas les annotations gênantes si elles sont dans l’api des servlets parce que là, on n’ajoute pas de dépendances supplémentaires.
Quand j’ai parlé des dépendances, je pensais à ceci :
Prenons un bean de donnée classique indépendant de toute autre api.
Si on utilise la persistance avec JPA, on va ajouter des annotations JPA.
Si on décide d’utiliser JDO, on va ajouter des annotations JDO en plus …
J’ai pas trop creusé alors vous me corrigerez si je dis des bêtises mais j’ai l’impression qu’avec ces annotations, mon bean est à la fois lié aux deux apis non ? Tout du moins dans eclipse qui compile à la volée mais peut être n’est-ce au final pas gênant à l’exécution si on utilise que l’une ou l’autre ?
« on lie son code avec pleins d’apis tierce » : ou pas. le débat avait eu lieu a propos de google guice. si au final tu ne veux pas utiliser l’api servlet, tu peux toujours te faire des annotations vides qui ne te serviront que a la compilation.
Salut,
Autant je trouve cela plutôt pas mal pour les servlets et les filters, autant, pour les listeners, le gain n’est pas énorme. Je comprend néanmoins qu’ils l’aient fait pour un souci de cohérence.
J’aime bien les annotations à la verbosité d’xml mais il ne faudrait pas qu’après la mode xml, on assiste à la mode annotations, à en mettre un peu trop partout ! Bon, tant que c’est facultatif, il est vrai que chacun fait comme il veut.
L’inconvénient que j’y vois, est qu’avec les annotations, on lie son code avec pleins d’apis tierce et cela me plaît moyennement. Cette remarque ne vaut pas pour le cas présent car si c’est prévu dans l’api des servlets, cela ne crée pas de dépendances supplémentaires.