Unable to catch javax.ejb.EJBTransactionRolledbackException in my ejb - jboss7.x

I am using JBoss 7.1.1 for deployment, and junit 4.11 + arquillian 1.1.2 for testing.
I have following method in my #Stateless EJB.
public MyEntity create(MyEntity entity) {
try {
getEntityManager().persist(entity);
} catch (Throwable e) {
System.out.println("Caught! " + e.getClass().getName());
}
return entity;
}
The entity MyEntity has field description annotated as follows:
#Size(min = 1, max = 256)
private String description;
If I pass an entity to create() which does not satisfy above constraint, I expect to see the message, but I do not see it. Instead, I get javax.ejb.EJBTransactionRolledbackException, somehow by-passing the try-catch block.
Any ideas why?

Because the exception javax.ejb.EJBTransactionRolledbackException is generated after the create() method. What was I thinking!

Related

Spring data rest i18n domain exceptions

I have a sdr project where I do some basic validation in entity setters and throw a domain exception if model is invalid. I can not get a message source inside the exception so that I can localize the business exception message. Custom exception class I have tried is:
#ResponseStatus(org.springframework.http.HttpStatus.CONFLICT)
public class DoublePriceException extends Exception {
#Autowired
static ReloadableResourceBundleMessageSource messageSource;
private static final long serialVersionUID = 1L;
public DoublePriceException(OrderItem orderItem) {
super(String.format(
messageSource.getMessage("exception.doublePricedItem", null, LocaleContextHolder.getLocale()),
orderItem.name));
}
}
And how I try to throw this mofo is:
public void setPrices(List<Price> prices) throws DoublePriceException {
for (Price price : prices) {
List<Price> itemsPrices = prices.stream().filter(it -> price.item.equals(it.item)).collect(Collectors.toList());
if(itemsPrices.size() > 1)
throw new DoublePriceException(itemsPrices.get(0).item);
}
this.prices = prices;
}
messageSource is always null. Is what I am trying not achievable?
DoublePriceException is obviously not a Spring managed Bean so that is not going to work.
You can register a Spring ControllerAdvice in your application that handles the exception and generates a suitable response.
/**
* Spring MVC #link {#link ControllerAdvice} which
* is applied to all Controllers and which will handle
* conversion of exceptions to an appropriate JSON response.
*/
#ControllerAdvice
public class ErrorHandlingAdvice
{
/**
* Handles a #DoublePriceException
*
* #param ex the DoublePriceException
*
* #return JSON String with the error details.
*/
#ExceptionHandler(DoublePriceException.class)
#ResponseStatus(HttpStatus.BAD_REQUEST)
#ResponseBody
public Object processValidationError(DoublePriceException ex)
{
//return suitable representation of the error message
//e.g. return Collections.singletonMap("error", "my error message");
}
}
Placing the above in a package scanned by the Spring framework should be enough to have it detected and applied.
Best I could come up with is catching the HttpMessageNotReadableException and calling getMostSpecificCause() like the following:
#RestControllerAdvice
public class ExceptionHandlingAdvice {
#Autowired
private MessageSource messageSource;
#ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseEntity<Object> onException(HttpMessageNotReadableException ex, WebRequest request) {
Locale locale = request.getLocale();
Throwable cause = ex.getMostSpecificCause();
String message = cause.getMessage();
if (cause instanceof MultiplePriceException) {
message = messageSource.getMessage("exception.multiple.price",
new Object[] { ((MultiplePriceException) cause).orderItem.name }, locale);
}
return new ResponseEntity(Collections.singletonMap("error", message), new HttpHeaders(),
HttpStatus.BAD_REQUEST);
}
}

Test EntityManager using JUnit Mockito

