Error creating a base repository class - spring-mvc

import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.QueryDslJpaRepository;
import org.springframework.data.querydsl.EntityPathResolver;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
#NoRepositoryBean
public class RepositorySupportImpl<T> extends QueryDslJpaRepository<T, Integer> implements RepositorySupport<T> {
private EntityManager entityManager;
public RepositorySupportImpl(JpaEntityInformation<T, Integer> entityInformation, EntityManager entityManager, EntityManager entityManager1) {
super(entityInformation, entityManager);
this.entityManager = entityManager1;
}
public RepositorySupportImpl(JpaEntityInformation<T, Integer> entityInformation, EntityManager entityManager, EntityPathResolver resolver, EntityManager entityManager1) {
super(entityInformation, entityManager, resolver);
this.entityManager = entityManager1;
}
#Override
public EntityManager getEntityManager() {
return this.entityManager;
}
#Transactional
#Override
public <S extends T> S save(final S entity) {
this.getEntityManager().persist(entity);
return entity;
}
}
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QueryDslPredicateExecutor;
import javax.persistence.EntityManager;
public interface RepositorySupport<T> extends JpaRepository<T, Integer>, QueryDslPredicateExecutor<T> {
EntityManager getEntityManager();
}
in my config class i have repositoryBaseClass = RepositorySupportImpl.class
But I get this error:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'registerService': Unsatisfied dependency expressed through field 'userRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository': Invocation of init method failed; nested exception is java.lang.IllegalStateException: No suitable constructor found on class ca.lighthouse.repository.RepositorySupportImpl to match the given arguments: [class org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation, class com.sun.proxy.$Proxy52]. Make sure you implement a constructor taking these

I had the same problem just now and after some debugging I figured out the solution:
Make sure you only have one EnableJpaRepositories annotation and that it's pointing to the implementation class (not to the interface):
#EnableJpaRepositories(repositoryBaseClass = GenericJpaRepositoryImpl.class)
I hope it helps someone in the future ;)

I already had the same problem, and the solution was to create the right constructor for implementing the repository.
public RepositorySupportImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
super(entityInformation, entityManager);
}

You have to use both constructors in the Impl class:
public GenericRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
super(entityInformation, entityManager);
this.em = entityManager;
domainClass = null;
}
public GenericRepositoryImpl(Class<T> domainClass, EntityManager entityManager) {
super(domainClass, entityManager);
this.em = entityManager;
this.domainClass = domainClass;
}

Thanks for all your comments, its working now. I wish I could definitively pin point the problem, but I can't. Here is the scenario, I have a spring mvc application, with controllers, entities, business services, jsps, and I wanted to clean things up so I decided to break the project down into modules. So I created a new project, added the modules and then copied the files from the old project into the new project. When I copied the RepositorySupport class and interface I thought I should rename it, to what you see above. That resulted in this error and after a few days of researching and trying different things I decided to copy in the original files and it worked. That's all I did, copy in the files and updated the references.

Related

Why do I get an "Ambiguous dependencies for interface" Exception when I'm already uses the #Produces annotation?

