gwt-rpc + appengine + persistence using restlet throws exception - gwt

I was trying to rebuild the Restlet sample Application for GWT + GAE ( http://wiki.restlet.org/docs_2.1/13-restlet/21-restlet/318-restlet/303-restlet.html ) .
I changed it a bit, since I am planning something diffrent but I thought it would be a good start.
It was going okish until now. The "Put" was coming through to app engine but when i tried to persist the Objects using JPA i get the following Exception:
Caused by: org.datanucleus.exceptions.ClassNotResolvedException: Class "de.fr1zle.shoplist.web.gae.client.ShoppingListRessourceProxy" was not found in the CLASSPATH. Please check your specification and your CLASSPATH.
at org.datanucleus.JDOClassLoaderResolver.classForName(JDOClassLoaderResolver.java:250)
at org.datanucleus.JDOClassLoaderResolver.classForName(JDOClassLoaderResolver.java:415)
at org.datanucleus.metadata.MetaDataManager.loadPersistenceUnit(MetaDataManager.java:767)
... 79 more
As you can see, datanucleus somehow tries to access the GWT Proxy class when loading the info from the persistence.xml.
I use the following in my ServerRessource:
#Put
public void putShoppingList(ShoppingList shoppingList) {
ShoppingListDOA shoppingListDOA = new ShoppingListDOA(shoppingList);
EntityManagerFactory emf = Persistence
.createEntityManagerFactory("transactions-optional");
try {
EntityManager entityManager = emf.createEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.persist(shoppingListDOA);
entityManager.flush();
transaction.commit();
entityManager.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (emf != null)
emf.close();
}
}
I somehow have the feeling that DataNucleus enhances the Proxy Class, too although I changed the properites for it to not do so.
Using: GAE 1.4.2 (tried 1.4.3, too) , GWT 2.2 and Restlet 2.1m3
Am I missing a point here? Your help is appricated :-)
Thanks in advance!
fr1zle

Related

How to execute JPA Entity manager operations inside Quarkus-Kafka consumer method

