Play Framework PathBindable with JPA Transactionnal context incompatible? - jpa

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

Related

spring data repository Implenation

I am using Spring DATA JPA and selected #Query annotation for creating queries (instead of using NamedQueries and Queries created from MethodName)
I have a data repository as below
public interface EventRepository extends CrudRepository<Event, Long> {
#Query("select e from Event e where e.name = :eventName)
public List<Event>findEventByName(String eventName );
}
Interface looks good and its enough as per Spring reference doc.
But I need a impl class because I need many other methods in addition to above.
I am facing 2 issues when I create EventRepositoryImpl java implementing EventRepository
Its asking to implement all the methods in EventRepository, findEventByName method is self contained in interface and why I need implement it again in Impl class?
Its asking to implement all the methods in CrudRepository, I know its per OOPS design, But there many methods
So, for these issues can I define my EventRepositoryImpl as abstract,
this seems to be working fine.
But do I need to worry about anything else, when Spring uses a abstract class as a bean.
or is there an elegant way to solve this issue.
Appreciate your help.
You do not have to implement all of these methods neither create an abstract class. Take a look into official documentation.
interface UserRepositoryCustom {
public void someCustomMethod(User user);
}
class UserRepositoryImpl implements UserRepositoryCustom {
public void someCustomMethod(User user) {
// Your custom implementation
}
}
interface UserRepository extends CrudRepository<User, Long>, UserRepositoryCustom {
// Declare query methods here
}

Spring Data JPA Querydsl doesn't work with projection

I have implemented Spring Data JPA and used Querydsl for search conditions. Which works fine with few changes as given in spring docs.
My REST controller method is given below
#RequestMapping(value = "/testdsl", method = RequestMethod.GET)
Iterable<User> index(
#QuerydslPredicate(root = User.class) Predicate predicate)
{
return userRepository.findAll(predicate);
}
and the repository is given below, commented methods give me projected objects nicely.
public interface UserRepository extends CrudRepository<User, Integer>,
QueryDslPredicateExecutor<User>, QuerydslBinderCustomizer<QUser>
{
//Collection<OnlyName> findAllProjectedBy();
//OnlyName findProjectedById(Integer id);
#Override
default public void customize(QuerydslBindings bindings, QUser root)
{
bindings.bind(String.class)
.first((StringPath path, String value) -> path.containsIgnoreCase(value));
}
}
And then I have this projection implemented where I get a subset of the whole entity class which is returned as the response.
public interface IUserProjection {
//...all required getters..
}
Now I want my Querydsl to return these projected objects.
Do we have any sample of such combination? I am using spring boot 1.4.0.RELEASE
You can do that but you'll need a concrete class...
class UserProjection {
#QueryProjection
public UserProjection(long id, String name){
...
}
}
And then your query would look like (in QueryDSL 3):
query.from(QTenant.tenant).list(new QUserProjection(QTenant.tenant.id, QTenant.tenant.name));
EDIT:
Query for queryDSL 4 would look like this:
List<UserProjection> dtos = query.select(new QUserProjection(QTenant.tenant.id, QTenant.tenant.name))
.from(tenant).fetch();

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.

Mongo custom repository autowired is null

I try to autowire my custom mongo repository (and it seems the constructor is executed) but still the result is null
I've looked at some similar questions
Spring Data Neo4j - #Autowired Repository == null
and
spring data mongo repository is null
but I still don't know how to solve this.
public class TestRepo {
#Autowired
PersonRepository repository;
public void find(String name)
{
System.out.println(repository.findByName(name));
}
}
config
<mongo:repositories base-package="com.yyyy.zzz" />
PersonRepository
public interface PersonRepository extends Repository<Person, BigInteger> {
#Query("{name : ?0}")
public Person findByName(String name);
}
Implementation
public class PersonRepositoryImpl implements PersonRepository{
PersonRepositoryImpl()
{
System.out.println("constructing");
}
public Person findByName(String name) {
...
}
}
if I get the repository bean directly from context it works
Your repository setup looks suspicious. To execute query methods, you don't need to provide an implementation at all. I suspect in your current setup the custom implementation you have in PersonRepositoryImpl "overrides" the query method and thus will be preferred on execution.
If you simply drop your implementation class, Spring Data will automatically execute the query for you on invocation.
Generally speaking, custom implementation classes are only needed for functionality you cannot get through other means (query methods, Querydsl intergration etc.).

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

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