I'm using two Messaging Oriented Middleware in my project. RabbitMQ and Apache Kafka. I have an consumer interface IConsume which are implemented by ConsumerRabbitMQ and ConsumerKafka. At startup going through some conditions I use the #Produces annotation to choose an implementation for the Interface Bean that I will inject, but it gives me this error.
Exception 1:
org.jboss.weld.exceptions.DeploymentException: WELD-001409: Ambiguous dependencies for type IConsume with qualifiers #Default
at injection point [BackedAnnotatedField] #Inject private com.mycompany.chatapp.startup.RunConsumers.ct
at com.mycompany.chatapp.startup.RunConsumers.ct(RunConsumers.java:0)
Possible dependencies:
- Session bean [class com.mycompany.chatapp.messagegateway.ConsumerRabbitMQ with qualifiers [#Any #Default]; local interfaces are [IConsume],
- Producer Method [IConsume] with qualifiers [#Any #Default] declared as [[BackedAnnotatedMethod] #Produces public com.mycompany.chatapp.startup.MOMConfigBean.produceIConsume()],
- Session bean [class com.mycompany.chatapp.messagegateway.ConsumerKafka with qualifiers [#Any #Default]; local interfaces are [IConsume]
#Default and #Alternative works, but I want it to choose by checking which of the Middleware is running.
The lookup works, I also tried beanName. I think the problem is with the #Produces, but I can't find to seem what.
import javax.enterprise.inject.Produces;
#Singleton
#Startup
public class MOMConfigBean {
private String mom;
#PostConstruct
public void init() {
mom = "Kafka";
}
#EJB(lookup = "java:global/Chatapp/ConsumerKafka!com.mycompany.chatapp.messagegateway.IConsume")
IConsume kafkaConsumer;
#EJB(lookup = "java:global/Chatapp/ConsumerRabbitMQ!com.mycompany.chatapp.messagegateway.IConsume")
IConsume rabbitConsumer;
#Produces
public IConsume produceIConsume() {
if ("Kafka".equals(mom)) {
return kafkaConsumer;
} else {
return rabbitConsumer;
}
}
public interface IConsume {
// some code
}
#Stateless
public class ConsumerKafka implements IConsume{
// some code
}
#Stateless
public class ConsumerRabbitMQ implements IConsume {
// some code
}
public class runConsumers{
#Inject
private IConsume ct;
}
You have three ambiguous sources of IConsume instances:
a ConsumerKafka EJB
a ConsumerRabbitMQ EJB
an #Produces public IConsume produceIConsume() method.
You need to disambiguate the source of the IConsume instances using a qualifier.
This qualifier would look something like:
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
#Qualifier
#Retention(RUNTIME)
#Target({METHOD, FIELD})
public #interface ConditionalMom {
}
Then qualify the producer:
#Produces
#ConditionalMom
public IConsume produceIConsume() {
if ("Kafka".equals(mom)) {
return kafkaConsumer;
} else {
return rabbitConsumer;
}
}
and the injection site:
public class runConsumers{
#Inject
#ConditionalMom
private IConsume ct;
}
Now you have a single source of #ConditionalMom IConsume instances so it is no longer ambiguous.
You will find that you will be using qualifiers all over the place as you start to further exploit CDI features.

CDI + EJB 3 + EJB Transaction

I need to audit invocations of ejb beans. Saying audit I mean write informations such as current logged user, method name, additional description to a database. I decided to do it by use of CDI decorator:
#Decorator
public class AccountServiceBeanDecorator implements AccountService {
#Inject
#Delegate
#Any
AccountService accountService;
#EJB
private AuditService auditService;
#Override
public Account createAccount(Account account) {
auditService.saveAudit("Method: createAccount", currentUser, "Creating account by admin");
return accountService.createAccount(account);
}
}
and the decorated class:
#Stateless
public class AccountServiceBean implements AccountService {
#Override
public Account createAccount(Account account) {
...
}
}
Now if I call AccountService from another ejb stateless bean, what will happen with transaction?:
#Stateless
public ApplicationFacadeBean implements ApplicationFacade {
#EJB
private AccountService accountService;
#Override
public Account createAccount(Account account) {
return accountService.createAccount(account);
}
}
I wanted to log transaction status in decorator (AccountServiceBeanDecorator) and decorated class (AccountServiceBean), so I injected TransactionSynchronizationRegistry as a resource in both classes:
#Decorator
public class AccountServiceBeanDecorator implements AccountService {
#Inject
#Delegate
#Any
AccountService accountService;
#EJB
private AuditService auditService;
#Resource
private TransactionSynchronizationRegistry reg;
#Override
public Account createAccount(Account account) {
log.info("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
log.info("tx ({}): {}", new Object[] {reg.getTransactionStatus(), reg.getTransactionKey()});
log.info("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
auditService.saveAudit("Method: createAccount", currentUser, "Creating account by admin");
return accountService.createAccount(account);
}
}
and
#Stateless
public class AccountServiceBean implements AccountService {
#Resource
private TransactionSynchronizationRegistry reg;
#Override
public Account createAccount(Account account) {
log.info("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
log.info("tx ({}): {}", new Object[] {reg.getTransactionStatus(), reg.getTransactionKey()});
log.info("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
...
}
}
I received strange behavior:
log from decorator
tx (0): JavaEETransactionImpl: txId=6 nonXAResource=null jtsTx=null localTxStatus=0 syncs=[com.sun.ejb.containers.ContainerSynchronization#68fb15d0]]]
NullPointerException on second log (reg is null).
Can anybody explain it to me? Wheter AccountServiceBean class is called within the same transaction as ApplicationFacade?
Thank you
first: i would not mixing ejbs with cdi interceptors. ejbs has it on interceptor implementations.
second: interceptors are executed in the same transaction as the ejb where the interceptor is around.
possible solution:
create a correct ejb interceptor
put the interceptor around the method / class
create a second ejb (MyLoggerBean) with a method like this logToDatabase(String message) and annotate this method with #TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
inside the interceptor create a class member like this: #EJB private MyLoggerBean loggerBean
inside your #AroundInvoke annotated method you could call loggerBean. logToDatabase(...)
this would create a new transaction from inside the current transaction of the ejb where the interceptor is around
--> i know my english is not very good. but i hope that you understand what i think should work. if i have the time, i make e example on github...
Hmm... what container are you using? Generally I wouldn't suspect a CDI decorator to work on an EJB... I can't think of anything in the JEE spec that I've encountered that would give evidence either way.
Faced with your problem though, I did this with an interceptor, not a decorator. These are supported by the EJB spec... Anyway, here's my code, you would need to grab the variables from the context in your case:
import java.lang.reflect.Method;
import javax.inject.Inject;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;
public class InvocationCountInterceptor {
#Inject
private InvocationCounter counter;
#AroundInvoke
public Object intercept(InvocationContext ctx) throws Exception {
Object returnValue = ctx.proceed();
Class<? extends Object> className = ctx.getTarget().getClass();
Method methodName = ctx.getMethod();
counter.incrementCounter(className, methodName);
return returnValue;
}
}
Then whatever EJB or EJB Method you want to audit, I just added this: #Interceptors(InvocationCountInterceptor.class)

autowiring selective beans into a list reference

I have a service interface I with implementaions I1,I2,I3...I10 out of which I want to use I1-I5 to be autowired as a List<I> in controller class C. The I6-I10 should not be be autowired. How can I achieve this. Moreover the I implementations are annotated #Service beans. I do not want to move them to xml declarations.
Based on the comment by mvb13 I have tried to weave a solution for the problem....
So I write a class extending ArrayList and mark it a Component
#Component("mysublist")
public class MyList extends ArrayList implements ApplicationContextAware
{
#Value("comma.sep.eligible.beans.classnames")
private String eligibles;
private ApplicationContext appCtx;
#PostConstruct
public void init()
{
Map allBeans = appCtx.getBeansOfType(I.class);
for(Object bean:allBeans.values())
{
if(eligibles.contains(bean.getClass().getSimpleName()))
{
add(bean);
}
}
}
public void setApplicationContext(ApplicationContext appCtx)
{
this.appCtx = appCtx;
}
}
Now I can autowire the above bean in my required class definition as:
#Service
public class MyService
{
#Resource(name="mysublist")
private List<I> myReqdBeans;
......
}
*Please ignore the generics related implications in the code.
You should use #Qualifier. It defines any subset that you need.
#Autowired
#Qualifier("MySubset")
private List<I> list;
But I think you should move your bean definitions in xml to use <qualifier ... /> property. I think you haven't another option to specify qualifier.
The #Qualifier annotation should give you what you need. You need to apply it in two places:
On the #Service beans that you wish to include in the sub-list
On the #Autowired list injected into your controller
So addressing the #Service beans first:
#Service
#Qualifier("MySubList")
public class MyService implements IMyService
{
}
And then within your Controller:
#Controller
public class MyController
{
#Qualifier("MySubList")
#AutoWired
private List<IMyService> myServices;
}
This instructs Spring to #AutoWire all IMyService implementations #Qualified as "MySubList"

How can I use same EJB in two different CDI beans and retrieve the values set from one bean into the another?

I have a stateful session bean where a list is maintained:
#Stateful
public class CartDAO{
private List<ShoppingCart> tempCart;
public void add(ShoppingCart shoppingCart){
tempCart.add(shoppingCart);
}
public List<ShoppingCart> getCart(){
return tempCart;
}
#PostConstruct
public void init(){
tempCart = new ArrayList<>();
}
}
Controller1 to add to the cart:
#Named
#SessionScoped
public class Controller1 implements Serializable {
#EJB
CartDAO cartDao;
public String addToShoppingCart() {
cartDao.add(shoppingCart);
}
}
Now, i want to ask you could i get the added items to the list from another cart?
#Named
#SessionScoped
public class Controller2 implements Serializable {
#EJB
CartDAO cartDao;
public String getShoppingCart() {
System.out.println(cartDao.getCart());//returns null
}
}
Obviously the above code returns null.
How do I retrieve the list from another controller. Any help will be much appreciated.
I don't see any obvious mistake here (are you sure that you don't call Controller2#getShoppingCart() before adding any items do your CartDAO?) but here are couple of my notions
you should have your CartDAO implement some interface or make it #LocalBean
all stateful beans should have method annotated with #Remove so you can clean the resources used in the bean (close datasources and son) and bean will be removed from the memory after this call
now it's recommended to use #Inject everywhere instead of #EJB, it's the same (you have to use #EJB only when you inject remote beans)
And also one point, if the System.out.println(cartDao.getCart()); returns null than it means the #PostConstruct haven't been called which is strange. Can you provide some more info about container and your environment?Also show us imports, this is big source of mistakes.

WELD-001408 Unsatisfied dependencies when injecting EJBs that implement interfaces

Here is the situation.
I've got the following interfaces:
public interface Parent { }
public interface ChildOne extends Parent { }
public interface ChildTwo extends Parent { }
and 2 EJBs:
#Stateless
public class FirstBean implements ChildOne { }
#Stateless
public class SecondBean implements ChildTwo { }
And also this CDI Bean:
#Named
#SessionScoped
public class TestController implements Serializable {
#Inject
private FirstBean firstBean;
#Inject
private SecondBean secondBean;
}
While trying to deploy this on Glassfish 3.1 I get the following exception:
Exception while loading the app : WELD-001408 Unsatisfied dependencies for type [FirstBean]
with qualifiers [#Default] at injection point [[field] #Inject private com.test.controllers.TestController.firstBean]
org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [FirstBean]
with qualifiers [#Default] at injection point [[field] #Inject private com.test.controllers.TestController.firstBean]
at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:305)
When both EJBs implement the Parent interface, the exception is the same.
Also, I tried adding qualifiers, but that didn't change anything.
I just played around with your construct, read a bit of the weld docu and found out the following.
You are using EJBs that implement an interface, so the no-interface view is not possible anymore (obviously), but you are trying to directly access the implementation. As soon as you declare it as an EJB you have to keep in mind the conventions. So, if you define an interface you have to use it to get access to the EJB. Changing it to the following, should work out:
#Inject
private ChildOne firstBean;
Accessing the implementation even though an interface is defined is just possible for plain CDI Managed Beans (classes without the #Stateless/#Stateful annotations). So get rid of your annotation and it will work out.
Just for your information, if you are using Glassfish. If you stick to your EJBs and try to access the parent interfaces method you will run into this bug / exception.
Better late than never:
Annotating the SLSB aditionally with #LocalBean works for me with JBoss AS 7.1.1. I don't like the idea of creating the interface for no added value.
Using your example:
#Stateless
#LocalBean
public class FirstBean implements ChildOne { }
#Stateless
#LocalBean
public class SecondBean implements ChildTwo { }
Have you tried using #EJB annotation rather then the CDI #inject annotation?
E.g.
#Named
#SessionScoped
public class TestController implements Serializable {
#EJB
private FirstBean firstBean;
#EJB
private SecondBean secondBean;
}

Resources