Dears, I want to update my domain entities according to message being received by Kafka topic. I am using Quarkus latest and Smallrye reactive messaging with Kafka. Pub-sub model is working fine with me, but in consumer method I am unable to update my entities using entityManager or HibernatePanache.
Whenever I try to use entityManager code inside consumer message, an exception is being thrown and handled silently. Here is my consumer code :
#Transactional
#Incoming("new-payment")
public CompletionStage<Void> updateTotalBuyers(String paymentEvent) {
return CompletableFuture.runAsync(() -> {
PaymentEvent event = jsonb.fromJson(paymentEvent, PaymentEvent.class);
TypedQuery<Book> query = em.createQuery("SELECT b FROM Book b where b.isbn=:isbn", Book.class);
query.setParameter("isbn", event.getIsbn());
Book book = query.getSingleResult();
book.setTotalBuyers(book.getTotalBuyers() + 1);
em.merge(book);
});
}
If anyone has a working code snippet for my problem it would be great. Also, how can I print that silent exception for further debugging ?
Update :
I surrounded the code with try/catch block and the below exception is being thrown :
javax.enterprise.context.ContextNotActiveException: interface javax.enterprise.context.RequestScoped
at io.quarkus.hibernate.orm.runtime.RequestScopedEntityManagerHolder_ClientProxy.arc$delegate(RequestScopedEntityManagerHolder_ClientProxy.zig:83)
at io.quarkus.hibernate.orm.runtime.RequestScopedEntityManagerHolder_ClientProxy.getOrCreateEntityManager(RequestScopedEntityManagerHolder_ClientProxy.zig:191)
at io.quarkus.hibernate.orm.runtime.entitymanager.TransactionScopedEntityManager.getEntityManager(TransactionScopedEntityManager.java:78)
at io.quarkus.hibernate.orm.runtime.entitymanager.TransactionScopedEntityManager.createQuery(TransactionScopedEntityManager.java:317)
at io.quarkus.hibernate.orm.runtime.entitymanager.ForwardingEntityManager.createQuery(ForwardingEntityManager.java:142)
at io.quarkus.hibernate.orm.panache.runtime.JpaOperations.find(JpaOperations.java:208)
at io.quarkus.hibernate.orm.panache.runtime.JpaOperations.find(JpaOperations.java:200)
at org.ibra.ebs.book.model.Book.find(Book.java)
at org.ibra.ebs.book.service.BookService.lambda$updateTotalBuyers$0(BookService.java:106)
at java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1626)
at java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1618)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
I added annotation #ActivateRequestContext on both class and method with no luck.
Update : I tried to elevate context-propagation using
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-reactive-streams-operators</artifactId>
</dependency>
Also same exception is being thrown with some context-propagation classes (which means it is being activated).
Regards.
Finally it worked :), Yes the answer was around context-propagation and here is what I did :
#Transactional
#Incoming("new-payment")
public CompletionStage<?> updateTotalBuyers(Message<String> paymentEvent) {
//TODO: move to CDI producer
ManagedExecutor executor = ManagedExecutor.builder()
.maxAsync(5)
.propagated(ThreadContext.CDI,
ThreadContext.TRANSACTION)
.build();
//TODO: move to CDI producer
ThreadContext threadContext = ThreadContext.builder()
.propagated(ThreadContext.CDI,
ThreadContext.TRANSACTION)
.build();
return executor.runAsync(threadContext.contextualRunnable(() -> {
try {
log.info("Into update total buyers");
PaymentEvent event = jsonb.fromJson(paymentEvent.getPayload(), PaymentEvent.class);
Book book = Book.find("isbn", event.getIsbn()).singleResult();
book.totalBuyers++;
book.persist();
log.info("Total books {}", book.totalBuyers);
} catch(Exception e) {
log.error("Something wrong happened !!!", e);
} finally {
paymentEvent.ack();
}
}));
}
I will try to make it more standard now.
Add #ApplicationScoped and #ActivateRequestContext both these annotations on the class and #Transactional annotation on the updateTotalBuyers method.
Cheers!
I had simillar issue using Quarkus + a single thread executor to collect AWS SQS messages.
Initial - wrong approach:
private final ExecutorService scheduler = Executors.newSingleThreadExecutor();
scheduler.submit(/*MyRunnable*/)
Solution: Injecting ManagedExecutor which is provided by quarkus:
#Inject
ManagedExecutor managedExecutor;
managedExecutor.submit(/*MyRunnable*/);
In your particular case you can replace following code with injecting ManagedExecutor.
ManagedExecutor executor = ManagedExecutor.builder()
.maxAsync(5)
.propagated(ThreadContext.CDI,
ThreadContext.TRANSACTION)
.build();
//TODO: move to CDI producer
ThreadContext threadContext = ThreadContext.builder()
.propagated(ThreadContext.CDI,
ThreadContext.TRANSACTION)
.build();

How to configure JaVers with OpenJPA in a Spring boot project

I'm trying to set up auditing for my project which is currently a Spring boot with Open JPA. Require help/pointers on configuring Javers for Open JPA.
I have tried configuring the project with SpringBoot annotations provided by Javers. It gives me following error -
org.apache.openjpa.persistence.EntityManagerImpl cannot be cast to org.hibernate.Session
#Bean
#Transactional
public DialectName javersSqlDialectName() {
Session session = (Session)entityManager.getDelegate();//.getSession();
Dialect hibernateDialect=null;
try {
Object dialect =
org.apache.commons.beanutils.PropertyUtils.getProperty(session.getSessionFactory(), "dialect");
hibernateDialect = (Dialect) dialect;
}
catch(Exception ex) {
System.out.println("Serious error");
}
return dialectMapper.map(hibernateDialect);
}

No #ResponseBody returned from #ExceptionHandler in Spring boot app deployed in Tomcat

