I am using EJB 3.1 and jersey for a restapi. I would like to have a SuperResource as below, which is then inherited by the actual rest resources as below. The way I have it now, my #EJB object is null. Does anyone know how to fix this?
#Stateless
public class SuperResource {
#EJB
protected GenericDao<DomainObject> dao;
. . .
}
public class MyResource extends SuperResource{
public String doGet(){
return dao.get(...);
}
}
I have tried the whole truth table between #Stateless and #Local, and SuperResource and MyResource. None of the permutations seems to work.
I don't know if that's important, my server is Glassfish 3.1.2
EDIT TO ADD DETAILS:
I didn't think so , but it seems that more detail may be necessary here:
Structure of my application:
#Local
public interface GenericDao<T extends DomainObject> {…}
public interface LoginDao extends GenericDao<Login>{...}
#Stateless
public class GenericDaoImpl<T extends DomainObject> implements GenericDao<T> {…}
#Stateless
public class LoginDaoImpl extends GenericDaoImpl<Login> implements LoginDao {…}
#Entity
public class Login implements java.io.Serializable, DomainObject {…}
What works:
#Stateless
#Path("mypath")
public class MyResource{
#EJB
private LoginDao dao;
public String doGet(){
return dao.get(...);
}
}
MyResource has to be an EJB bean as well, by annotating it with #Stateless:
#Stateless
public class MyResource extends SuperResource{
public String doGet(){
return dao.get(...);
}
}
If you only need the injected DAO, you could choose to inject your JAX-RS resource with that DAO using CDI instead. If you resources -becomes- a stateless bean, then this has certain consequences that you need to be aware of (like a transaction that starts for every method, unless you explicitly disable that, etc).
It looks like EJB injection issue. Depending on Server, you need to play around mappedName/name/beanName
What I can confirm is that, the following code works on JBoss 7.1.1.
#Local
public interface HelloWorldLocal {
public String sayHello();
}
#Stateless
public class HelloWorldBean implements HelloWorldLocal {
public String sayHello(){
return "Hello..............................................................................";
}
}
#Remote
public interface BaseRemote {
public String test();
}
#Stateless
public class BaseBean implements BaseRemote{
#EJB
HelloWorldLocal bean;
public String test() {
return "Base Bean";
}
}
#Remote
public interface DerivedRemote {
String test();
}
#Stateful
public class DerivedBean extends BaseBean implements DerivedRemote{
public String test() {
return bean.sayHello();
}
}
Related
I am trying to implement as of enterprise level, there they have folders like Repository,Service,ServiceImpl
In Services they have interface with method declaration
In ServiceImpl they have class implementing the interface of services
In Repository they have all Repository interfaces
BeanInjection is a class where we have all repositories and service classes and interfaces with
#Autowired annotation.
When I tried to implement "#Autowired" to service class getting this Error.
Tried this no help link
Tried this no help but getting loop error link
Controller.java
public class SessionController extends BeanInjectionService {
#GetMapping
public ResponseEntity<List<Session>> list(){
LOGGER.info("Request received to view the sessions");
List<Session> sessions = sessionService.findAll();
LOGGER.info("Successfully fetched all the sessions");
return new ResponseEntity<>(sessions, HttpStatus.OK);
}
SessionService.java(Interface)
public interface SessionService {
List<Session> findAll();
}
SessionServiceImpl.java(Class)
public class SessionServiceImpl extends BeanInjectionService implements SessionService {
#Override
public List<Session> findAll(){
return sessionRepository.findAll();
}
BeanInjectionService.java(Class)
public class BeanInjectionService {
#Autowired
public SessionRepository sessionRepository;
**// Error Showing here while starting application
// Consider defining a bean of type 'com.example.conferencedemo.services.SessionService' in your configuration.**
#Autowired
public SessionService sessionService;
#Autowired
public SpeakerRepository speakerRepository;
#Autowired
public SpeakerService speakerService;
}
SessionRepository.java(Interface)
public interface SessionRepository extends JpaRepository<Session,Long> {
}
Thanks in advance
I find using BeanInjectionService a little weird, but I'll answer around it.
Unless you add #Service on SessionServiceImpl, you can't autowire it.
Circular dependency - If you do step 1, it will create a circular dependency because SessionServiceImpl needs its superclass object(BeanInjectionService) to be created first. But BeanInjectionService cannot be created unless it finds an object of SessionServiceImpl.
To break the circular dependency, you have only one option. Don't extend BeanInjectionService. Rather, autowire SessionRepository directly into SessionServiceImpl.
#Service
public class SessionServiceImpl implements SessionService {
#Autowired
private SessionRepository sessionRepository;
#Override
public List<Session> findAll(){
return sessionRepository.findAll();
}
}
Having the following class structure:
public abstract class A {
String someProperty = "property"
public abstract void doSomething();
}
#Service
public class Aa extends A {
#Override
public abstract void doSomething() {
System.out.println("I did");
}
}
#Service
public class Ab extends A {
#Override
public abstract void doSomething() {
System.out.println("I did something else");
}
}
I need a way to tell Spring which A concrete class to Autowire in my Foo service, based on a property in a properties file.
#Service
public class Foo {
#Autowire
private A assignMeAConcreteClass;
}
And in my properties file I have this:
should-Aa-be-used: {true, false}
Remove the #Service annotation, instead write a #Bean-annotated method in a configuration class that reads the properties, and returns the appropriate A instance.
Not a new way but in your case I think that a possible suitable way would be to use
FactoryBean in the class that wants to inject the bean conditionally.
The idea is simple : you implement FactoryBean by parameterizing it with the interface of the bean that you want to inject and override getObject() to inject the wished implementation :
public class FactoryBeanA implements FactoryBean<A> {
#Autowired
private ApplicationContext applicationContext;
#Value("${should-Aa-be-used}")
private boolean shouldBeUsed;
#Override
public A getObject() {
if (shouldBeUsed) {
return applicationContext.getBean(Aa.class));
return applicationContext.getBean(Ab.class));
}
}
But FactoryBean instances are not classic beans. You have to configure it specifically.
You could configure it in a Spring Java configuration in this way :
#Configuration
public class FactoryBeanAConfiguration{
#Bean(name = "factoryBeanA")
public FactoryBeanA factoryBeanA() {
return new FactoryBeanA();
}
#Bean
public beanA() throws Exception {
return factoryBeanA().getObject();
}
}
I have a service which I am trying to inject across various classes in my tests but I am getting its instance as null.
My config interface:
MyService.java
public interface MyService {
public String getHostUri();
}
My implementation class of this interface: MyServiceImpl.java
public class MyServiceImpl implements MyService {
private static final String BASE_HOST_URI_CONFIG = "localhost:4444";
#Override
public String getHostUri() {
return BASE_HOST_URI_CONFIG;
}
My Spring configuration class with the bean:
#Configuration
public class AutomationSpringConfig {
#Bean
public MyService getMyService(){
return new MyServiceImpl();
}
}
My testNG class:
#ContextConfiguration(classes=AutomationSpringConfig.class ,loader =AnnotationConfigContextLoader.class)
public class BasicAutomatedTest extends AbstractTestNGSpringContextTests {
private static final Logger LOGGER = Logger.getLogger(BasicAutomatedTest.class);
#Inject
private MyService myService;
#Test
public void basicTest {
Setup setup = new Setup();
LOGGER.info(myService.getHostUri());
LOGGER.info(setup.myService.getHostUri());
}
}
My helper class in which I am not able to get the injection:
public class Setup {
#Inject
public MyService myService;
}
So when I try to get the hostUri via the setup object in the BasicAutomatedTest's basicTest method I get a NullPointerException.
So I am not able to inject the MyService bean in the Setup class.
In order to use annotations you need to specify that behaviour in your beans XML configuration file. Something like this:
<context:component-scan base-package="your.base.package"/>
<context:annotation-config/>
Hope it helps!
Because I have some generics which need to be passed to the newly produced object, I am creating a producer. But while producer works, the EntityManager is not injected because producer creates an instance with operator new instead of using CDI.
How can I produce an object with CDI support?
The code:
Qualifier:
#Qualifier
#Retention(RUNTIME)
#Target(
{ FIELD, TYPE, METHOD })
public #interface Multiselector
{
Class<? extends Dbo> clazz();
}
Producer:
#SessionScoped
public class MultiselectorProducer implements Serializable
{
#Produces
#Multiselector(clazz = SpecialDbo.class)
public MultiselectorService<SpecialDbo> produce()
{
return new MultiselectorService<SpecialDbo>(SpecialDbo.class);
}
}
Service class:
#Stateful
#LocalBean
public class MultiselectorService<T extends Dbo> implements Serializable
{
#Inject
private EntityManager em;
private List<T> itemList;
public MultiselectorService()
{
}
public MultiselectorService(Class<? extends Dbo> clazz)
{
itemList = em.createQuery("some Sql String", clazz);
}
....
}
NOTE: The EntityManager is a custom crud service which is otherwise injected correctly
Any improvement suggestions over the code are welcome. Thanks!
You have mixed a lot of unrelated things:
Your service MultiselectorService is an EJB, and you cannot produce it with a producer. EJB is registered once application is created and then depending on the scope it creates instances.
You have a method public void MultiselectorService(Class<? extends Dbo> clazz) with the name similar to constructor, it against convention.
Assume that you have fixed that method to be a constructor, but then line 'itemList = em.createQuery("some Sql String", clazz);' will fail with NPE. Because em will be initialized only after bean creation. there are two ways to do it:
Inject entity manager into constructor (this is against EJB spec, if you will still use EJB)
Execute initialization operation in method with annotation '#PostConstruct'
Do you have a producer for EntityManager ? e.g. you cannot just inject entity manager, you need to provide as a resource for EJB, with annotation #PersistenceContext
I understand what you try to achieve. The main problem is that manually created beans are not managed by container, this means that interceptors and decorators won't apply (e.g. PostConstruct and Transactional annotation will not work). Check here. So far the best way to achieve this is:
public interface SpecialDboMultiselectorService extends MultiselectorService {
}
#Stateless
public class SpecialDboMultiselectorServiceImpl extends MultiselectorServiceImpl<SpecialDbo> implements SpecialDboMultiselectorService
{
public SpecialDboMultiselectorServiceImpl() {
super(SpecialDbo.class);
}
}
public class MultiselectorServiceImpl<T extends Dbo> implements MultiselectorService {
#Inject
private EntityManager em;
private Class<? extends Dbo> clazz;
private List<T> itemList;
public MultiselectorService(Class<? extends Dbo> clazz) {
this.clazz = clazz
}
#PostConstruct
public void init() {
itemList = em.createQuery("some Sql String", clazz);
}
}
and inject SpecialDboMultiselectorService.
I have a class
EntiyFacadeImpl.java
#Stateless
public class EntityFacadeImpl implements EntityFacade {
#EJB
ICustomerBean customerBean;
public void printCustomer(Customer c) {
customerBean.printCustomer(c);
customerBean.additionalFieldsHandler(c.getAdditionalFields().toString());
}
}
Where ICustomerBean is #Local interface and have two implementation classes CustomerBean.java and CustomerBeanExt.java where later one extends CustomerBean.java
#Stateless(name = "CustomerBean")
public class CustomerBean implements ICustomerBean {
public void printCustomer(Customer customer) {
System.out.println(customer);
}
public void additionalFieldsHandler(String additionalFields) {
// an empty implemetation here
}
}
#Stateless(name = "CustomerExtBean")
public class CustomerExtBean extends CustomerBean implements ICustomerBean {
#Override
public void additionalFieldsHandler(String additionalFields) {
// some custom implemetation
System.out.println("Additional Fields: "+additionalFields);
}
}
ICustomer interface looks like this
#Local
public interface ICustomerBean {
public void printCustomer(Customer c);
public void additionalFieldsHandler(String additionalFields);
}
My aim is that whenever I inject my EntityFacade (interface for EntityFacadeImpl) in SimpleRESTPojo.java only, I want CustomerExtBean to be inject in it, while when any other class injects it I want CustomerBean to be injected
#Path("/pojo")
public class SimpleRESTPojo {
#EJB
private EntityFacade entityFacade;
}
My app's entry point is EntityFacade only. Is there a way to achieve this?
Actually, after reading your question, it looks like you're trying to introduce tight coupling. CDI doesn't make EntityFacade aware of where it was injected in to. I don't see a way to do this.
What you could do is create an extended version of EntityFacade that used this injection point:
#Inject
#Extended //or whatever qualifier you come up with
private ICustomerBean customerBean;
and then use that same qualifier on the extended EntityFacade.