I am using Junit with Mockito. I want to test EntityManager, i am getting java.lang.NullPointerException
The below is what i have tried,
main class method is,
#Override
public ReplicationPerspective buildReplicationPerspective(final String replicationDomain)
throws ReplicationStateException {
try {
System.out.println("Test");
final ReplicationPerspective localPerspective =
this.replicationPerspectiveQuery.findReplicationPerspective(replicationDomain);
List<String> ncdKeys = new ArrayList<String>();
for (NodeChangeDelta ncd : this.nodeChangeDeltaQuery.findByChangeStatus(
replicationDomain, ChangeStatus.PENDING)) {
ncdKeys.add(ncd.getKey());
}
localPerspective.setPendingNodeChangeDeltaKeys(ncdKeys);
LOGGER.debug("Local perspective is {} ", localPerspective);
return localPerspective;
}
catch (Throwable t) {
LOGGER.error("Failed to build replication perspective", t);
throw new ReplicationStateException(t);
}
}
replicationPerspectiveQuery Bean file method is,
#PersistenceContext
private EntityManager em;
#Override
public ReplicationPerspective findReplicationPerspective(final String replicationDomain) {
Validate.notBlank(replicationDomain);
ReplicationPerspective perspective =
this.em.find(ReplicationPerspective.class, replicationDomain);
if (perspective == null) {
this.replicationPerspectiveInitializer
.initializeReplicationPerspective(replicationDomain);
perspective = this.em.find(ReplicationPerspective.class, replicationDomain);
}
return perspective;
}
And my test case method is,
#Test
public void testBuildReplicationPerspective() throws ReplicationStateException {
this.replicationStateServiceBean =
new ReplicationStateServiceBean(null, null, null, null,
new ReplicationPerspectiveQueryBean(), null, null);
this.em = Mockito.mock(EntityManager.class);
Mockito.when(this.em.find(ReplicationPerspective.class, REPLICATION_DOMAIN))
.thenReturn(null);
this.replicationStateServiceBean.buildReplicationPerspective(REPLICATION_DOMAIN);
}
I am getting NPE error in replicationPerspectiveQuery Bean file at the below line
ReplicationPerspective perspective =
this.em.find(ReplicationPerspective.class, replicationDomain);
How to test entity manager, help me to solve.
I have also tried to mock like below but didn't work,
Mockito.when(this.replicationPerspectiveQuery.findReplicationPerspective(REPLICATION_DOMAIN)).thenReturn(null);
You are lacking the instructions to have Mockito do the actual injection. Right now you have the EntityManager mocked, but it is not used anywhere.
You can declare your bean as a member of the testclass and annotate it with #InjectMocks to have Mockito do the wiring for you.
See also the documentation for more info and examples.

How to generalize a JMockit test using Spring autowiring

