Playframework : The JPA context is not initialized. JPA Entity Manager automatically - jpa

I keep receiving this error although my Bootstrap class looks like this:
#OnApplicationStart
public class Bootstrap extends Job {
#Override
public void doJob() {
...
user.save();
}
}
My User class looks like this:
#Entity
public class User extends Model {
...
The #Entity annotation is javax.persistence.Entity. The Model is play.db.jpa.Model.
I'm not doing anything with threads. How do I initialize the JPA context in Play!

Check that your jpa settings are correct in application.conf Use db=mem for testing

Related

CDI context in Kafka de-/serializer in Quarkus app

I have a Quarkus project with Smallrye reactive messaging based on Kafka. Since I want to work with a "complex pojo" I need a custom de-/serializer.
I'd like to make those two classes CDI beans so I can inject and use my custom logger, which is a CDI bean. Is there a way to achieve this?
Right now my injected logger object is simply null:
import org.apache.kafka.common.serialization.Serializer;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
#ApplicationScoped
public class MySerializer implements Serializer<MyDto>
{
#Inject MyLogger logger;
#Override public byte[] serialize(String topicName, MyDto myDto)
{
// this causes a java.lang.NullPointerException
logger.info("serializing");
...
}
}
As far as I know, you can only register a class name with kafka, and it will create that class internally, ie. without using CDI.
Possible workaround: make the registered object a thin wrapper around the CDI-bean, and delegate the work to the bean:
public class MySerializer implements Serializer<MyDto> {
private MySerializerCdi delegate;
public MySerializer() {
delegate = CDI.current().select(MySerializerCdi.class).get();
}
#Override public byte[] serialize(String topicName, MyDto myDto) {
return delegate.serialize(topicName, myDto);
}
...
}
... and rename your original CDI class accordingly.

Spring Data Jpa Query methods are not invoking the repositoryBaseClass

I have a repository base class as defined below.
#NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {
}
public class BaseRepositoryImpl<T, ID extends Serializable>
extends SimpleJpaRepository<T, ID> implements BaseRepository<T, ID> {
public BaseRepositoryImpl(JpaEntityInformation<T, ?> entityInfo, EntityManager entityMgr) {
super(entityInfo, entityMgr);
}
// ...
}
#Configuration
#EnableJpaRepositories(basePackages = "org.example",
repositoryBaseClass = BaseRepositoryImpl.class)
public class BaseConfig {
// additional JPA Configuration
}
I have defined a business repository class and a query method as seen below.
#Repository
public interface CarRepository extends BaseRepository<Car, Long> {
#Query("SELECT c FROM Car c Where active = 1")
List<Car> findAllActiveCars();
}
I have a test class which invokes the findAllActiveCars(). I am getting the expected results. But, that query method is not invoking any of the methods in BaseRepository class. How to customize the return values of the query methods?
You didn't show the methods that you did implement, so it is not clear why they don't get called, but since you want to decrypt entity fields, consider listening to JPAs entity lifecycle events. #PostLoad should be able to do the trick.
https://docs.jboss.org/hibernate/core/4.0/hem/en-US/html/listeners.html

Mixing Spring Data Envers and QueryDSL

I'm using a global custom repository in my project which extends QueryDslJpaRepository:
public class CustomPagingAndSortingRepositoryImpl<T, ID extends Serializable> extends QueryDslJpaRepository<T, ID>
implements CustomPagingAndSortingRepository<T, ID> {
And the interface:
public interface CustomPagingAndSortingRepository<T, ID extends Serializable>
extends JpaRepository<T, ID>, QueryDslPredicateExecutor<T> {
And then on my configuration I annotate it with:
#EnableJpaRepositories(repositoryBaseClass = CustomPagingAndSortingRepositoryImpl.class)
All is working fine, but now I was trying to add auditing support to my entities by using spring-data-envers and according to the docs I should use a specific repository factory bean class :
#EnableJpaRepositories(repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class, repositoryBaseClass = CustomPagingAndSortingRepositoryImpl.class)
Now obviously if I do this things won't work because my repositories will now be created through the EnversRevisionRepositoryFactoryBean class and will no longer be of CustomPagingAndSortingRepositoryImpl type.
How can I support something like this? I'm not seeing how since my custom repository need to extend from QueryDslJpaRepository already.
I think the relevant part for you is this method of EnversRevisionRepositoryFactoryBean:
#Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
return EnversRevisionRepositoryImpl.class;
}
Here you really want your CustomPagingAndSortingRepositoryImpl returned. So I would try the following:
extend EnversRevisionRepositoryFactoryBean and overwrite getRepositoryBaseClass to return your CustomPagingAndSortingRepositoryImpl.
Make CustomPagingAndSortingRepositoryImpl extend EnversRevisionRepositoryImpl.

Play Framework PathBindable with JPA Transactionnal context incompatible?

I'm trying to implement a simple PathBindable Interface for my customEntity, thing is I'm working with JPA, and when I try to load the bindable url, I get this JPA error :
[info] application - onBadRequest: POST /path/customEntity/2554003 - No EntityManager bound to this thread. Try to annotate your action method with #play.db.jpa.Transactional
Of course the action method bound to this route is annotated with #Transaction.
I've also tried to add the annotation directly on the customEntity.bind method but i got same error.
My Entity code sample :
public class MyEntity implements Serializable, PathBindable<MyEntity> {
#Override #play.db.jpa.Transactional
public MyEntity bind(String key, String value) {
return findById(Long.valueOf(value));
}
#Override
public String unbind(String s) {
return String.valueOf(id);
}
#Override
public String javascriptUnbind() {
return String.valueOf(id);
}
}
My controller sample :
#Transactional
public class MyController extends Controller {
public static Result read(final MyEntity ent) {
return ok(ent.getName());
}
}
My route file sample :
POST /myEntity/:ent controllers.MyController.read(ent : MyEntity)
EDIT :
Like suggested by #Mon Calamari, I've tried with JPA.withTransaction syntax and it works partially, it leads me to another problem with relational data loading, looks like I can't get any relational data from the model afterwards if the model is fetched withing the withTransaction method.
Execution exception[[LazyInitializationException: failed to lazily initialize a collection of role: models.Entity.mappedChilds, could not initialize proxy - no Session]]
Some kind of JPA limitation ? Does it mean JPA and PathBindable's Play feature are incompatible ?
#play.db.jpa.Transactional annotation is for controllers methods only. Try wrapping findById(Long.valueOf(value)) into JPA.withTransaction

Wrapping Spring Data JPA with ApsectJ

Is it possible?
Currently I am using some aspects for my MVC controllers, what works really fine. I'm wrapping their responses and I have desired effect.
I also want to do this with Spring Data JPA repositories. But since they're generated based on the interface e.g:
public interface SomeRepository<T extends Some, ID extends Serializable> extends
BaseRepository<T, ID>, JpaSpecificationExecutor<T> {
public List<T> findById(Long id)
}
It generates me controller which is ready to use:
http://localhost:8080/findById?id=1234
I also want to wrap this controller. Is it possible?
This should work:
#Component
#Aspect
public class MyAdvice {
#Before("execution(* com.company.jpa.SomeRepository+.findById(..))")
public void intercept() { ... }
}
Basically, we are telling the framework to intercept the call to the findById method on any sub-class of SomeRepository.
Here is a sample application demonstrating this in action.