I have a Spring Boot web app that runs just fine from STS but shows different behavior when running in Tomcat from a WAR file.
I use Thymeleaf to handle all my web pages but I have a couple pages that are using jQuery to send async calls and make user experience more dynamic.
Anyway, I have a Controller method that calls a service method which may throw a RuntimeException which I handle this way :
#ExceptionHandler(MyRuntimeException.class)
#ResponseStatus(HttpStatus.BAD_REQUEST)
public #ResponseBody String handleMyRuntimeException(MyRuntimeException exception) {
return "Oops an error happened : " + exception.getMessage();
}
In JS, I use the response body I return above to display a message on screen.
That works perfectly fine when running my app in STS but once I switch to deploy it in Tomcat the ErrorPageFilter gets invoked and in doFilter() it does:
if (status >= 400) {
handleErrorStatus(request, response, status, wrapped.getMessage());
response.flushBuffer();
}
In handleErrorStatus() it creates an error with the status and associated message but doesn't return my response.
I haven't figured out how to solve this and I'd really appreciate if anybody could help.
Thanks!
I went around this issue (I would think that is a Spring Boot issue) by doing the following.
Separate Rest and Mvc controllers
See my question here : Spring MVC: Get i18n message for reason in #RequestStatus on a #ExceptionHandler
Inject Jackson converter and write response myself :
#ControllerAdvice(annotations = RestController.class)
#Priority(1)
#ResponseBody
public class RestControllerAdvice {
#Autowired
private MappingJackson2HttpMessageConverter jacksonMessageConverter;
#ExceptionHandler(RuntimeException.class)
#ResponseStatus(value = HttpStatus.BAD_REQUEST)
public void handleRuntimeException(HttpServletRequest request, HttpServletResponse response, RuntimeException exception) {
try {
jacksonMessageConverter.write(new MyRestResult(translateMessage(exception)), MediaType.APPLICATION_JSON, new ServletServerHttpResponse(response));
response.flushBuffer(); // Flush to commit the response
} catch (IOException e) {
e.printStackTrace();
}
}
}

Issues with Restful Jersey and JSON