So I would like to use a generic test for a few different Dao methods. Inside the Dao, I implemented the save functionality to be Entity independent, so I figured it would be best to make the tests Entity independent as well. Currently I have the following for one of my jmockit tests that is autowired with spring.
#Injectable
public EntityManager em;
#Tested
SyncClaimDao syncClaimDao = new SyncClaimDaoImpl();
#Before
public void setUp() {
Deencapsulation.setField(syncClaimDao, "em", em);
}
private void testSaveEntity (Class T) {
// Existing claim happy path
new Expectations() {
{
em.contains(any); result = true;
em.merge(any);
}
};
if (T.isInstance(SyncClaimEntity.class)) {
Assert.assertTrue(syncClaimDao.saveClaim(new SyncClaimEntity()));
} else if (...) {...}
}
#Test
public void testSaveClaim() {
testSaveEntity(SyncClaimEntity.class);
}
SyncClaimDaoImpl
#Override
public boolean saveClaim(SyncClaimEntity claim) {
return saveEntity(claim);
}
private boolean saveEntity(Object entity) {
boolean isPersisted = false;
try {
isPersisted = em.contains(entity);
if (isPersisted) {
em.merge(entity);
} else {
em.persist(entity);
em.flush();
isPersisted = true;
}
logger.debug("Persisting " + entity.getClass().getSimpleName() + ": " + entity.toString());
}
catch (NullPointerException ex) {
...
}
catch (IllegalArgumentException ex) {
...
}
return isPersisted;
}
When I run the tests I am seeing the following errors:
mockit.internal.MissingInvocation: Missing invocation of:
javax.persistence.EntityManager#contains(Object)
with arguments: any Object
on mock instance: javax.persistence.$Impl_EntityManager#44022631
at at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
... 4 more
Caused by: Missing invocation
at [redacted].dal.dao.SyncClaimDaoImplTest$1.<init>(SyncClaimDaoImplTest.java:48)
at [redacted].dal.dao.SyncClaimDaoImplTest.testSaveEntity(SyncClaimDaoImplTest.java:46)
at [redacted].dal.dao.SyncClaimDaoImplTest.testSaveClaim(SyncClaimDaoImplTest.java:67)
... 10 more
Now if I just move the Expectations block into the #Test method like so:
#Test
public void testSaveClaim() {
new Expectations() {
{
em.contains(any); result = true;
em.merge(any);
}
};
Assert.assertTrue(syncClaimDao.saveClaim(new SyncClaimEntity()));
I get a successful test run as should be. I'm thinking that the spring autowiring for the Test method is not properly scoping my Expectations. That's why I'm seeing the missing invocation errors.
Does anyone have any ideas on how to generalize my Expectations so I can create simpler tests for generalized methods?
I see the mistake now: T.isInstance(SyncClaimEntity.class). The Class#isInstance(Object) method is supposed to be called with an instance of the class, not with the class itself; so, it's always returning false because SyncClaimEntity.class is obviously not an instance of SyncClaimEntity.

Spring JDBC and Java 8 - JDBCTemplate: retrieving SQL statement and parameters for debugging

I am using Spring JDBC and some nice Java 8 lambda-syntax to execute queries with the JDBCTemplate.
The reason for choosing Springs JDBCTemplate, is the implicit resource-handling that Spring-jdbc offers (I do NOT want a ORM framework for my simple usecase's).
My problem is that I want to debug the whole SQL statements with their parameters. Spring prints the SQL by default but not the parameters. Therefor I have subclassed the JDBCTemplate and overridden a query-method.
An example usage of the JDBCTemplate:
public List<Product> getProductsByModel(String modelName) {
List<Product> productList = jdbcTemplate.query(
"select * from product p, productmodel m " +
"where p.modelId = m.id " +
"and m.name = ?",
(rs, rowNum) -> new Product(
rs.getInt("id"),
rs.getString("stc_number"),
rs.getString("version"),
getModelById(rs.getInt("modelId")), // method not shown
rs.getString("displayName"),
rs.getString("imageUrl")
),
modelName);
return productList;
}
To get hold of the parameters I have, as mentioned, overridden the JDBCTemplate class. By doing a cast and using reflection I get the Object[] field with the parameters from an instance of ArgumentPreparedStatementSetter.
I suspect this implementation could potentially be dangerous, as the actual implementation of the PreparedStatementSetter may not always be ArgumentPreparedStatementSetter (Yes I should do an instanceOf check). Also, the reflection code may not be as elegant, but that is besides the point now though :).
Here's my custom implementation:
public class CustomJdbcTemplate extends JdbcTemplate {
private static final Logger log = LoggerFactory.getLogger(CustomJdbcTemplate.class);
public CustomJdbcTemplate(DataSource dataSource) {
super(dataSource);
}
public <T> T query(PreparedStatementCreator psc, final PreparedStatementSetter pss, final ResultSetExtractor<T> rse)
throws DataAccessException {
if(log.isDebugEnabled()) {
ArgumentPreparedStatementSetter aps = (ArgumentPreparedStatementSetter) pss;
try {
Field args = aps.getClass().getDeclaredField("args");
args.setAccessible(true);
Object[] parameters = (Object[]) args.get(aps);
log.debug("Parameters for SQL query: " + Arrays.toString(parameters));
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new GenericException(e.toString(), e);
}
}
return super.query(psc, pss, rse);
}
}
So, when I execute the log.debug(...) statement I would also like to have the original SQL query logged (same line). Has anyone done something similar or are there any better suggestions as to how this can be achieved?
I do quite a few queries using this CustomJDBCTemplate and all my tests run, so I think it may be an acceptable solution of for most debug purposes.
Kind regards,
Thomas
I found a way to get the SQL-statement, so I will answer my own question :)
The PreparedStatementCreator has the following implementation:
private static class SimplePreparedStatementCreator implements PreparedStatementCreator, SqlProvider
So the SqlProvider has a getSql() method which does exactly what I need.
Posting the "improved" CustomJdbcTemplate class if anyone ever should need to do the same :)
public class CustomJdbcTemplate extends JdbcTemplate {
private static final Logger log = LoggerFactory.getLogger(CustomJdbcTemplate.class);
public CustomJdbcTemplate(DataSource dataSource) {
super(dataSource);
}
public <T> T query(PreparedStatementCreator psc, final PreparedStatementSetter pss, final ResultSetExtractor<T> rse)
throws DataAccessException {
if(log.isDebugEnabled()) {
if(pss instanceof ArgumentPreparedStatementSetter) {
ArgumentPreparedStatementSetter aps = (ArgumentPreparedStatementSetter) pss;
try {
Field args = aps.getClass().getDeclaredField("args");
args.setAccessible(true);
Object[] parameters = (Object[]) args.get(aps);
log.debug("SQL query: [{}]\tParams: {} ", getSql(psc), Arrays.toString(parameters));
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new GenericException(e.toString(), e);
}
}
}
return super.query(psc, pss, rse);
}
private static String getSql(Object sqlProvider) { // this code is also found in the JDBCTemplate class
if (sqlProvider instanceof SqlProvider) {
return ((SqlProvider) sqlProvider).getSql();
}
else {
return null;
}
}
}

