Grails-The different dependence Injection ways in grails - grails

What's the difference of different way to inject dependence in grails:
ABCService abcService
def abcService
#Autowired
ABCService ABCService

Expected type is specified, if service with name abcService (or other Spring bean with such name) will have different class, then you'll get ClassCastException here
Just any bean with name abcService
Spring annotation, it's optional. But if you've marked a field but Grails/Spring cannot find such bean it will throw NoSuchBeanDefinitionException (previous two will get null if it doesn't exists) #Autowired could be combined with def type also
Basically Grails services are standard Spring beans, Grails just follows convention over configuration that for every class in services dir it will create a bean with name abcService that could be autowired into other beans. All other job is done by Spring. See also docs for Spring and Grails

Related

CDI failure with Dependent/applicatio Scope class

I am trying to Inject ServletContext in my dependant scope class but it always gives the failure.
java.lang.IllegalStateException: No CXF message usable for JAX-RS #Context injections in that thread so can't use interface javax.servlet.ServletContext
I am not able to undestand the reason that why can't I inject it here. I am using a producer method and when inside producer method,I try to access ServletContext obj then it gives above exception. I have also checked if the Injected servlet context is null but it is not null. But When I call any method using it for example sc.getContextPath() it gives the above exception. Below is the code snippet:
#Dependent
public class AuthContexthandler {
#Context
ServletContext sc;
#Produces
JWTAuthContextInfo getInfo() {
try{
System.out.println(sc.getContextPath()); //here I get the above mentioned error
//rest of the code
}catch(Exception e){
e.printStackTrace();
}
}
}
you must use #inject instead of #Context.
you can use #Context to inject object instances related to the context of HTTP requests into to JAX-RS source class and as AuthContextHandler(as #Christoph Böhme said) is not a JAX-RS source class so you cannot use #Context
but as http://docs.jboss.org/weld/reference/latest/en-US/html_single/ says:
An object bound to a lifecycle context is called a bean. CDI includes
built-in support for several different kinds of bean, including the
following Java EE component types:
managed beans, and EJB session beans. Both managed beans and EJB
session beans may inject other beans. But some other objects, which
are not themselves beans in the sense used here, may also have beans
injected via CDI. In the Java EE platform, the following kinds of
component may have beans injected:
message-driven beans,
interceptors,
servlets,
servlet filters and
servlet event listeners,
JAX-WS service endpoints and handlers,
JAX-RS resources,
providers and javax.ws.rs.core.Application subclasses, and
JSP tag handlers and tag library event listeners.
it means you also can use #Inject annotation in your JAX-RS source class.
there are also some predefined Beans in CDI such as ServletContext that you can use #inject annotation to inject them.
https://docs.jboss.org/seam/3/servlet/latest/reference/en-US/html/injectablerefs.html
https://docs.oracle.com/javaee/7/tutorial/cdi-adv004.htm

Inject ArrayList using RequiredArgsConstructor

I tried to inject List into constructor through lombok RequiredArgsConstructor
#Slf4j
#Component
#RequiredArgsConstructor (onConstructor = #_(#Inject))
public class ClassA {
#NonNull private List<GoodSkill> skills;
......
}
However then have errors:
[tomcat:launchProperties]
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'ClassA' defined in URL
[jar:file:/XXXXX/ClassA.class]: Unsatisfied dependency expressed
through constructor parameter 0; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type java.util.List<\GoodSkill>: expected at least 1
bean which qualifies as autowire candidate. Dependency annotations: {}
It seems there is NO bean of for "List<\GoodSkill>"? I guess there's some special rule when injecting List or other Collections? And as for GoodSkill class, I guess I also should add annotation like #Component?
========
edit:
More weird thing is, I re-build package and now it's no longer complaining find no bean for List<\GoodSkill>, but no bean for GoodSkill. I'm very confused.
Injecting is possible only for managed beans. So, for a list you should have somewhere something like:
#Component
public class GoodSkillList extends ArrayList<GoodSkill>{}
for container to find.
Perhaps you have? If you have many of such beans container/Spring might not be able to decide which to use. In that case you can delimit the possible alternatives many ways for example you could set ClassA to accept only:
#NonNull private GoodSkillList skills;
or alternatively you can research howto inject/autowire by name.

Spring boot #ConditionalOnBean does not detect bean missing, throws exception "No qualifying bean of type"

Have this #Configuration class that requires a bean implementing JmsProperties which is declared in the #ConditionalOnBean
#Configuration
#ConditionalOnBean(JmsProperties.class)
public class JmsConfiguration {
#Inject
private JmsProperties properties;
...
}
Getting exception:
Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [com.....JmsProperties] found for dependency:
Isn't the #ConditionalOnBean supposed to detect this missing bean and not try to inject the dependency in the first place?
Thanks in advance for any pointers
You've cross-posted on the Spring Boot tracker and the developers responded:
#ConditionalOnBean is evaluated after all configuration classes have been processed, i.e you can't use it to make a whole configuration class conditional on the presence of another bean. You can, however, use it where you have to make all of the configuration's beans conditional on the presence of another bean.
You must use #ComponentScan(basePackages="".
Without using it your app wont discover & register/instantiate all defined beans and hence you would end up with this type of exception i.e. No bean def found.

How to access a local interfaces from one project into another within the same ear project

I have a web project that has FacesValidator, this validator needs to access an EJB service to verify if a record exists. Unfortunately, I cannot inject my enterprise beans since the validator is not a managed-bean, so I'm trying to access it via InitialContext. I've tried different combination from http://docs.oracle.com/javaee/6/tutorial/doc/gipjf.html but failed.
What works is this format:
java:global/myProject-ear-1.0.0/myProject/MyService!com.czetsuya.myProject.service.membership.MyService,
My question is can it be simplify? Seems too long.
Thanks,
czetsuya
Look at the server logs. A bit decent EJB container (at least, Glassfish 3 and JBoss 6/7 do), logs all available JNDI names of the EJB during EJB deployment step. Provided that the validator is properly been put in the WAR and the EJB has a #Local interface, then the shortest JNDI name would be the java:app one which should in your case have been java:app/myProject/MyService.
A completely different alternative is to just make the validator a JSF or CDI managed bean instead, so that you can just use the #EJB annotation.
#ManagedBean // Or #Named.
#ApplicationScoped // Provided that the instance doesn't have any state.
public class MyValidator implements Validator {
#EJB
private MyService myService;
// ...
}
and reference it by binding instead of validatorId:
<f:validator binding="#{myValidator}" />
Note that from JSF 2.2 on, you should be able to inject #EJB in a #FacesValidator (and #FacesConverter).
See also:
How to inject in #FacesValidator with #EJB, #PersistenceContext, #Inject, #Autowired

Inject singleton bean into session bean via remote interface, object always "null"

I need to inject a singleton bean into the session bean. Below are the corresponding classes. The problem is that the injected object is always null. I tried all of the JNDI lookup strings which my JBoss 7.0.1 server showed me during startup (i.e. JNDI bindings for session bean named GlobalBean in deployment unit subdeployment .. of deployment .. are as follows: ..). I also tried commenting out the #EJB annotation in GlobalBean.java and also tried to use the "ejb/GlobalBean" during injection. However, no luck. What could be the reason? Thx.
GlobalBean.java:
#Startup
#Singleton
#Remote(GlobalBeanRemote.class)
#EJB(name="ejb/GlobalBean", beanName="GlobalBean", beanInterface=GlobalBeanRemote.class)
#ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class GlobalBean implements GlobalBeanRemote
{
// CODE
}
SessionBean.java:
#Stateful
public class SessionBean extends ParentBean
{
#EJB(name="java:module/GlobalBean!project.framework.interfaces.GlobalBeanRemote")
private GlobalBeanRemote globalBeanAPI3;
// CODE
}
In your SessionBean class try changing name attribute of #EJB to mappedName.
#EJB(mappedName="java:module/GlobalBean!project.framework.interfaces.GlobalBeanRemote")
This will, of course, only work if your two beans are in the same module.
Update
Given that your beans are in separate modules, try using the java:app namespace:
#EJB(mappedName="java:app ...")
The java:app namespace is used to look up local enterprise beans packaged within the same application. That is, the enterprise bean is packaged within an EAR file containing multiple Java EE modules. JNDI addresses using the java:app namespace are of the following form:
java:app[/module name]/enterprise bean name[/interface name]
Also try removing GlobalBean's #EJB annotation. #EJB is used to define a dependency.

Resources