Whenever building a Java EE 6 or 7 application always use the javax:javaee-api maven dependency and only that. So lets start with a Java EE 7 maven pom.xml
<?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>se.magnuskkarlsson.examples</groupId>
<artifactId>example-javaee7</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>example-javaee7</finalName>
</build>
</project>
To make JAX-RS work we need to add an class that extends Application and annotated with @ApplicationPath.
package se.magnuskkarlsson.example.javaee7;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath("/rest")
public class JavaEE7Application extends Application {
}
Then we can write our Boundary JAX-RS class.
package se.magnuskkarlsson.example.javaee7.boundary;
import java.net.URI;
import java.util.List;
import javax.inject.Inject;
import javax.validation.Valid;
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.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import se.magnuskkarlsson.example.javaee7.control.EmployeeBean;
import se.magnuskkarlsson.example.javaee7.entity.Employee;
@Path("/employee")
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public class EmployeeRest {
@Inject
EmployeeBean bean;
// returns 200 OK if found, othereise 204 No Content
@GET
@Path("/{id}")
public Employee findById(@PathParam(value = "id") long id) {
return bean.findById(id);
}
// returns 200 OK, otherwise empty JsonArray
@GET
public List<Employee> findAll() {
return bean.findAll();
}
// returns 201 Created and Location header, otherwise 400 Bad Request and reason in body
@POST
public Response create(@Context UriInfo uriInfo, @Valid Employee employee) {
long id = bean.create(employee).getId();
URI location = uriInfo.getAbsolutePathBuilder().path("/" + id).build();
return Response.created(location).build();
}
// returns 200 OK, otherwise 400 Bad Request and reason in body
@PUT
public Employee update(@Valid Employee employee) {
return bean.update(employee);
}
// returns always 204 No Content
@DELETE
@Path("/{id}")
public void delete(@PathParam(value = "id") long id) {
bean.delete(id);
}
}
And our business logic we encapsulate in a Controller class.
package se.magnuskkarlsson.example.javaee7.control;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException;
import javax.persistence.PersistenceContext;
import se.magnuskkarlsson.example.javaee7.entity.Employee;
@Stateless
public class EmployeeBean {
@PersistenceContext
private EntityManager em;
public Employee findById(long id) {
return em.find(Employee.class, id);
}
public List<Employee> findAll() {
return em.createQuery("FROM Employee e").getResultList();
}
public Employee create(Employee employee) {
em.persist(employee);
return employee;
}
public Employee update(Employee employee) {
em.merge(employee);
return employee;
}
public void delete(long id) {
try {
Employee employee = em.getReference(Employee.class, id);
em.remove(employee);
} catch (EntityNotFoundException IGNORE) {
// we want to delete anyway ...
}
}
}
And finally our Entity class.
package se.magnuskkarlsson.example.javaee7.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
@Entity
@XmlRootElement
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private Long id;
@Column(length = 255)
@Size(min = 3, max = 255)
private String name;
public Employee() {
}
public Employee(Long id, String name) {
this.id = id;
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
We also need to a META-INF/persistence.xml file.
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="javaee7" transaction-type="JTA">
<properties>
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
</properties>
</persistence-unit>
</persistence>
And a WEB-INF/beans.xml file to make our application CDI aware.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="all">
</beans>
To test this build and deploy your application to, e.g. JBoss EAP 7.
Then create a new simple java project that we suffix with -st, for system test. In that pom.xml we need to add a jax-rs and json-p implementation dependency.
<?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>se.magnuskkarlsson.examples</groupId>
<artifactId>example-javaee7-st</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- jax-rs reference implementation -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.17</version>
<scope>test</scope>
</dependency>
<!-- json-p reference implementation -->
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.0.4</version>
<scope>test</scope>
</dependency>
<!-- the glue between jax-rs and json-p reference implementation -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-processing</artifactId>
<version>2.17</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Now lets write our system test.
package se.magnuskkarlsson.example.javaee7.boundary;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import static javax.ws.rs.core.MediaType.*;
import javax.ws.rs.core.Response;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
public class EmployeeRestIT {
private Client client;
private WebTarget target;
@Before
public void setUp() throws Exception {
client = ClientBuilder.newClient();
target = client.target("http://localhost:8080/example-javaee7/rest/employee");
}
@Test
public void crud() throws Exception {
JsonObjectBuilder builderCreate = Json.createObjectBuilder();
JsonObject input = builderCreate.add("name", "Foo Bar").build();
Response respCreate = target.request(APPLICATION_JSON).post(Entity.json(input));
assertThat(respCreate.getStatus(), is(201));
String location = respCreate.getHeaderString("Location");
assertNotNull(location);
Response respGet = client.target(location).request(APPLICATION_JSON).get();
assertThat(respGet.getStatus(), is(200));
JsonObject payload = respGet.readEntity(JsonObject.class);
System.out.println("payload='" + payload + "'");
int id = payload.getInt("id");
JsonObjectBuilder builderUpdate = Json.createObjectBuilder();
JsonObject update = builderUpdate.add("id", id).add("name", "UPDATED!").build();
Response respUpdate = target.request(APPLICATION_JSON).put(Entity.json(update));
assertThat(respCreate.getStatus(), is(201));
System.out.println("respUpdate=" + respUpdate.readEntity(JsonObject.class));
Response respDelete = target.path("/" + id).request(APPLICATION_JSON).delete();
assertThat(respDelete.getStatus(), is(204));
}
@Test
public void findNonExisting() throws Exception {
Response response = target.path("/-999").request(APPLICATION_JSON).get();
assertThat(response.getStatus(), is(204));
String payload = response.readEntity(String.class);
assertThat(payload, is(""));
}
@Test
public void findAll() throws Exception {
Response resp = target.request(APPLICATION_JSON).get();
assertThat(resp.getStatus(), is(200));
JsonArray array = resp.readEntity(JsonArray.class);
assertThat(array.size(), is(0));
}
@Test
public void updateInvalid() throws Exception {
JsonObjectBuilder builder = Json.createObjectBuilder();
JsonObject input = builder.add("name", "E").build();
Response response = target.request(APPLICATION_JSON).put(Entity.json(input));
assertThat(response.getStatus(), is(400));
System.out.println("status : " + response.getStatus());
System.out.println("entity : " + response.readEntity(String.class));
response.getHeaders().forEach((key, value) -> System.out.println(key + ": " + value));
}
@Test
public void delete() throws Exception {
JsonObjectBuilder builder = Json.createObjectBuilder();
JsonObject input = builder.add("name", "Foo Bar").build();
Response respCreate = target.request(APPLICATION_JSON).post(Entity.json(input));
assertThat(respCreate.getStatus(), is(201));
String location = respCreate.getHeaderString("Location");
assertNotNull(location);
Response respDelete = client.target(location).request(APPLICATION_JSON).delete();
assertThat(respDelete.getStatus(), is(204));
}
@Test
public void deleteNonExisting() throws Exception {
Response respDelete = target.path("/-999").request(APPLICATION_JSON).delete();
assertThat(respDelete.getStatus(), is(204));
}
}
No comments:
Post a Comment