Instantiating variables in Controller on start of application using Play Framework - java

I am using Java through the Play Framework to implement an API. I am trying to instantiate a few variables on the start of the application that should last for the entire life of the application and that are to be used in my HomeController.
These variables are objects that can be used to call functions from a specific class.
I have read that the best way to implement code that executes on the start of the application is to use Dependency Injection but I did not understand how to do it.
Can you please clarify how this is done?
Thank you.

The example on Dependency Injection uses Google Guice. The first is to include that dependency on the build.sbt file.
you can do that by adding
// https://mvnrepository.com/artifact/com.google.inject/guice
libraryDependencies += "com.google.inject" % "guice" % "4.1.0"
You can then choose to extend GlobalSettings (https://www.playframework.com/documentation/2.5.x/GlobalSettings) and choose to inject a Guice injector
An example of the implementation is here : https://dzone.com/articles/guicing-play-framework
Hope it helps

You can find here and here more examples of dependency injection in Play.
After you got the idea, it should be easy to implement.
To define an object, that should last for the application entire lifecycle:
Define the class (of such object) with #Singleton annotation:
#Singleton
public class MyClass4AppLifecycle {
public MyClass4AppLifecycle() {
...
}
....
}
Add to the controller a data member with #Inject annotation:
public class MyController extends Controller {
#Inject
private MyClass4AppLifecycle myGlobalObject;
...
Note: since you mentioned several objects, member inject annotation seems more appropriate, that a constructor annotation.
Register you class for dependency injection in the default module (it is the simplest way):
public class Module extends AbstractModule {
#Override
protected void configure() {
bind(MyClass4AppLifecycle.class).asEagerSingleton();
}
}
Repeat the three above for each type you need to have globally

Related

Java EE CDI - obtaining a new instance of a class each time a method is called

I am looking to do some refactoring of a Java J2EE application, but I am not clear how to have CDI provide the needed dependencies:
The current setup is quite simple/easy to understand:
#ApplicationScoped
public class MyApplication {
#Inject
#Named("Default")
private Dependency dependency;
public void dostuff(){
dependency.process();
}
}
I now need a new instance of dependency each time I call dostuff.
I am unclear on how to use CDI to create this for me. My Dependency has its own dependencies that I would like CDI to create for me.
I expect there is a layer of indirection I need to add.
Additional context:
This class is part of a process that polls for work to be done, and is hosted in Wildfly.
We are not using Spring in the project.
Since what you desire is having a new instance of Dependency, each time the method is called, I think what you need is an instance of Provider that is (javax.inject.Provider<T>) injected in your class/bean.
Inject the provider to your current class:
#Inject Provider<DesiredBean> provider;
Then, in your method doStuff() obtain the new instance:
DesiredBean desiredBean = provider.get();
This should get you going.
Is there a specific reason you need to use CDI besides the dependency injection?
If not, I'd suggest making doStuff() take a Dependency object as a parameter:
public void doStuff(Dependency dependency) {
dependency.process();
}
Then, when you call the method, you provide it with a new instance of Dependency:
myApplication.doStuff(new Dependency());
That way, you are still keeping your class less coupled than declaring a new instance in the constructor or field.

Guice How to inject dependencies to an object instantiated from a dynamically loaded class

I want to load a plugin which is dependent to some features of my application.
I can create an instance of the entry class. Bu I cannot inject required dependencies to it.
For example lets assume that I have class in the plugin like that:
class ThirdPartyService implements Service {
//no argument constructor and overridden methods
//Inject database config which is known by application to the service:
#Inject
void setDatabaseConfig(DatabaseConfig dbConfig) {
this.dbConfig = dbConfig;
}
}
The guice modules in the application don't know ThirdParyService. Because it is a dynamically loaded class. So I cannot bind Service to this class. Is there any way to inject DatabaseConfig to a ThirdParyService instance?
Note: I don't want to load the plugins at the beginning of the application. Instead, I want to load plugins at runtime.
Use injector.injectMembers()
This will call the setter injection

Can Spring add a bean to context based on class (name) and inject it?

I have a Spring application consisting of multiple modules. One of these modules requires certain Spring beans to be present in the context (it cannot run standalone as it does not have a complete context itself).
This module provides basic functionality that needs to be shared amongst many applications that customize this module by making the correct beans available (singleton or request scoped, depending on needs).
This works perfectly and we're very happy with this setup as it provides a seperation between core functionality and business specific logic.
My question is now, I have a class that can optionally be used to satisfy one of the depedencies. It is not annotated with #Component to prevent it being scanned, however I would like the projects to be able to choose to use this class or supply their own implementation.
The core module looks like this:
public interface AProvider;
#Component
public class AService {
#Inject private AProvider aProvider;
}
And it provides this implementation that can optionally be used:
public class DatabaseBasedAProvider implements AProvider {
#Inject private SomeOtherDependency dependency; // <-- this needs to be injected still if used!
}
An example project that uses the core module then must make sure that one bean of type AProvider is present on the context. This can be achieved like:
#Configuration
public class Configuration {
#Bean
AProvider getAProvider() {
return new OurOwnAProviderImplementation();
}
}
What I would like though is something like:
#BeanClass // <-- some annotation I made up
Class<AProvider> getAProviderClass() {
return DatabaseBasedAProvider.class; // <-- have spring inject this!
}
What I don't want is:
#Bean
AProvider getAProvider() {
return new DatabaseBasedAProvider( ... add dependencies here myself ... );
}
I have solved a case similar to yours (if I understand correctly), using the #Primary annotation. Might be something for you.
public interface AProvider { }
For every module to have some implementation of the interface, create a default implementation that is shared.
#Service
public class DefaultAProvider implements AProvider {}
Then, if some module wishes to use its own implementation, "override" the bean using #Primary.
#Primary
#Service
public class MyVerySpecialAProvider implements AProvider {}
Then, anytime you inject AProvider, Spring will pick the #Primary implementation.
An alternative will be to use #Profile, another alternative would be to annotate your AProvider classes with #Component in combination with #ConditionalOnProperty and document the different choices to your consumers.
Example
#Component
#ConditionalOnProperty(name = "my.aprovider.choice", havingValue = "database")
public class DatabaseBasedAProvider implements AProvider {
#Inject private SomeOtherDependency dependency; // <-- this needs to be injected still if used!
}
I've found a solution that allows me to decide at the client what class I want to use for AProvider.
It is not super nice, but it does mean I don't need to make specific changes to the code in the core module (as this module is supposed to be generic).
In a #Configuration class in the client's config I'm now doing this:
#Component
static class MyDatabaseBasedAProvider extends DatabaseBasedAProvider {
// No implementation
}
This makes Spring construct the class and handle all the injections. It could be shorter and it does require the class to be non-final but it works.
The client is now alerted if the bean is missing, is free to make their own implementation and free to pick one of the existing implementations if one suits their needs, without the core module having to decide before hand how AProvider might be supplied.

Wicket #SpringBean and Spring #Autowired with injection via constructor

I have a Wicket panel in which I want to inject bean using #SpringBean
public class SomePanel extends Panel {
#SpringBean
private BlogSummaryMailGenerator blogSummaryMailGenerator;
}
But this BlogSummaryMailGenerator has injection via constructor defined like this:
#Component
public class BlogSummaryMailGenerator {
private BlogRepository blogRepository;
private BlogPostRepository blogPostRepository;
#Autowired
public BlogSummaryMailGenerator(BlogRepository blogRepository,
BlogPostRepository blogPostRepository) {
this.blogRepository = blogRepository;
this.blogPostRepository = blogPostRepository;
}
}
And when SomePanel is instantiated I am getting an exception
Caused by: java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
at net.sf.cglib.proxy.Enhancer.emitConstructors(Enhancer.java:721) ~[cglib-3.1.jar:na]
at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:499) ~[cglib-3.1.jar:na]
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25) ~[cglib-3.1.jar:na]
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216) ~[cglib-3.1.jar:na]
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377) ~[cglib-3.1.jar:na]
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285) ~[cglib-3.1.jar:na]
at org.apache.wicket.proxy.LazyInitProxyFactory.createProxy(LazyInitProxyFactory.java:191) ~[wicket-ioc-7.2.0.jar:7.2.0]
Adding empty no-args constructor to the BlogSummaryMailGenerator solves this issue but adding such code only to make injection work is wrong and I would like to avoid it.
Any suggestions how to make #SpringBean work with beans using injection via constructor?
The real problem is in CGLIB. It requires a default constructor to be able to create the proxy instance. The real Spring bean is created separately by Spring and has no such restrictions. The default constructor needed by CGLIB could be even private as far as I remember.
Update: Since Wicket 9.5.0 Wicket could also use ByteBuddy instead of CGLib.
Another solution is to use an interface for this bean. Then Wicket will use JDK Proxy instead of CGLIB and in this case there is no need of default constructor in the implementation.
Solution
To be able to take advantage of constructor injection for #SpringBean in Wicket components you just have to add Objenesis to your compile time dependencies.
Explanation
Objenesis is a little and less known byte code manipulation library which (in opposite to CGLIB provided together with Wicket) is able to create a proxy object for a class which has no default (no args) constructor. If you add it as a compile dependency to your project then Wicket will switch it's internal lazily initializable proxy creation logic to take advantage of Objenesis (instead CGLIB which requires no args constructor) while instantiating a proxy. Unfortunately this feature is not documented but I can confirm it works in my case.
The error message is pretty clear. Wicked trying to create instance of proxy class for BlogSummaryMailGenerator with CGLIB library. Since you didn't (or you can't) provide arguments to constructor, it looking for contstructor with no arguments. But it can't, and you get error.
Just replace constructor injection with property injection, and create no argument constructor:
#Component
public class BlogSummaryMailGenerator {
#Autowired
private BlogRepository blogRepository;
#Autowired
private BlogPostRepository blogPostRepository;
public BlogSummaryMailGenerator() {}
}
Actually, you do not need to declare an empty constructor. I did it just for clarity. Note, that BlogRepository and BlogPostRepository should be declared as beans (marked with #Component annotation, or created as #Bean in Spring configuration).
UPDATE:
When you add SpringComponentInjector in your WebApplication.init(), you can specify false for third paramter, which means 'wrapInProxies'. Wicket will never wrap Spring beans in porxy, and you can use #Autowired for constructors.
#Override
public void init()
{
super.init();
AnnotationConfigApplicationContext springContext =
new AnnotationConfigApplicationContext();
springContext.register(SpringConfig.class);
springContext.refresh();
getComponentInstantiationListeners().add(new SpringComponentInjector(this,
springContext, false));
}
The correct way to solve this is not to add Objenesis to your project, but to inject interfaces instead of concrete implementations, as #martin-g already explained (of course, we do not always have the privilege to be able to do the right thing, but when we do, we should do it).
I have a project that started to give the exact same error and stack after a library update I still don't exactly understand (complete Maven dependency hell, I inherited it, go easy on me). The reason was that I was creating a Spring request-scoped bean from a concrete subclass of ListModel<MyClass> and Wicket was hell bent on wrapping that class into a lazy loaded proxy, which it couldn't do because there was no zero-args-constructor.
I fixed it by changing the configuration class to create a named instance of IModel<List<MyClass>> and by defining the injected dependency using the name.
In the configuration class:
#Bean(name = "namedModel")
#RequestScope
public IModel<List<MyClass>> myObjectList() {
return new MyClass(parameters);
}
In the component:
#Inject
#Named("namedModel")
private IModel<List<MyClass>> myModel;

How do you make dynamic bindings in Guice that require an injected Instance?

I'd like to create a Module that dynamically binds instances to named annotations. The use case is I would like to automatically bind the values in my configuration with the key in the properties file being the #Named value.
However the configuration is bound in a different module so I need the config to be injected. Solutions I've looked at are:
Binding in the configure() method.
This method is not injected into and I can not get the base configuration.
Using a Provider/#Provides.
Providers only bind a single instance.
Using MultiBinder.
My use case is a little different then what is provided by this extension. Multi-binding allows you to bind multiple instances separately and then have them injected as a Collection more complex containing type. I would like to bind each instance separately and have them by uniquely identifiable for injection latter.
Use a childInjector.
Unfortunately this isn't possible without some extensive modification of existing code. This answer is a very good description of how to solve this problem this way though.
Inject the binder somehow. (I started getting a little hackier)
Guice allows injecting the Injector for latter use, I tried injecting the Binder into the Module though a #Provides method and then using the binder directly to make multiple binds within the method. Guice would not inject the binder.
Remember that all of the configure methods configure all of the bindings in an Injector before any injection can happen. That said, a few things:
Binding #Named properties to the contents of a single Properties instance is so useful, there's a Names.bindProperties(...) method that does it automatically for you. The only trick is that you need to have the Properties instance at the time configure() is run.
If they're all available at the same time, don't worry about binding the properties in one module and binding the application in another. As long as they all go into the same Injector, Guice will combine them all and let them satisfy each others' dependencies.
Providers can return different instances, and usually do--but you're right that it won't help you differentiate between keys. If injecting the Properties instance directly is too ugly, consider making a lightweight factory instead:
public class ConfigOracle {
#Inject private Properties properties;
public String getAsString(String key) { ... }
public int getAsInt(String key) { ... }
}
public class SomeConfigUser {
#Inject private ConfigOracle configOracle;
public void doStuff() {
doStuffBasedOn(configOracle.getAsString("my.properties.key"));
}
}
You should never need to inject a Binder (or anything else) into a Module.
If you implement Module, the binder will be a parameter of configure(). If you extend AbstractModule as you should, just call the binder() method.
You can pass in dependencies through constructor arguments to the Module, if need be, which (as far as I'm concerned) is the only way Modules should vary the bindings they create.
There's no reason you couldn't create a Module through an Injector, but you'd have to have an Injector first, and it sounds like you're trying to get away with only having one.
If you need other instances from the Injector you can always write a Provider implementation with #Inject fields/methods/constructors, or even take in parameters in a #Provides method (which will be filled in with dependencies automatically).
Overall I still favor the child injector approach (thanks for the link and compliment to my previous answer!), which fits your "dynamic bindings based on an injected instance" description the best, and would literally be this simple:
class PropertiesModule extends AbstractModule {
Properties properties;
PropertiesModule(Properties properties) {
this.properties = properties;
}
#Override public void configure() {
Names.bindProperties(binder(), properties);
}
}
Injector oldInjector = Guice.createInjector(allYourOtherModules);
Module myModule = new PropertiesModule(oldInjector.get(Properties.class));
Injector injector = oldInjector.createChildInjector(myModule);

Categories