I am using Spring 4.x in which I am using #Conditional annotation to control the bean registration.
I have classes defined as given below,
#Controller
class SchoolController{
#Autowired
#Qualifier("studentProcessor")
private StudentProcessor studentProcessor;
//Some code
}
#Component("studentProcessor")
class StudentProcessor{
#Autiwired
private SportService sportService;
//Some code
}
#Component
#Conditional(ServiceCondition.class)
class SportService{
//Some code
}
class ServiceCondition implements Condition{
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//Some condition
}
}
When I start the Tomcat, I get this exception:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'studentProcessor': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.student.service.SportService com.student.processors.StudentProcessor.sportService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.student.service.SportService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Is this the expected behavior?
If not then how do I get rid of this issue?
From your configuration, SportService bean is loaded based on the conditional implementation of ServiceCondition.
So, if the matches method returns false for some reason based on your logic, then SportService is would not be created and will not be available for autowiring.
That being said, StudentProcessor cannot have a concrete #Autowired for SportService.
I am not fully aware of your requirement, but for you to proceed with this configuration, you need to mark autowiring as optional.
#Autiwired
private SportService sportService;
//Some code
to
#Autiwired(required = false)
private SportService sportService;
//Some code
Further, you need to check if the instance is injected or not and then use it.
Related
(Trying to keep this simple.)
I have a (partial) ByteBuddy recipe like this:
builder
.method(someMatcher())
.intercept(MethodDelegation.to(this.interceptor));
I have an "interceptor" class defined like this:
private static final class Interceptor {
private Interceptor() {
super();
}
#RuntimeType
private final Object doSomething(#This final Proxy<?> proxy,
#SuperCall final Callable<?> callable,
#Origin final String methodSignature) throws Exception {
final Object proxiedInstance = proxy.getProxiedInstance();
// TODO: logic
return callable.call(); // for now
}
}
(The interceptor method needs to be non-static for various reasons not important here.)
When I create an instance of this ByteBuddy-defined class and call a simple public void blork() method on it, I get:
Cannot resolve ambiguous delegation of public void com.foo.TestExplorations$Frob.blork() to net.bytebuddy.implementation.bind.MethodDelegationBinder$MethodBinding$Builder$Build#3d101b05 or net.bytebuddy.implementation.bind.MethodDelegationBinder$MethodBinding$Builder$Build#1a9efd25
How can there be ambiguity when there is only one interceptor? What have I done wrong?
Byte Buddy just adds a method call to the instrumented class which needs to be able to see the target class. If it is private, it is ignored and Byte Buddy searches further up the hierarchy where it finally consideres the methods of Object which are all equally unsuited but therefore an ambiguity exception is thrown instead of an exception that no method could be bound.
In the following case,
public class Base {
#Transactional
public void doSave() {
// ...
}
}
public class Inherited extends Base {
public void someMethod() {
super.doSave();
}
#Override
public void doSave() {
super.doSave();
}
}
If I add the #Transactional annotation to Inherited.someMethod, the interceptor gets called without issue.
However, without the annotation on the inherited class, the interceptor does not get involved in the call to the super class from Inherited.someMethod().
Furthermore, calling Inherited.doSave() does not seem to get the interceptor invoked either. I would have expected the annotation on the superclass to be also valid on the subclass. Is this not the expected behaviour?
I am using Apache DeltaSpike for the #Transactional annotation and this is being deployed as a war in an ear (technically as a jar in a war in an ear). However, this may not be relevant as trying with a custom interceptor shows the same behaviour.
This is JBoss EAP 6.3.0 Alpha in case its relevant.
This is expected. Interceptors are only applied if the object is managed. When you you write it this way with inheritence, it's not applied as it's not part of a call stack that CDI is aware of. You would need to inject Base into your class and call Base.doSave
I have a JSF Beans structure of this sort:
#ManagedBean
#ViewScoped
public class ViewBeany implements Serializable {
....
#ManagedProperty(value='#{sessionBeany})
transient private SessionBeany sessionBeany;
...
public getSessionBeany() { ... };
public setSessionBeany(SessionBeany sessionBeany) { ... };
}
The reason for the transient is that the session bean has some non-Serializable members and cannot be made Serializable.
Will this work?
If not, How can I solve the problem of not being able to serialize SesionBeany but having to keep it as a managed property under a view scoped bean?
Thanks!
This won't work. If the view scoped bean is serialized, all transient fields are skipped. JSF doesn't reinject managed properties after deserialization, so you end up with a view scoped bean without a session scoped bean property which will only cause NPEs.
In this particular construct, your best bet is to introduce lazy loading in the getter and obtain the session bean by the getter instead of by direct field access.
private transient SessionBeany sessionBeany;
public SessionBeany getSessionBeany() { // Method can be private.
if (sessionBeany == null) {
FacesContext context = FacesContext.getCurrentInstance();
sessionBeany = context.getApplication().evaluateExpressionGet(context, "#{sessionBeany}", SessionBeany.class);
}
return sessionBeany;
}
[UPDATE: After discussion on the Glassfish forums/ML at http://forums.java.net/jive/thread.jspa?messageID=480532 a bug was filed against Glassfish https://glassfish.dev.java.net/issues/show_bug.cgi?id=13040 for this issue.]
I'm trying to inject a local no-interface view of a #Stateless EJB into a JSF2 #Named #javax.enterprise.context.SessionScoped backing bean. The EJB is one of several that extend an abstract generic base class. Injection of "#Inject TheEJBClass varName" fails with "Unable to convert ejbRef for ejb TheEJBClass to a business object of type class my.package.name.TheAbstractBase". [edit: Actually, it turns out that injection succeeds, but method resolution in the injected proxy for methods inherited from superclasses fails.] If I use "#EJB TheEJBClass varName" then varName remains null, ie nothing is injected.
Details:
I'm running Glassfish 3.0.1 on Linux (Ubuntu 10.04 in case it matters) and having real problems handling injection of my data model EJBs into my JSF2 session scoped models using CDI (Weld). And yes, before you ask, I have beans.xml in place and CDI is activating to perform injection.
If I inject it with an #EJB annotation, eg:
#EJB TheEJBClass memberName;
... the EJB isn't actually injected, leaving memberName null.
If I inject it with a CDI #Inject annotation:
#Inject TheEJBClass memberName;
... then CDI complains when I call a method of "memberName" that's implemented in a superclass of TheEJBClass and not overridden in TheEJBClass its self, reporting:
java.lang.IllegalStateException: Unable to convert ejbRef for ejb TheEJBClass to a business object of type class my.package.name.TheAbstractBase
at
com.sun.ejb.containers.EjbContainerServicesImpl.getBusinessObject(EjbContainerServicesImpl.java:104)
at
org.glassfish.weld.ejb.SessionObjectReferenceImpl.getBusinessObject(SessionObjectReferenceImpl.java:60)
....
I've tried converting the base to concrete class and de-generifying it, but encounter the same problem, so I don't think I'm hitting the Weld bugs with generic bases (https://jira.jboss.org/browse/WELD-305, https://jira.jboss.org/browse/WELD-381, https://jira.jboss.org/browse/WELD-518).
An outline of the code, with full package qualification on annotations added for clarity, is:
// JSF2 managed backing bean.
//
// Called via #{someJSF2Model.value} in a JSF2 page
//
#javax.inject.Named
#javax.enterprise.context.SessionScoped
public class SomeJSF2Model implements Serializable {
#javax.inject.Inject TheEJBClass member;
public Integer getValue() {
return member.getValue();
}
// blah blah
}
// One of several EJB classes that extend TheAbstractBase
#javax.ejb.Stateless
public class TheEJBClass extends TheAbstractBase {
// blah blah
// does **NOT** override "getValue()"
}
public abstract class TheAbstractBase {
// blah blah
public Integer getValue() {
return 1;
}
}
Note that injection does work if I override TheAbstractBase.getValue() in TheEJBClass, or if I call a method defined in TheEJBClass and not any superclass. It seems like the issue is something to do with inheritance.
Very similar code that used JSF2's built-in lifecycle and injection features worked, but given that this is a new project and CDI is where things are heading in the future, I thought it best to try to go for CDI. Here's what I started out with using JSF2/EJB injection, which worked:
// JSF2 managed backing bean. Using #ManagedBean and JSF2's #SessionScoped
// instead of CDI #Named and CDI #SessionScoped this time.
//
#javax.faces.bean.ManagedBean
#javax.faces.bean.SessionScoped
public class SomeJSF2Model implements Serializable {
#javax.ejb.EJB TheEJBClass member;
public Integer getValue() {
return member.getValue();
}
// blah blah
}
// One of several EJB classes that extend TheAbstractBase
// Unchanged from CDI version
#javax.ejb.Stateless
public class TheEJBClass extends TheAbstractBase {
// blah blah
// does **NOT** override "getValue()"
}
// Unchanged from CDI version
public abstract class TheAbstractBase {
// blah blah
public Integer getValue() {
return 1;
}
}
I'm currently working on putting together a self-contained test case, but thought I'd fire off the question now in case this is something where I'm just doing something silly or there's a well known solution my Google-fu isn't up to finding. Why did it work with JSF2/EJB injection, but fail with CDI injection?
( Since re-posted on the Glassfish forums as http://forums.java.net/jive/thread.jspa?threadID=152567 )
As noted above, it's a Weld/glassfish bug.
Fix: Give up on Glassfish and move to JBoss AS 7, which actually works most of the time.
public void runTest() throws Exception {
InitialContext ctx = new InitialContext();
ResourceManager bean = (ResourceManager) ctx.lookup("ejb/ResourceManagerJNDI");
System.out.println(bean.DummyText());
}
Hello. So i'm trying to create an EJB application, and this is the test client for it. the JNDI lookup is successful but when calling the "DummyText" method, i get the following error:
javax.ejb.EJBException: nested exception is: java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.RemoteException: nested exception is: javax.ejb.EJBException: nested exception is: javax.ejb.CreateException: Could not create stateless EJB; nested exception is:
javax.ejb.EJBException: nested exception is: javax.ejb.CreateException: Could not create stateless EJB (...)
This is how the bean class looks:
#Stateless(name="ResourceManager", mappedName="ejb/ResourceManagerJNDI")
#Remote
#Local
public class ResourceManagerBean implements ResourceManager
{
#EJB
private AccessDAO accessDAO;
#EJB
private ResourceDAO resourceDAO;
#EJB
private DepartmentDAO departmentDAO;
(list of methods)
}
Any advice will be greatly appreciated. Thank you.
Here's my first thoughts.
You should have something like
#Remote
public interface ResourceManagerSessionRemote {
(list of methods)
}
Break your remote and local interfaces out
#Stateless(name="ResourceManager", mappedName="ejb/ResourceManagerJNDI")
public class ResourceManagerBean implements ResourceManagerSessionRemote
{
#EJB
private AccessDAO accessDAO;
#EJB
private ResourceDAO resourceDAO;
#EJB
private DepartmentDAO departmentDAO;
(list of methods)
}