I have a strange issue and didn't find any information about it at all.
Having a simple POJO like (simplified..)
#XmlRootElement
public class Bill {
List<Position> positions
.. getter/setter
}
#XmlRootElement
public class Position {
.. some simple properties with getters/setters
}
I am unable to call a RESTful Service using instances of these classes. I'm getting real weird errors I don't really understand.
org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of java.util.List out of START_OBJECT token
The funny thing is, when I just test serialization/deserialization using Jackson Object mapper directly, it works as expected!
ObjectMapper mapper = new ...
mapper.writeValue(stringWriter, bill);
mapper.readValue(stringWriter.toString(), Bill.class);
This works perfectly. So I guess the POJO itself is OK and Jackson is able to handle the JSON-String.
Calling the RESTful service using the same Bill instance fails with the error mentioned above. I see it is using Jackson as well, here is part of stack trace:
at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:160)
at org.codehaus.jackson.map.deser.StdDeserializationContext.mappingException(StdDeserializationContext.java:198)
at org.codehaus.jackson.map.deser.CollectionDeserializer.deserialize(CollectionDeserializer.java:103)
at org.codehaus.jackson.map.deser.CollectionDeserializer.deserialize(CollectionDeserializer.java:93)
at org.codehaus.jackson.map.deser.CollectionDeserializer.deserialize(CollectionDeserializer.java:25)
at org.codehaus.jackson.map.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:230)
And here is how the RESTful Application is configured:
#javax.ws.rs.ApplicationPath("rest")
public class ApplicationConfig extends Application {
public Set<Class<?>> getClasses() {
return getRestResourceClasses();
}
/**
* Do not modify this method. It is automatically generated by NetBeans REST support.
*/
private Set<Class<?>> getRestResourceClasses() {
Set<Class<?>> resources = new java.util.HashSet<Class<?>>();
resources.add(rest.RestAPI.class);
// following code can be used to customize Jersey 1.x JSON provider:
try {
Class jacksonProvider = Class.forName("org.codehaus.jackson.jaxrs.JacksonJsonProvider");
resources.add(jacksonProvider);
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(getClass().getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
return resources;
}
}
Do you have any idea what I'm missing?
I generated the service and the client with NetBeans. Oh and it works when I use XML instead of JSON.
Any help would be very much appreciated.
I'm sorry but after hours of testing and debugging I finally found the cause of the problem.
Still I would be very interested why this is?
Commenting out the following code did the trick:
// following code can be used to customize Jersey 1.x JSON provider:
try {
Class jacksonProvider = Class.forName("org.codehaus.jackson.jaxrs.JacksonJsonProvider");
resources.add(jacksonProvider);
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(getClass().getName()).log(java.util.logging.Level.SEVERE, null, ex);
}

How to propagate a client-side UserTransaction into a stateless session bean using BMT

This scenario using CMT is working:
Stateless session bean with CMT, one method annotated with #TransactionAttribute(TransactionAttributeType.MANDATORY). Within this method, a record is written into a RDBMS using an XA data source and plain JDBC.
The stand-alone client (separate JVM, command-line Java application) is getting a UserTransaction from the application server (by JNDI lookup),
starts the transaction, and calls the EJB.
If the client commits the UserTransaction, the record is written into the database.
If the client rollbacks the UserTransaction, the record is not written into the database.
In the PostgreSql log files, one can see the prepared transaction with BEGIN, and COMMIT or ROLLBACK
If the client does not start a transaction before calling the EJB, a javax.ejb.EJBTransactionRequiredException is thrown (as expected, TransactionAttributeType.MANDATORY).
Now I switch from CMT to BMT
Again, if the client does not start a transaction before calling the EJB, a javax.ejb.EJBTransactionRequiredException is thrown (as expected, TransactionAttributeType.MANDATORY).
If I call sessionContext.getUserTransaction().getStatus(), it always reports Status.STATUS_NO_TRANSACTION.
The record is always written into the database, if the client calls commit or rollback.
In the PostgreSql log files, there are no prepared transactions, just plain insert commands.
The source of the EJB:
#Remote(DemoIfc.class)
#Stateless(name = "DemoBmt")
#TransactionManagement(TransactionManagementType.BEAN)
public class DemoBmt implements DemoIfc {
#Resource
private SessionContext sessionContext;
#TransactionAttribute(TransactionAttributeType.MANDATORY)
public String ping(final String s) throws SystemException {
try {
System.out.println("TX: status: "
+ this.sessionContext.getUserTransaction().getStatus());
} catch (Exception e) {
System.out.println("TX: status: " + e.getMessage());
}
try {
writeIntoDb();
if (s.startsWith("crash")) {
throw new SystemException("Simulated crash");
}
return s.toUpperCase();
} catch (NamingException e) {
throw new SystemException(e.getMessage());
} catch (SQLException e) {
throw new SystemException(e.getMessage());
}
}
}
The client's source:
final UserTransaction ut = (UserTransaction) initialContext
.lookup("UserTransaction");
try {
ut.begin();
System.out.println(demo.ping("crash: DemoBmt with UT"));
ut.commit();
} catch (Exception ex) {
System.out.println("Expected rollback");
ut.rollback();
}
I am using JBoss 6.0.0 final.
How can I properly propagate the client-side UserTransaction into the EJB with BMT?
BMT beans cannot participate in an existing transaction
From EJB 3.1 spec.:
13.6.1 Bean-Managed Transaction Demarcation
The container must manage client invocations to an enterprise bean
instance with bean-managed transaction demarcation as follows. When a
client invokes a business method via one of the enterprise bean’s
client views, the container suspends any transaction that may be
associated with the client request....