@Provider
public class RuntimeExceptionMapper implements ExceptionMapper<RuntimeException> {
private static final Logger LOGGER = Logger.getLogger(RuntimeExceptionMapper.class.getName());
@Override
public Response toResponse(final RuntimeException e) {
// taken from http://stackoverflow.com/questions/13716793/jersey-how-to-register-a-exceptionmapper-that-omits-some-subclasses
if (e instanceof WebApplicationException) {
return ((WebApplicationException) e).getResponse();
}
LOGGER.log(Level.WARNING, "RuntimeException occurred", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Sorry, something went wrong")
.build();
}
}
Entries tagged [arquillian]
Jersey 1.x ExceptionMapper examples
TweetPosted on Saturday Oct 29, 2016 at 12:42PM in Technology
CAUTION: this posting is about Jersey 1.x which is obsoleted. If you use more modern JAX-RS implementation such as Jersey 2.x or above, please check if there are any better approaches.
JAX-RS (Jersey) provides a mechanism called ExceptionMapper which is an universal way to map an exception that thrown by a JAX-RS implementation itself or application code, to any HTTP response. In this posting, I’ll introduce some basic but useful usages of it that I have found.
ExceptionMapper for RuntimeException
When your resource method throw an Exception, say, an unintentional NullPointerException which caused by a bug or something, typically this produces a 500 Error page which created by your application container. You can catch, log those exceptions and produce a customer-friendly response with an ExceptionMapper which is something like following:
ExceptionMapper for NotFoundException
When your app receive a request which has no corresponding resource method, typically this produces a 404 Error page created by your container as well as an uncaught Exception. You can handle this situation with an ExceptionMapper as follows:
@Provider
public class NotFoundExceptionMapper implements ExceptionMapper<NotFoundException> {
private static final Logger LOGGER = Logger.getLogger(NotFoundExceptionMapper.class.getName());
@Override
public Response toResponse(final NotFoundException e) {
LOGGER.log(Level.FINE, "NotFoundException occurred", e);
return Response.status(Response.Status.NOT_FOUND)
.entity("Check the destination path of your request - we have no API here")
.build();
}
}
ExceptionMapper for ParamExceptionMapper
Let’s say you have a value class which is something like following:
public class EmployeeId {
private final long value;
public EmployeeId(final long value) {
if (value < 1) {
throw new IllegalArgumentException("EmployeeId must be larger than zero");
}
this.value = value;
}
public EmployeeId(final String value) {
this(Long.parseLong(value));
}
// getter and toString omitted
}
And you have a resource method which receives an EmployeeId
as follows:
@Path("myresource")
public class MyResource {
@GET
@Path("emp")
@Produces(MediaType.TEXT_PLAIN)
public String emp(@QueryParam("id") EmployeeId id) {
...
}
}
When the resource method receives a valid id
, say 123
, Jersey automatically constructs an EmployeeId
instance and passes it to the application code. That’s fine, but consider if a malicious user has sent an invalid value, say -1
. Typically this produces an error page which created by your container as well. You may want to return a more informational response with HTTP status code 400
with an ExceptionMapper which is something like:
@Provider
public class ParamExceptionMapper implements ExceptionMapper<ParamException> {
private static final Logger LOGGER = Logger.getLogger(ParamExceptionMapper.class.getName());
@Override
public Response toResponse(final ParamException e) {
LOGGER.log(Level.FINE, "ParamException occurred", e);
final StringBuilder sb = new StringBuilder("Your parameter '" + e.getParameterName() + "' is invalid");
final Throwable cause = e.getCause();
if (cause instanceof IllegalArgumentException) {
final String message = cause.getMessage();
if (message != null && !message.isEmpty()) {
sb.append(": ").append(message);
}
}
return Response.status(Response.Status.BAD_REQUEST)
.entity(sb.toString())
.build();
}
}
Conclusion
ExceptionMapper helps making error responses of your REST APIs more helpful. And it reduces repetitive exception handling code in your resource classes that tend to be tons of boilarplate.
You can obtain complete code based on Jersey 1.x and testcases that powered by Arquillian, Embedded Tomcat and Apache HttpClient, from my GitHub repository.
Tags: arquillian jax-rs jersey
Modifying persistence.xml to execute drop-and-create dynamically
TweetPosted on Monday Mar 23, 2015 at 03:19PM in JPA
I need that for Arquillian testing so I created an utility method for that.
Tags: arquillian jpa
Arquillian EJB-JAR/EAR testing examples
TweetPosted on Friday Mar 20, 2015 at 10:33AM in Arquillian
There are plenty of examples of Arquillian testing with WAR deployments, but not for other deployments such as EJB-JAR or EAR. so I created some examples. these examples were tested against Arquillian 1.1.7.Final, using WildFly 8.2.0.Final as remote container. the entire project can be obtained from GitHub.
Testing against EJB-JAR deployment
Assume we have a simple EJB in a EJB-JAR project as follows:
@Stateless @LocalBean public class SomeEjb { public String hello(String name) { return "Hello, " + name; } }
Test class:
@RunWith(Arquillian.class) public class EjbJarIT { @Deployment public static Archive<?> createDeploymentPackage() { final Archive archive = ShrinkWrap.create(JavaArchive.class).addClass(SomeEjb.class); return archive; } @EJB private SomeEjb someEjb; @Test public void test() { Assert.assertEquals("Hello, Kyle", someEjb.hello("Kyle")); } }
The deployment will be a WAR through Arquillian’s automatic enrichment process while the method annotated as @Deployment
produced JavaArchive
.
Testing against EAR deployment
Assume we have a simple EAR project which depends on the preceding EJB-JAR project.
Test class:
@RunWith(Arquillian.class) public class EarIT { @Deployment public static Archive<?> createDeploymentPackage() throws IOException { final JavaArchive ejbJar = ShrinkWrap.create(JavaArchive.class, "ejb-jar.jar").addClass(SomeEjb.class); // Embedding war package which contains the test class is needed // So that Arquillian can invoke test class through its servlet test runner final WebArchive testWar = ShrinkWrap.create(WebArchive.class, "test.war").addClass(EarIT.class); final EnterpriseArchive ear = ShrinkWrap.create(EnterpriseArchive.class) .setApplicationXML("test-application.xml") .addAsModule(ejbJar) .addAsModule(testWar); return ear; } @EJB private SomeEjb someEjb; @Test public void test() { Assert.assertEquals("Hello, Kyle", someEjb.hello("Kyle")); } }
test-application.xml
which will be embed as application.xml
:
<application> <display-name>ear</display-name> <module> <ejb>ejb-jar.jar</ejb> </module> <module> <web> <web-uri>test.war</web-uri> <context-root>/test</context-root> </web> </module> </application>
Also I have an another example that uses the EAR which Maven has produced because creating EAR with ShrinkWrap would be annoying in some complex cases. the @Deployment
method will embed the test WAR into the EAR, and add a module
element into existing application.xml
before returning the archive to Arquillian runtime. the @Deployment
method would be something like this:
... @Deployment public static Archive<?> createDeploymentPackage() throws IOException { final String testWarName = "test.war"; final EnterpriseArchive ear = ShrinkWrap.createFromZipFile( EnterpriseArchive.class, new File("target/ear-1.0-SNAPSHOT.ear")); addTestWar(ear, EarFromZipFileIT.class, testWarName); ...
Tags: arquillian ear ejb
Arquillian Persistence Extension examples
TweetPosted on Wednesday Mar 18, 2015 at 05:47PM in Arquillian
The whole project can be obtained from GitHub. tested with WildFly 8.2.0.Final as remote container.
Implementation (test target)
Assume we have very simple 2 entities as follows:
@Entity public class Dept implements Serializable { @Id private Integer id; @Column(nullable = false) private String name; @OneToMany(mappedBy = "dept") private Collection<Employee> employees; ... @Entity public class Employee implements Serializable { @Id private Integer id; @Column(nullable = false) private String name; @JoinColumn(nullable = false) @ManyToOne private Dept dept; ...
Test target EJB:
@Stateless @LocalBean public class HumanResourcesBean { @PersistenceContext private EntityManager em; public void addEmployee(Employee employee, Integer deptId) { final Dept dept = em.find(Dept.class, deptId); dept.getEmployees().add(employee); employee.setDept(dept); em.persist(employee); } public void addDept(Dept dept, Employee employee) { Collection<Employee> employees = new ArrayList<>(); dept.setEmployees(employees); employees.add(employee); employee.setDept(dept); em.persist(dept); em.persist(employee); } }
addEmployee() testing
Test method of addEmployee():
@Test @UsingDataSet("input.xml") @ShouldMatchDataSet(value = "addEmployee-expected.xml", orderBy = "id") public void addEmployeeTest() throws Exception { Employee emp = new Employee(); emp.setId(2002); emp.setName("Todd"); humanResourcesBean.addEmployee(emp, 200); }
Initial entry data (input.xml):
<dataset> <Dept id="100" name="Sales"/> <Dept id="200" name="Finance"/> <Employee id="1000" name="Scott" dept_id="100"/> <Employee id="1001" name="Martin" dept_id="100"/> <Employee id="1002" name="Nick" dept_id="100"/> <Employee id="2000" name="Jordan" dept_id="200"/> <Employee id="2001" name="David" dept_id="200"/> </dataset>
Expected data (addEmployee-expected.xml):
<dataset> <Employee id="1000" name="Scott" dept_id="100"/> <Employee id="1001" name="Martin" dept_id="100"/> <Employee id="1002" name="Nick" dept_id="100"/> <Employee id="2000" name="Jordan" dept_id="200"/> <Employee id="2001" name="David" dept_id="200"/> <Employee id="2002" name="Todd" dept_id="200"/> <!-- Newly added --> </dataset>
addDept() testing
Test method of addDept():
@Test @UsingDataSet("input.xml") @ShouldMatchDataSet(value = "addDept-expected.xml", orderBy = "id") public void addDeptTest() throws Exception { Dept dept = new Dept(); dept.setId(300); dept.setName("Engineering"); Employee emp = new Employee(); emp.setId(3000); emp.setName("Carl"); humanResourcesBean.addDept(dept, emp); }
Initial entry data (input.xml) is the same to previous testing.
Expected data (addDept-expected.xml):
<dataset> <Dept id="100" name="Sales"/> <Dept id="200" name="Finance"/> <Dept id="300" name="Engineering"/> <!-- Newly added --> <Employee id="1000" name="Scott" dept_id="100"/> <Employee id="1001" name="Martin" dept_id="100"/> <Employee id="1002" name="Nick" dept_id="100"/> <Employee id="2000" name="Jordan" dept_id="200"/> <Employee id="2001" name="David" dept_id="200"/> <Employee id="3000" name="Carl" dept_id="300"/> <!-- Newly added --> </dataset>
It works well with multiple tables.
addDept() testing with DBUnit
Sometimes use of DBUnit directly is useful for complex assertion. in such case you need to care following conditions:
-
If you use JPA, force EntityManager to execute DMLs via invoking
em.flush()
before assertion -
Include test data to the Arquillian’s application archive so that DBUnit can load these data on the server side
The XML can be included via addAsResource()
method as follows:
@Deployment public static Archive<?> createDeploymentPackage() { final WebArchive webArchive = ShrinkWrap.create(WebArchive.class, "test.war") .addPackage(Dept.class.getPackage()) .addClass(HumanResourcesBean.class) .addAsResource("datasets/addDept-expected.xml") // to be loaded by DBUnit on the server side .addAsResource("test-persistence.xml", "META-INF/persistence.xml"); // System.out.println(webArchive.toString(true)); return webArchive; }
The test method of addDept() and related convenient methods:
@Test @UsingDataSet("input.xml") public void addDeptTestWithDbUnit() throws Exception { Dept dept = new Dept(); dept.setId(300); dept.setName("Engineering"); Employee emp = new Employee(); emp.setId(3000); emp.setName("Carl"); humanResourcesBean.addDept(dept, emp); em.flush(); // force JPA to execute DMLs before assertion final IDataSet expectedDataSet = getDataSet("/datasets/addDept-expected.xml"); assertTable(expectedDataSet.getTable("Dept"), "select * from dept order by id"); assertTable(expectedDataSet.getTable("Employee"), "select * from employee order by id"); } private static IDataSet getDataSet(String path) throws DataSetException { return new FlatXmlDataSetBuilder().build(HumanResourcesBeanIT.class.getResource(path)); } private void assertTable(ITable expectedTable, String sql) throws SQLException, DatabaseUnitException { try (Connection cn = ds.getConnection()) { IDatabaseConnection icn = null; try { icn = new DatabaseConnection(cn); final ITable queryTable = icn.createQueryTable(expectedTable.getTableMetaData().getTableName(), sql); Assertion.assertEquals(expectedTable, queryTable); } finally { if (icn != null) { icn.close(); } } } }
Testing a JBatch job using Arquillian on remote WildFly
TweetPosted on Thursday Mar 05, 2015 at 05:14PM in JBatch
I pushed entire project to https://github.com/lbtc-xxx/arquillian-jbatch .
While I prefer remote EJB way like my previous posting for JBatch testing, it works well for simple project. but little slower than remote EJB on my environment.
Tags: arquillian jbatch wildfly