spring 3 AOP anotated advises

Trying to figure out how to Proxy my beans with AOP advices in annotated way.
I have a simple class
#Service
public class RestSampleDao {
#MonitorTimer
public Collection<User> getUsers(){
....
return users;
}
}
i have created custom annotation for monitoring execution time
#Target({ ElementType.METHOD, ElementType.TYPE })
#Retention(RetentionPolicy.RUNTIME)
public #interface MonitorTimer {
}
and advise to do some fake monitoring
public class MonitorTimerAdvice implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable{
try {
long start = System.currentTimeMillis();
Object retVal = invocation.proceed();
long end = System.currentTimeMillis();
long differenceMs = end - start;
System.out.println("\ncall took " + differenceMs + " ms ");
return retVal;
} catch(Throwable t){
System.out.println("\nerror occured");
throw t;
}
}
}
now i can use it if i manually proxy the instance of dao like this
AnnotationMatchingPointcut pc = new AnnotationMatchingPointcut(null, MonitorTimer.class);
Advisor advisor = new DefaultPointcutAdvisor(pc, new MonitorTimerAdvice());
ProxyFactory pf = new ProxyFactory();
pf.setTarget( sampleDao );
pf.addAdvisor(advisor);
RestSampleDao proxy = (RestSampleDao) pf.getProxy();
mv.addObject( proxy.getUsers() );
but how do i set it up in Spring so that my custom annotated methods would get proxied by this interceptor automatically? i would like to inject proxied samepleDao instead of real one. Can that be done without xml configurations?
i think should be possible to just annotate methods i want to intercept and spring DI would proxy what is necessary.
or do i have to use aspectj for that? would prefere simplest solution :- )
thanks a lot for help!
You haven't to use AspectJ, but you can use AspectJ annotations with Spring (see 7.2 #AspectJ support):
#Aspect
public class AroundExample {
#Around("#annotation(...)")
public Object invoke(ProceedingJoinPoint pjp) throws Throwable {
...
}
}