@Entity
@XmlRootElement
@NamedQuery(name = "Person.findAll", query = "select p from Person p")
public class Person {
@Id
@GeneratedValue
private long id;
private String 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;
}
JPA com EclipseLink e Jersey
Neste exemplo, um serviço da web é criado para armazenar e recuperar dados do banco de dados. Jersey será usado para criar o serviço da web.. Para o banco de dados, o provedor JPA usado será EclipseLink.
O serviço da web irá armazenar e recuperar informações sobre pessoas:
Os dois serviços que nosso aplicativo oferece são: persistir uma pessoa, recuperando todas as pessoas do banco de dados:
@Singleton
@Lock(LockType.READ)
public class PersonDAO {
@PersistenceContext
private EntityManager em;
public Person save(final String name) {
final Person person = new Person();
person.setName(name);
em.persist(person);
return person;
}
public List<Person> findAll() {
return em.createNamedQuery("Person.findAll", Person.class).getResultList();
}
A seguir, estamos prontos para expor como um serviço esta lógica de negócios:
@Path("/person")
@RequestScoped
public class PersonService {
@Inject
private PersonDAO dao;
public PersonService() {
System.out.println();
}
@GET
@Path("/create/{name}")
public Person create(@PathParam("name") final String name) {
return dao.save(name);
}
@GET
@Path("/all")
public List<Person> list() {
return dao.findAll();
}
Agora que temos uma classe de serviço, definindo os recursos fornecidos pelo aplicativo, estendemos a classe jakarta.ws.rs.core.Application
e adicionamos nosso PersonService
:
public class JerseyApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
final Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(PersonService.class);
return classes;
}
}
Há mais uma etapa a ser executada para configurar um servlet fornecido por Jersey.
Isso pode ser feito em webapp/WEB-INF/web.xml
:
<web-app 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_3_0.xsd"
version="3.0">
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jakarta.ws.rs.Application</param-name>
<param-value>org.superbiz.service.JerseyApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
O serviço da web está pronto para ser testado. Para isso, vamos escrever um teste de unidade usando Arquillian:
@RunWith(Arquillian.class)
public class JerseyApplicationTest {
@Deployment(testable = false)
public static WebArchive createDeployment() {
return ShrinkWrap.create(WebArchive.class, "jersey-application.war")
.addPackage(JerseyApplication.class.getPackage())
.addPackage(Person.class.getPackage())
.addPackage(PersonDAO.class.getPackage())
.addAsManifestResource(new FileAsset(new File("src/main/webapp/WEB-INF/web.xml")), "web.xml")
.addAsManifestResource(new ClassLoaderAsset("META-INF/persistence.xml"), "persistence.xml")
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
}
@ArquillianResource
private URL webapp;
@Test
public void test() {
get("person/create/TestPerson");
String allPersons = get("person/all");
assertTrue(allPersons.contains("<name>TestPerson</name>"));
}
private String get(String url) {
final CloseableHttpClient client = HttpClients.custom().build();
final HttpHost httpHost = new HttpHost(webapp.getHost(), webapp.getPort(), webapp.getProtocol());
final HttpClientContext context = HttpClientContext.create();
final HttpGet get = new HttpGet(webapp.toExternalForm() + url);
CloseableHttpResponse response = null;
try {
response = client.execute(httpHost, get, context);
return EntityUtils.toString(response.getEntity());
} catch (final IOException e) {
throw new IllegalStateException(e);
} finally {
try {
IO.close(response);
} catch (final IOException e) {
// no-op
}
}
}
}
Usamos o Arquillian para iniciar programaticamente um novo container de teste. Em um teste, uma pessoa é persistida e sua presença no banco de dados é verificada recuperando todas as entidades de pessoa.
Um exemplo completo pode ser encontrado aqui.
É um projeto maven, e o teste pode ser executado com o comando mvn clean install
.