TP Handlers JAX-WS

Liens

Travail

Reprendre un des services codé dans le TP précédent comme base. Le TP est à rendre sur spiral pour le 23/12.

Vous pouvez également partir du projet suivant: storecalservicedummy.zip

Le TP a été testé sur Tomcat avec la pile CXF.

Handler de log

Créer une classe LogHandler pour implémenter un handler qui va afficher l'élément principal des messages reçus et envoyés, ainsi que la date. Pour cela, la classe doit implémenter l'interface LogicalHandler<LogicalMessageContext>, le log se faisant dans la méthode handleMessage.

Configurer le service pour utiliser le handler et tester avec soapUI

Ajout d'information

Créer une classe étendant SOAPHandler<SOAPMessageContext>. Si un élément {http://master-info.univ-lyon1.fr/M2TI/sw/store-cal/}user 1) est dans le header SOAP, prendre sa valeur et ajouter au contexte un propriété user avec cette valeur.

Question optionnelle: Modifier le WSDL pour y intégrer les déclarations de header (voir ici).

Intégrer ce handler de tel façon qu'il soit exécuté avant le handler de log sur un message entrant. Modifier le handler de log de façon à afficher la propriété user.

Ajout d'information - 2

Créer un handler supplémentaire qui, lors du stockage d'un calendrier, ajoute dans la base de donnée l'information de l'utilisateur ayant demandé ce stockage (le “propriétaire” du calendrier) et intégrer ce handler dans la chaine de handlers du service.

Contrôle d'accès

Ajouter un ou plusieurs handlers permettant d'effectuer un contrôle d'accès:

  • un utilisateur ne peut pas écraser un calendrier créé par un autre,
  • un utilisateur ne peut lire que les calendriers qu'il a lui même stocké.

On pourra empêcher l'accès/la modification en lançant une exception SOAPFaultException ou ProtocolException (selon le type de handler). On fera attention à l'ordre des handlers dans la chaine.

Annexes

Exemple de fichier service.xml avec quelques handlers ainsi que de l'injection de dépendance2):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:jaxws="http://cxf.apache.org/jaxws"
      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
 
    <import resource="classpath:META-INF/cxf/cxf.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
 
	<bean id="dsp" class="m2ti.ti3.storecalservice.DataSourceProvider"/>
	<bean id="ws" class="m2ti.ti3.storecalservice.StoreCalServiceImpl">
		<property name="datasourceProvider" ref="dsp"/>
	</bean>
	<bean id="logHandler" class="m2ti.ti3.storecalservice.handlers.LogHandler" />
	<bean id="userHandler" class="m2ti.ti3.storecalservice.handlers.UserHandler" />
	<bean id="checkUserHandler" class="m2ti.ti3.storecalservice.handlers.UserCheckHandler">
		<property name="datasourceProvider" ref="dsp"/>
	</bean>
 
    <jaxws:endpoint id="storecalservice"
                  implementor="#ws"
                  address="/StoreCalService">
    	<jaxws:handlers>
    		<ref bean="logHandler" />
    		<ref bean="checkUserHandler"/>
    		<ref bean="userHandler" />
    	</jaxws:handlers>              
    </jaxws:endpoint>
</beans>

et le fichier web.xml qui l'utilise:

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <display-name>StoreCalService</display-name>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
		classpath:m2ti/ti3/storecalservice/services.xml
        </param-value>
    </context-param>
 
    <listener>
        <listener-class>
		org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
 
    <servlet>
        <servlet-name>CXFServlet</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CXFServlet</servlet-name>
        <url-pattern>/services/*</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
 
 
    <!-- lien vers un datasource configuré dans tomcat -->
    <resource-ref>
        <description>Datasource for StoreCalService</description>
        <res-ref-name>jdbc/StoreCalDS</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>
 
 
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

Fichier de configuration pour le tomcat exécuté via maven3), src/main/webapp/META-INF/context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Context path="/StoreCalService">
  <!-- connection à la base orapeda1 via le tunnel ssh -->
  <Resource auth="Container" driverClassName="oracle.jdbc.OracleDriver" 
            maxActive="20" maxIdle="10" maxWait="-1" name="jdbc/StoreCalDS" 
            password="xxxxxx" type="javax.sql.DataSource" 
            url="jdbc:oracle:thin:@localhost:1521:orapeda1" username="xxxxxx"/>
</Context>
1)
l'URI entre accolade est le namespace
2)
la classe DataSourceProvider contient simplement une méthode permettant de récupérer un Datasource pour établir une connexion au SGBD
3)
mvn tomcat:run