Faker for Grails gives variable not defined error - spring

I have a Grails 2.4.4 application configured with spring-security-core. I want to generate fake users in the BootStrap using the faker plugin. However when I instantiate the bean fakerService in BootStrap and try using it ie. fakerService.firstname(), I get an error :
ERROR context.GrailsContextLoaderListener - Error initializing the application: Cannot invoke method firstName() on null object
Message: Cannot invoke method firstName() on null object
I'm just a beginner in Grails. Am I doing the Dependency Injection wrong?
http://pasteboard.co/rvbihRU.png

Yes you are :)
A little background. When you add a class-scope variable (a field) in a Groovy class without an explicit scope modifier (e.g. public, private, protected) it defaults to public just like classes and methods. But it is considered a property in the JavaBean sense, so the Groovy compiler creates a getter and a setter for you based on the name. So if you declare def foo and String bar (it doesn't matter whether you specify the type) you'll get Object getFoo(), void setFoo(Object), String getBar(), and void setBar(String) methods (you should decompile a POGO class with a decompiler and see this for yourself - it's pretty cool stuff - I recommend JD-GUI, but use whatever you prefer). If you had declared any of them already Groovy would skip that one and not overwrite yours. This is cool because you can treat the variable like a simple public field, but at any time add getter and/or setter logic and not affect calling clients (Groovy or Java, since the Java classes would have been calling the getter and setter all along, and Groovy calls the getter and setter for you when you read or write a property).
So why am I babbling on about this? Dependency injection is done by Spring - you're injecting Spring beans. There are various ways to do this, but the default in Grails is to use autoinject-by-name. So for any bean registered in the ApplicationContext and special classes like BootStrap, integration tests, etc., Spring scans the methods looking for setters. It strips off "set" and lowercases the next letter, and that's the "property" name of the setter. If there's a bean with that name in the ApplicationContext, Spring will call that setter, passing the bean with that name, and if the types are in sync, your class will have a reference to that bean.
You added a local variable. Nothing special happens to local variables, and Spring doesn't see them, and they're not candidates for dependency injection. Move the declaration to class scope, before the init closure, e.g.
class BootStrap {
def fakerService
def init = {
...
}
}
and the Groovy compiler will add a getFakerService method that isn't of much interest, but also a setFakerService method that Spring will see. It will determine that its property name is "fakerService", see that there is a bean with that name, and call the setter. This all happens before Grails calls the init closure, so at that point the value will be a non-null FakerService eagerly awaiting your calls.

Related

Spring Boot application.properties appear unregistered when accessed from constructor

This is the code that I have:
#Component
#Configuration
#PropertySource("application.properties")
public class Program {
#Value("${app.title}")
private String appTitle;
public Program() {
System.out.println(appTitle);
}
}
The application.properties has
app.title=The Program
The output is null insteaf of The Program.
So, what am I missing? I have tried several examples; none worked.
Since appTitle is an autowired field, it is not set until after the object is initially constructed. This is why the value is still null in your example. The bean construction process in this scenario is as follows:
The Program constructor is called, creating a new Program instance
The appTitle field is set on the newly constructed bean to ${app.title}
The ideal fix for this depends on your goals. If you truly need the value within the constructor, you can pass it in as an autowired constructor parameter. The value will then be available within the constructor:
#Component
#Configuration
#PropertySource("application.properties")
public class Program {
public Program(#Value("${app.title}") appTitle) {
System.out.println(appTitle);
}
}
If you don't need it in the constructor itself, but need it for the proper initialization of the bean, you could alternatively use the #javax.annotation.PostConstruct annotation to make use of it after the object's construction but before it is made available for use elsewhere:
#Component
#Configuration
#PropertySource("application.properties")
public class Program {
#Value("${app.title}")
private String appTitle;
#PostConstruct
public void printAppTitle() {
System.out.println(appTitle);
}
}
Finally, if you don't need the value at construction time, but need it during the life of the bean, what you have will work; it just won't be available within the body of the constructor itself:
#Component
#Configuration
#PropertySource("application.properties")
public class Program {
#Value("${app.title}")
private String appTitle;
}
Nothing wrong, just don't do it in a constructor...
Other answers on this question are written assuming the goal is creating a Spring-managed bean that uses the given property in its creation. However, based on your comments in another answer, it looks like the question you want answered is how to access an externalized property (one provided by #Value) within a no-argument constructor. This is based on your expectation that a Java inversion of control (IoC) container such as Spring should allow accessing externalized properties (and presumably other dependencies) within a no-argument constructor. That being the case, this answer will address the specific question of accessing the property within a no-argument constructor.
While there are certainly ways this goal could be achieved, none of them would be idiomatic usage of the Spring framework. As you discovered, autowired fields (i.e. fields initialized using setter injection) cannot be accessed within the constructor.
There are two parts to explaining why this is. First, why does it work the way it does, programmatically? Second, why was it designed the way it was?
The setter-based dependency injection section of the Spring docs addresses the first question:
Setter-based DI is accomplished by the container calling setter methods on your beans after invoking a no-argument constructor or a no-argument static factory method to instantiate your bean.
In this case, it means that first the object is created using the no-argument constructor. Second, once the object is constructed, the appTitle is initialized on the constructed bean. Since the field isn't initialized until after the object is constructed, it will have its default value of null within the constructor.
The second question is why Spring is designed this way, rather than somehow having access to the property within the constructor. The constructor-based or setter-based DI? sidebar within the Spring documentation makes it clear that constructor arguments are in fact the idiomatic approach when dealing with mandatory dependencies in general.
Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies. [...]
The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null. Furthermore, constructor-injected components are always returned to the client (calling) code in a fully initialized state. [...]
Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. [...]
A property needed to construct the object certainly would be categorized as a mandatory dependency. Therefore, idiomatic Spring usage would be to pass in this required value in the constructor.
So in summary, trying to access an application property within a no-argument constructor is not supported by the Spring framework, and in fact runs contrary to the recommended use of the framework.

Kotlin instance variable is null when accessed by Spring proxied class

I have a service class that is being proxied by Spring, like so:
#Service
#Transactional
open class MyService { ... }
If I remove the open modifier, Spring complains that it needs to proxy the class to apply the #Transactional annotation tweaks.
However, this is causing issues when calling a function on the proxied service, which attempts to access a variable:
#Service
#Transactional
open class MyService {
protected val internalVariable = ...
fun doWork() {
internalVariable.execute() // NullPointerException
}
}
The internalVariable is assigned as part of its declaration, does not have any annotations (like #Autowired, etc.), and works fine when I remove the #Transactional annotation and the requirement for Spring to proxy the class.
Why is this variable null when Spring is proxying/subclassing my service class?
I hit a similar issue and the above comments by Rafal G & Craig Otis helped me-- so I'd like to propose that the following write up be accepted as an answer (or the comments above be changed to an answer and they be accepted).
The solution: open the method/field.
(I hit a similar case where it was a closed method that caused the problem. But whether it is a field/method the solution is the same, and I think the general cause is the same...)
Explanation:
Why this is the solution is more complicated and definitely has to do with Spring AOP, final fields/methods, CGLIB proxies, and how Spring+CGLIB attempts to deal with final methods (or fields).
Spring uses proxies to represent certain objects to handle certain concerns dealt with by Aspect Oriented Programming. This happens with services & controllers (especially when #Transactional or other advice is given that requires AOP solutions).
So a Proxy/Wrapper is needed with these beans, and Spring has 2 choices-- but only CGLIB is available when the parent class is not an interface.
When using CGLIB to proxy classes Spring will create a subclass called
something like myService$EnhancerByCGLIB. This enhanced class will
override some if not all of your business methods to apply
cross-cutting concerns around your actual code.
Here comes the real surprise. This extra subclass does not call super
methods of the base class. Instead it creates second instance of
myService and delegates to it. This means you have two objects now:
your real object and CGLIB enhanced object pointing to (wrapping) it.
From: spring singleton bean fields are not populated
Referenced By: Spring AOP CGLIB proxy's field is null
In Kotlin, classes & methods are final unless explicitly opened.
The magic of how Spring/CGLib when & how chooses to wrap a Bean in an EnhancerByCGLIB with a target delegate (so that it can use finalized methods/fields) I don't know. For my case, however the debugger showed me the 2 different structures. When the parent methods are open, it does not create a delegate (using subclassing instead) and works without NPE. However, when a particular methods is closed then for that closed method Spring/CGLIB uses a wrapped object with delegation to a properly initialized target delegate. For some reason, the actual invocation of the method is done with the context being the wrapper with its uninitialized field values (NULLs), causing NPE. (Had the method on the actual target/delegate been called, there should not have been a problem).
Craig was able to solve the problem by opening the property (not the method)-- which I suspect had a similar effect of allowing Spring/CGLib to either not use a delegate, or to somehow use the delegate correctly.

Grails - Best Way to Access Beans in Normal Groovy Classes

I'm trying to inject an existing bean into a Groovy class and I know Grails bean injection doesn't work for normal Groovy classes (in src/groovy folder). I can get access to a bean via
Holders.applicationContext.getBean('beanName')
However, I'm wondering if this is the best approach (from a execution speed and memory usage point of view). I will be calling a bean from a method that's called hundreds of times during the normal use of the application and I'm wondering if there might be a better approach. At the very least, should I be storing the bean reference (maybe in the constructor) so that I don't call the above code over and over again? Could I store a static reference to the bean so that each class doesn't have to store its own? Any other suggestions or improvements?
Your Groovy (or Java) class cannot use dependency injection, but it is very likely called directly or indirectly from a class that can, e.g. a controller or a service. Rather than having this class pull in its dependencies (which runs pretty strongly against the ideas of dependency injection and inversion of control), pass into the class the beans that it needs, or at a minimum the ApplicationContext if the beans aren't always known up front.
So for example rather than doing this in your service (where Thing is your src/groovy class):
def someServiceMethod(...) {
def thing = new Thing()
thing.doSomething(42, true)
}
add a dependency injection for the bean it needs in the service and pass it along with the other args, either in the constructor or in individual methods, e.g.
class MyService {
def someBean
def someServiceMethod(...) {
def thing = new Thing(someBean)
thing.doSomething(42, true)
}
}
Groovy classes in src/groovy are not picked up for dependency injection by default. But you can configure them manually by adding a bean definition to conf/spring/resources.groovy:
import your.class.from.src.groovy.MyBean
beans = {
myBean(MyBean)
}
Using this way you can configure how dependencies should be resolved.
You can do this manual, e.g.
myBean(MyBean) {
myService = ref('myService') // assumes you have a MyService bean that can be injected to the `myService` field
}
Or you can use autowiring (what grails does by default for services/controllers):
myBean(MyBean) { bean ->
bean.autowire = 'byName'
}
By adding beans to resources.groovy you can also inject these beans into services and controllers.
For more details see the Spring section in the Grails documentation

What does the #Value annotation in method do?

I see one method annotated with #Value("${some.property}")
as in
#Value("${some.property}")
public void setSomething(String param) {
... do something with param
}
What is that annotation doing there?
Basically it tells Spring's AutowiredAnnotationBeanPostProcessor to call the setSomething method with the resolved value of some.property as the argument... but only if you have a PropertySourcesPlaceholderConfigurer in your bean definitions; if you haven't configured one the post processor will only inject the string "${some.property}"(without quotes) to your method.
An IllegalArgumentException will be thrown if the value could not be resolved unless you have used a default e.g. "${some.property:default}".
Spring resolves these values using the current Environment and its PropertySources e.g. JVM system properties, a Java properties file, etc.
Also you may use Spring Expression Language (SpEL) to resolve things like #{someBean.someMethod} or #{systemProperties[user.region]}
Sidenote: As the documentation states
Fields are injected right after construction of a bean, before any
config methods are invoked. [...] Bean property setter methods [as in this case] are effectively just a special case of such a general config method.
A common mistake is to try to execute some logic in your constructor using the value injected but at this moment the value has not be resolved nor injected because the constructor must finish in order to inject the value in the config method. In these cases you have to use the #Value or #Autowired annotations in your constructor arguments.
You may also use #PostConstruct or the XML init-method attribute pointing to a method that will be executed after the bean properties have been set. Alternatively you can implement the InitializingBean interface.

Implementation of "Context.getApplicationContext().getBean"

Can anyone explain what happens when we call
ApplicationContext.getApplicationContext().getBean(abcclassName.class)
being the abcclassName being an abstract class.
I understand that an abstract class cannot be instantiated. Then how does this work?
I have never done this with Abstract Classes, but with Interfaces.
What it will do is to get the instance of the subclass defined in your context. In other words if you have a bean of the class Cat (subclass of Animal) defined in your context and you use the class Animal to pass to your ApplicationContext.getBean(). You will get the Cat back.
If you have more than one subclass in your context, it will throw an exception though.
See this for reference: http://docs.spring.io/spring/docs/3.0.x/api/org/springframework/beans/factory/BeanFactory.html#getBean%28java.lang.Class%29
Looking through the source code for DefaultListableBeanFactory -- source -- should answer your question. (Both links are for version 3.0.x, as that is what I found with GrepCode. I imagine that not much has changed in terms of finding the matching beans by a type)
Basically, it takes the class, and looks for Beans in the ApplicationContext that are assignable to the provided type.
The method AbstractBeanFactory#isTypeMatch(String, Class<?>) contains the code that will be of most interest to you, and there is a path that reaches it via the DefulatListableBeanFactory#getBean(Class<?>) method.
After going through Source code Spring 3.0.5 , when you do ApplicationContext.getApplicationContext().getBean(abcclassName.class) on abstract class and if the abstract class is not configured as #component then the AbstractBeanFactory calls the isTypematch method to get the Correct Entity .
Basically it takes all beans ( which ever initiated in context) and iterate one by one and will check that bean is factory for requested or the bean can be assignable for the requested.
if only one bean resolved using that type then it returns that bean if its found multiple beans then it returned error .
return !BeanFactoryUtils.isFactoryDereference(name) &&
typeToMatch.isAssignableFrom(beanInstance.getClass());
The typeToMatch.isAssignableFrom(beanInstance.getClass()); call use Native method in Object class public native boolean isAssignableFrom(Class<?> cls); to check

Resources