I've got an ejb
#Stateless
#LocalBinding(jndiBinding = DmsExportExecutor.DEFAULT)
public class InjectedBean implements BeanInterface {
}
that implements interface
#Local
public interface BeanInterface {
public static final String DEFAULT = "package.InjectedBean";
}
And i'm trying to inject this into a bean, that's in exactly the same project and package. by #jndiinject annotation
public class AnotherBean {
#JndiInject(jndiName = BeanInterface.DEFAULT)
BeanInterface bean;
}
If i do that, a runtime exception is thrown.
java.lang.RuntimeException: Unable to inject jndi dependency: env/package.InjectedBean/bean into property package.InjectedBean. AnotherBean.bean: package.InjectedBean not bound
Caused by: javax.naming.NamingException: Could not dereference object [Root exception is javax.naming.NameNotFoundException: package.InjectedBean not bound]
Caused by: javax.naming.NameNotFoundException: package.InjectedBean not bound
After refactoring my InjectedBean into another package that is even located inside of the same maven project, it starts working.
Could anyone explain why this happens?
Have you tried using the standard #EJB annotation ?
#EJB
BeanInterface bean;
This should do the work for you by bean type.
You should see if (and how) your injected bean is loaded by the EJB container at container startup
or using the admin gui.
You can always do a basic lookup:
InitialContext().lookup("the.bean.jndi.name").
Y.Lev
Related
Hi I have a spring boot project. The main class package is like this :
com.som.demo
I have used an external jar as a maven dependency in my project. In that jar there is a service class annotated with #Service as below :
#Service
public class SomeServiceImpl implements SomeService {
#Autowired
private TreeCacheWrapper ffCoreCache;
#Autowired(required = false)
private ZookeeperProperties zookeeperProperties;
public SomeServiceImpl(TreeCacheWrapper ffCoreCache, ZookeeperProperties zookeeperProperties) {
this.ffCoreCache = ffCoreCache;
this.zookeeperProperties = zookeeperProperties;
}
}
And the main package where this SomeServiceImpl class is as below :
com.som.test
Now in my project when I am autowiring the class I get the bean creation error while running the spring boot app. This is how I am doing :
#Autowired
private SomeService someService;
Error :
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'someServiceImpl'
Unsatisfied dependency expressed through field 'ffCoreCache';
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'ffCoreCache' defined in class path resource [com/som/test/config/ZooKeeperConfig.class]:
Bean instantiation via factory method failed;
nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [com.som.test.cache.TreeCacheWrapper]:
Factory method 'ffCoreCache' threw exception;
nested exception is java.lang.NoClassDefFoundError: org/apache/curator/retry/ExponentialBackoffRetry
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'ffCoreCache' defined in class path resource [com/som/test/config/ZooKeeperConfig.class]:
Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [com.som.test.cache.TreeCacheWrapper]:
Factory method 'ffCoreCache' threw exception; nested exception is java.lang.NoClassDefFoundError: org/apache/curator/retry/ExponentialBackoffRetry
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.som.test.cache.TreeCacheWrapper]:
Factory method 'ffCoreCache' threw exception; nested exception is java.lang.NoClassDefFoundError: org/apache/curator/retry/ExponentialBackoffRetry
Caused by: java.lang.NoClassDefFoundError: org/apache/curator/retry/ExponentialBackoffRetry
Caused by: java.lang.ClassNotFoundException: org.apache.curator.retry.ExponentialBackoffRetry
When spring boot application starts, it scans for beans in the same package as your main class, and all packages beneath it.
Since your main class resides in the package com.som.demo spring boot will find any beans in this package, or in packages like com.som.demo.sample1, com.som.demo.a.b.c etc
However it won't scan com.som.test package because its a "peer" to the main package.
In general you can configure spring boot to scan the packages of your choice with the help of #ComponentScan annotation that accepts a list of base packages to scan. You can put this annotation right on your main class (next to #SpringBootApplication).
However this is kind of against the conventions of spring boot.
Read this tutorial for more technical details and examples.
Annotate Service interface with #Service, not the Implementation class and try to annotate ServiceImplementation class with #Component.
Spring boot by default scan to beans in your main package. you can configure it using
#SpringBootApplication(scanBasePackages={"com.som.demo" , "com.som.test"})
I have a method with #PostConstruct annotation which uses autowired service
#Service
public ServiceWithPostConstruct{
private AutowiredService autowiredService;
#Autowired
public ServiceWithPostConstruct(AutowiredService autowiredService) {
this.autowiredService= autowiredService;
}
#PostConstruct
public void doSomething() {
autowiredService.doSomethingElse();
}
}
AutowiredService declaration
#Component
public class AutowiredService {
private static final Logger LOGGER = LoggerFactory.getLogger(AutowiredService .class);
private static final String SUCCESS_CODE = "0";
private RestOperations restOperations;
#Autowired
public AutowiredService (RestOperations restOperations) {
this.restOperations = restOperations;
}
///
}
somewhere else in the code, I have a completely unrelated component, which has a scope = request
#Component
#Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ScopedService{
}
and listener in web.xml
org.springframework.web.context.request.RequestContextListener
this service works correctly, where it is used.
However while starting the application, I get the following error:
12-Dec-2017 13:24:15.221 SEVERE [localhost-startStop-1]
org.apache.catalina.core.StandardContext.listenerStart Exception
sending context initialized event to listener instance of class
org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'controller' defined in file
[controller.class]:
Unsatisfied dependency expressed through constructor parameter 1;
nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'serviceWithPostConstruct':
Invocation of init method failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'scopedTarget.scopedService': Scope
'request' is not active for the current thread; consider defining a
scoped proxy for this bean if you intend to refer to it from a
singleton; nested exception is java.lang.IllegalStateException: No
thread-bound request found: Are you referring to request attributes
outside of an actual web request, or processing a request outside of
the originally receiving thread? If you are actually operating within
a web request and still receive this message, your code is probably
running outside of DispatcherServlet/DispatcherPortlet: In this case,
use RequestContextListener or RequestContextFilter to expose the
current request.
This error might have been understood if I would be autowiring the mentioned ScopedService. But clearly I am not. I don't understand, why this #PostConstruct method has anything to do with ScopedService.
If I remove the #PostConstruct annotation problem disappears. And the ScopedService works everywhere as intended, in Singletons as well. However, only if I get rid of the #PostConstruct annotation. Unfortunately, I need to keep it.
I am certain that the use of autowired service in doSomething() method is the core of the problem, if I remove the autowired service, the application starts correctly.
It seems, that because of this #PostConstruct method, Spring checks ALL services, and when it comes to the ScopedService (the only component with scope=request) it recognizes that in that moment there is no HttpRequest and throws an error. Why? It is not connected in any way with that ScopedService.
What can be done about that?
I will appreciate any ideas.
Wierd problem here. I have a bean with a remote interface declared and an implementation defined as a Stateless bean. Since I want to be able to replace the bean with a different bean depending on the implementation requirements, I have an ejb-reference declared in glassfish-web.xml.
I can successfully inject the bean if I use the name syntax to refer to the reference name like #EJB(name = "BeanReference"). I can also do a lookup: new InitialContext().lookup("java:comp/env/BeanReference").
The weird thing happens when I don't have any injections at all (no #EJB). Then the lookup fails with "javax.naming.NameNotFoundException: No object bound to name java:comp/env/BeanReference". If I list the pairs in "java:comp/env" it confirms that the reference doesn't exist unless an #EJB injection occurs somewhere in the application. I have checked the jndi-name entry and confirmed it matches the output from Glassfish during initialization.
I also tried using #Local instead of #Remote and get the same results. I prefer the #Remote since in an actual deployment the MyBean implementation will likely reside on a remote glassfish instance. It is local only for development and testing.
Using Glassfish 3.1.1 and NetBeans 7.1.2. Code snippets below...exception handling omitted for clarity.
#Remote
public interface MyBean {
public String doSomething();
}
#Stateless
public class MyBeanImpl implements MyBean {
#Override
public String doSomething() {
return "something";
}
}
#Stateless
#LocalBean
public class MyOtherBean {
public MyOtherBean() {
Context ctx = new InitialContext();
MyBean myBean = (MyBean)ctx.lookup("java:comp/env/BeanReference");
String rc = myBean.doSomething();
System.out.println("rc = " + rc);
}
}
<ejb-ref>
<ejb-ref-name>BeanReference</ejb-ref-name>
<jndi-name>java:global/appName/MyBeanImpl!com.test.bean.MyBean</jndi-name>
</ejb-ref>
I'm triying to consume a Local EJB in the same Glassfish, but different ears. But Glassfish can't found the local EJB or can't consume
I read this:
According to the JavaEE tutorial, the client of a #Local bean "must run in the same JVM as the enterprise bean it accesses."
In the first ear,
I have the local Interface inside a jar
#Local
public interface MyLocalBean {
int getNumber(int num3);
}
In another jar, I have the implementation
#Stateless
#LocalBean
public class MyLocalBeanImpl implements MyLocalBean,Serializable{
public MyLocalBeanImpl() {}
public int getNumber(int num3){......
In the second ear,
in the same Glassfish
I have the local Interface inside a jar
#Local
public interface MyLocalBean {
int getNumber(int num3);
}
In another jar, I have the consumer
#Stateless
#LocalBean
public class BeanConsumer{
#EJB(name="MyLocalBeanImpl")
private MyLocalBean beanlocal;
with #EJB and (name="MyLocalBeanImpl") parameter the error is:
Cannot resolve reference Local ejb-ref name=MyLocalBeanImpl,Local 3.x
interface =my.package.MyLocalBean,ejb-link=null,lookup=,
mappedName=,jndi-name=,refType=Session|#]
with #EJB and (name="my.package.MyLocalBeanImpl") parameter the error is:
Cannot resolve reference Local ejb-ref name=my.package.MyLocalBeanImpl,
Local 3.x interface =my.package.MyLocalBean,ejb-link=null,
lookup=,mappedName=,jndi-name=,refType=Session|#]***
I tried too with mappedName
#Stateless(name="MyLocalBeanImpl",mappedName ="MyLocalBeanImpl")
public class MyLocalBeanImpl implements MyLocalBean{
#EJB(name="MyLocalBeanImpl",mappedName ="MyLocalBeanImpl")
private MyLocalBean beanlocal;
but the error persist
Cannot resolve reference Local ejb-ref name=MyLocalBeanImpl,
Local 3.x interface =my.package.MyLocalBean,ejb-link=null,
lookup=,mappedName=MyLocalBeanImpl,jndi-name=,refType=Session
GlassFish works with a JNDI like
java:global[/<app-name>]/<module-name>/<bean-name>
I added the annotation #LocalBean to the bean MyLocalBeanImpl
#Stateless
#LocalBean
public class MyLocalBeanImpl implements MyLocalBean{
public MyLocalBeanImpl() {}
public int getNumber(int num3){......
and when I deployed Glassfish say the jndi are two
Portable JNDI names for EJB OtroBean
java:global/myfirstear/myejbs/MyLocalBeanImpl!my.package.MyLocalBeanImpl
and
java:global/myfirstear/myejbs/MyLocalBeanImpl!my.package.MyLocalBean
i'm trying with
#EJB(lookup="java:global/myfirstear/myejbs/MyLocalBeanImpl!my.package.MyLocalBeanImpl")
It seems that Glassfish found the Local Bean, but... Glassfish have problems casting o something like this
javax.naming.NamingException
javax.ejb.EJBException: javax.ejb.CreateException: Could not create stateless EJB
at
com.sun.ejb.containers.StatelessSessionContainer
._getContext(StatelessSessionContainer.java:454)
.....
Caused by: javax.ejb.EJBException:
javax.ejb.CreateException: Could not create stateless EJB
....
Caused by: com.sun.enterprise.container.common.spi.util.InjectionException:
Exception attempting to inject Local ejb-ref name=my.package.BeanConsumer/beanlocal,
Local 3.x interface =my.package.MyLocalBean,ejb-link=null,
lookup=java:global/myfirstear/myejbs/MyLocalBeanImpl!my.package.MyLocalBeanImpl,
mappedName=,jndi-name=,refType=Session into class my.package.BeanConsumer:
Can not set my.package.MyLocalBean field my.package.BeanConsumer.beanlocal
to my.package.beans.__EJB31_Generated__MyLocalBeanImpl__Intf____Bean__
And trying with
#EJB(lookup="java:global/myfirstear/myejbs/MyLocalBeanImpl")
I get:
throws javax.naming.NamingException
javax.ejb.EJBException: javax.ejb.EJBException: javax.ejb.CreateException: Could not create stateless EJB
Caused by: com.sun.enterprise.container.common.spi.util.InjectionException:
Exception attempting to inject Local ejb-ref
name=my.package.BeanConsumer/beanlocal,
Local 3.x interface =my.package.MyLocalBean,
ejb-link=null,
lookup=java:global/myfirstear/myejbs/MyLocalBeanImpl,
mappedName=,jndi-name=,refType=Session
into class my.package.BeanConsumer:
Lookup failed for 'java:comp/env/my.package.BeanConsumer/beanlocal'
in SerialContext
[myEnv={java.naming.factory.initial=
com.sun.enterprise.naming.impl.SerialInitContextFactory,
java.naming.factory.state=
com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl,
java.naming.factory.url.pkgs=
com.sun.enterprise.naming}
It is possible to inject a local EJB into another EJB in the same JVM but different ear.
The problem is that you cannot rely on the name of the bean anymore as you need to tell the consumer bean the complete JNDI name. You can find this name in the server logs during deployment; the moment the bean is bound to the JNDI directory the server shows it in the logs.
in my service layer
public class MyServiceLayerImpl{
public void method1(){
MyServicelayer.method(); //is this correct?
}
public void method2(){
}
#Autowired
MyServiceInterface MyServiceLayer;
}
if i have method inside service layer that need to call another service inside service layer. i cannot use this._method ,because, i'm using AOP for caching. In order for the caching to work, i have to use #Autowired to get the service. Therefore, is the above style ok?
i get below error
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.company.iss.services.MyServiceLayerImpl#85aedd': Autowiring of fields failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.company.iss.services.MyServicelayer com.company.iss.services.MyServiceLayerImpl.MyServiceLayer; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.company.iss.services.MyServiceLayer] is defined: Unsatisfied dependency of type [interface com.company.iss.services.MyServiceLayer]: expected at least 1 matching bean
It's hard to tell from the weird formatting and naming, but if you want to call one service from another:
public interface MasterService {
void someMethod();
}
public class MasterServiceImpl implements MasterService {
private OtherService otherService;
public void someMethod() {
this.otherService.someCallOnOtherService();
}
#Autowired
public void setOtherService(OtherService otherService) {
this.otherService = otherService;
}
}
Now, you must have configured both MasterServiceImpl and whatever implements OtherService. There are many ways to do this, the most popular being explicitly in your XML configuration with annotation-based configured a close second.
Also note that AOP tends to be very flaky if you aren't using interfaces. In your code, your Impl doesn't actually implement anything. I would recommend against that.
Apart from having an uppercase variable and no colon - it's fine.
You would, of course, need to define your class as a bean. Either by using the #Service (or another stereotype) annotation on it, or using <bean> in applicationContext.xml (see here for the annotation-based config introduced in spring 2)
Another thing: your member variables should be lowercase, not uppercase.