Imprimer 

Dans cet article, nous allons voir comment créer un web service de type RESTful utilisant XML. Un autre article suivra avec utilisation du format JSON.

Ce type de Web Service permet de manipuler des ressources à partir de requêtes HTTP avec en entrée ou en sortie du XML :

Pour l'exemple, la ressource sera un projet constitué d'un nom, d'une date de début et d'une date de fin.

Nous utiliserons le serveur Glassfish qui se base sur Jersey concernant les Web services RESTful.

Nous allons donc voir comment créer/modifier/supprimer/rechercher un projet via un Web Service RESTFul XML tout en stockant cette information dans une base MySQL via JPA.

 

Le fichier pom.xml

Il s'agit d'un pom de type war :

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mycompany.prj3</groupId>
    <artifactId>Prj5WebServiceRest</artifactId>
    <version>1.0</version>
    <packaging>war</packaging>

    <name>Prj5WebServiceRest</name>

    <properties>
        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>com.mycompany.prj3</groupId>
            <artifactId>Prj3Beans</artifactId>
            <version>1.0</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>  
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.16</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                    <compilerArguments>
                        <endorseddirs>${endorsed.dir}</endorseddirs>
                    </compilerArguments>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.6</version>
                <executions>
                    <execution>
                        <phase>validate</phase>
                        <goals>
                            <goal>copy</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${endorsed.dir}</outputDirectory>
                            <silent>true</silent>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>javax</groupId>
                                    <artifactId>javaee-endorsed-api</artifactId>
                                    <version>7.0</version>
                                    <type>jar</type>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

 

Création de l'entity Project avec ces annotations JPA

package com.mycompany.prj3.beans;

import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.xml.bind.annotation.XmlRootElement;

/**
 *
 * @author thierry
 */
@Entity
@Table(name = "PROJECT")

@NamedQueries({
    @NamedQuery(name = Project.PROJECT_FIND_ALL_PROJECTS, query = "SELECT dto FROM Project dto"),
    @NamedQuery(name = Project.PROJECT_FIND_BY_ID, query = "SELECT dto FROM Project dto where dto.projectId=:projectId"),
    @NamedQuery(name = Project.PROJECT_FIND_BY_NAME, query = "SELECT dto FROM Project dto where upper(dto.name) like upper (:pName)")
})

@XmlRootElement
public class Project {

    public static final String PROJECT_FIND_ALL_PROJECTS = "PROJECT_FIND_ALL";
    public static final String PROJECT_FIND_BY_ID = "PROJECT_FIND_BY_ID";
    public static final String PROJECT_FIND_BY_NAME = "PROJECT_FIND_BY_NAME";
    public static final String PROJECT_COUNT = "SELECT count(dto.projectId) FROM Project dto";

    public Project() {
    }

    @Id
    @Column(name = "PROJECT_ID")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long projectId;

    @Column(name = "NAME", unique = true, nullable = false)
    private String name;

    @Temporal(TemporalType.DATE)
    @Column(nullable = true)
    private Date startDate ;
            
    @Temporal(TemporalType.DATE)
    @Column(nullable = true)
    private Date endDate;

    public Long getProjectId() {
        return projectId;
    }

    public void setProjectId(Long projectId) {
        this.projectId = projectId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return "Project : name=" + name;
    }

    public Date getStartDate() {
        return startDate;
    }

    public void setStartDate(Date startDate) {
        this.startDate = startDate;
    }

    public Date getEndDate() {
        return endDate;
    }

    public void setEndDate(Date endDate) {
        this.endDate = endDate;
    }

}

 

Création du Web Service REST

Quelques explications :

package com.mycompany.prj3.webservicerest;

import com.mycompany.exception.ExceptionUtil;
import com.mycompany.prj3.beans.Project;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import org.apache.log4j.Logger;

/**
 *
 * @author thierry
 */
@Stateless
@Path("project")
public class ProjectResource  {
  
    private static final Logger logger = Logger.getLogger(ProjectResource.class);
    
    @PersistenceContext(unitName = "puBdProject")
    private EntityManager entityManager;
    
    public ProjectResource() {
    }
    
    @GET
    @Produces("text/xml")
    public Project getProject(@QueryParam("id") Long id) {
        logger.info("In getProject for id : " + id);
        Project project = null;
        try {
            project = entityManager.find(Project.class, id);
        } catch (NoResultException e) {
            logger.error("Exception catchee " + ExceptionUtil.displayException(e));
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }
        logger.info("Project name : " + (project != null ? project.getName() : "Pas de projet"));
        return project;
    }
    
    @POST
    @Consumes("text/xml")
    public void insertProject(Project project) {
        logger.info("In insertProject");
        try {
            entityManager.persist(project);
            logger.info("projectName=[" + project.getName() + "] id=" + project.getProjectId());
            logger.info("startDate=" + (project.getStartDate()!=null ? project.getStartDate() : "Pas de date"));
        } catch (Exception e) {
            logger.error("Exception catchee " + ExceptionUtil.displayException(e));
        }
    }
    
    @GET
    @Produces("text/xml")
    @Path("/all/")
    public List<Project> getProjects() {
        logger.info("In getProjects");
        List<Project> list = null;
        try {
            list = entityManager.createNamedQuery(Project.PROJECT_FIND_ALL_PROJECTS).getResultList();
            logger.info("Nombre de projet : " + (list != null ? list.size() : "0"));
        } catch (Exception e) {
            logger.error("Exception catchee " + ExceptionUtil.displayException(e));
        }
        
        return list;
    }
    
    @PUT
    @Consumes("text/xml")
    public void updateProject(Project project) {
        logger.info("In updateProject");
        try {
            entityManager.merge(project);
            logger.info("projectName=[" + project.getName() + "] id=" + project.getProjectId());
        } catch (Exception e) {
            logger.error("Exception catchee " + ExceptionUtil.displayException(e));
        }
    }
    
    @DELETE
    @Consumes("text/xml")
    public void deleteProject(@QueryParam("id") Long id) {
        logger.info("In deleteProject for id " + id);
        try {
            Project project = entityManager.find(Project.class, id);
            logger.info("projectName=[" + project.getName() + "] id=" + project.getProjectId());
            entityManager.remove(project);
        } catch (Exception e) {
            logger.error("Exception catchee " + ExceptionUtil.displayException(e));
        }
    }
}

 

Configuration de Glassfish pour la prise en charge des URL représentant des web services REST

Il faut indiquer que certaines URL, celles correspondantes aux web services REST que nous voulons exposés, soient prise en compte par Jersey.

Pour cela deux méthodes :

package com.mycompany.prj3.webservicerest;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("resources")
public class JaxRsConfig extends Application {
} 

 

Pour tester le Web Service

Pour tester le GET, entrer l'URL via le navigateur : 

Par contre, pour un POST/PUT/DELETE, nous utilisons curl.

 

Code source

Prj5WebServiceRest.zip