How to use Google Guice to instantiate a class at the start - java

I am implementing a Service Oriented Architecture system. There are some classes in my system that talk to an external API, so there must be some way that we can instantiate these classes when I start my program, so that they don't have to be instantiated every time someone sends a request. I was wondering if Google Guice would have something like that but so far I have found that Google Guice is good for choosing implementation class for an interface, and for by-need instantiation.
To make my question more clearer, let's say ClassAPIUser is the class which calls an external API, and it is the class I would like to instantiate in the beginning (static void main method). And let's say ClassCaller has a field of ClassAPIUser. I would like to find a way so that I can tell my program to fetch the already-instantiated ClassAPIUser from the main method (the entry-point) :
> public class ClassCaller {
>
> private ClassAPIUser classAPIUser;
>
> // Constructor
> public ClassCaller (ClassAPIUser classAPIUser) {
> this.classAPIUser = classAPIUser;
> }
> }
Is there a way I can use Google Guice to let ClassCaller know that classAPIUser is the one instantiated in the static void main method? Also, what should I be specifying in the static void main method and how should I be instantiating ClassAPIUser in the static void main method?

By default, Guice returns a new instance each time it supplies a value. This behaviour is configurable via scopes. Scopes allow you to reuse instances: for the lifetime of an application (#Singleton), a session (#SessionScoped), or a request (#RequestScoped). Guice includes a servlet extension that defines scopes for web apps. Custom scopes can be written for other types of applications.
Singleton is what you want. Take a look at the documentation.

Related

Is there a common pattern to instantiate a library class as a singleton and have the library able to access that instance internally?

Say I have a library project which provides a class MyService.
I'd like clients to be able to instantiate MyService as a singleton and at the same time, I'd like the library to be able to access that singleton internally.
Now I can do the standard MyService.getInstance() sort of thing, but that doesn't lead to a very testable code if my library has MyService.getInstance() calls all over the place.
Perhaps any classes in the library that need an instance of MyService can take in MyService as a constructor parameter:
class MyTestableClass(val myService: MyService) {
// Now this class can be unit tested with a mock/fake MyService
}
But at some higher level in the library I'm still going to have to pass MyService.getInstance() to this class.
Is there a standard pattern to accomplish this? Basically I want the client to be able to instantiate MyService as a singleton and also have the library able to access that instance internally, while having the ability to swap out the singleton instance with a mock/fake for unit testing.
I wouldn't say there is a single standard way of achieving this. But here is a approach I used for some libraries in the past.
In Kotlin one possibility to provide the singleton for you is to make use of the lazy delegate. Alternatively you can use an object instead.
public interface SingletonTarget {}
internal class SingletonClassImpl: SingletonTarget {}
public val mySingleton: SingletonTarget by lazy { SingletonClassImpl () }
// or
public object SingletonObjectImpl: SingletonTarget {}
Both can be combined with constructor injection easily.
public fun interface BookFlight {
operator fun invoke(): Unit
}
internal class BookFlightService(private val service: SingletonTarget): BookFlight { ... }
You can provide instances of your functions using factories. This might also be the right place to "glue" your singleton to the library functions.
public fun BookFlight(): BookFlight =
BookFlightService(mySingleton) // or SingletonObjectImpl

How to use guice injection for an existing singleton class?

I have an existing class named Legacy which is mostly written in old school singleton pattern. Now I want to introduce a new field to it and I would like to use Guice. Legacy itself is not Guice controlled, it is used by another Service class (inside the Service class, it calls the getInstance() of Legacy class to retrieve the Legacy object right now), and that Service class is been created using Guice injector.
public class Legacy {
public synchronized static Legacy getInstance() {
if(sInstance == null) {
sInstance = new Legacy();
}
return sInstance;
}
private Legacy() {
legacyObj = LegacyField.getInstance(); // get a singleton
}
private static Legacy sInstance;
private LegacyField legacyObj;
private NewField newObj; // this is the new dependency I would like to add using Guice
}
What I tried is that I tried to put method Inject into Legacy class
#Inject
public void setNewField(NewField newObj) {
this.newObj = newObj;
}
And in the module file of the Service, I bind the NewField object, but when I run the program, it throwed a NullPointer exception. So the inject doesn't work. Any idea of how to make NewField inject into my program but keep the current old-school singleton paradigm and not changing too much about everything else?
EDIT
There are a least three solutions below and I don't quite know which is the best or are they equivalent.
I just found another solution:
// put in the module
bind(Legacy.class).toInstance(Legacy.getInstance());
In this example, your module itself, not Guice, takes responsibility for obtaining a Legacy instance, then asks Guice to always use this single instance to fulfill all Legacy injection requests.
But according to the javadoc
When the Injector is created, it will automatically perform field and method injection for this instance, but any injectable constructor on Legacy is simply ignored. Note that using this approach results in "eager loading" behavior that you can't control.
Though only slightly cleaner than Thomas's answer, you can configure the injection of your Singleton from within your Module using requestInjection or requestStaticInjection.
// In your Module:
requestInjection(Legacy.getInstance()); // for an instance field, or
requestStaticInjection(Legacy.class); // for a static field.
The docs on the wiki warn about the downsides, though:
This API is not recommended for general use because it suffers many of the same problems as static factories: it's clumsy to test, it makes dependencies opaque, and it relies on global state.
Here is a somewhat hackish solution.
In the bootstrapping of your application,
may be in method public static void main(String[] args),
you should already have code similar to this:
Injector injector = Guice.createInjector(yourModule);
At this place add the following line:
injector.injectMembers(Legacy.getInstance());
By doing so, all the #Injects in your Legacy singleton
should be resolved.
See also the javadoc of Injector.injectMembers.

Initialize a "singleton" by configure file is suitable or not?

Initialize a singleton by configure file is suitable or not?
I notice that the constructor of singleton should not have any parameter, the reason is that if you need use parameters to configure your object, probably that should not be singleton. Seems this sentence very famous, but indeed there are serval cases are special:e.g.
We design a simple distributed system to deal with tons of users' query:
only one central server
n sub servers, each sub server connecting to central server
there is no connections between sub servers
Obviously, we may design the "central server" as singleton, the details like this:
enum ServerType;
abstract class Server;
class CentralServer inherit from Server;(CentralServer is singleton)
class SubServer inherit from Server;
class Query;
... ... ...
But the central server need some configuration, such as:
serverName
description
portNum-ipAddress map
the list of its sub servers
the size of BlockingQueue
... ... ...
How to initialize the central server by these properties?
My current solution:
using the configure file to finish this part job.
I define another class called Configuration.
So the current constructor of central server like this:
class CentralServer extends Server implements Runnable, ....... {
....
....
private static CentralServer _instance;
private CentralServer () {
super();
....
serverName = Configuration.getCentralServerName();
description = Configuration.getCentralServerDescription();
Configuration.initCentralServerPortNumIpMap(portNumIpMap);
Configuration.initCentralServerSubServersList(subServersList);
sizeBlockingQueue = Configuration.initCentralServerBlockingQueueSize();
....
}
public CentralServer getInstance() {
if (_instance == null) {
_instance = new CentralServer();
}
return _instance;
}
....
....
}
The Configuration class, will read and analyze configuration-file, to get out of configuration info.
My Question:
Initialize singleton like this suitable or not, if not, please
give out more suitable approach
I also need configure all sub servers, so seems the Configuration
class is too heavy, should I split the Big Configuration class into
two sub class? class CentralConfiguration, and class
SubConfiguration?
Unfortunately, your implementation for a Singelton is WRONG!! Simply because it is not thread safe.
public CentralServer getInstance() {
if (_instance == null) { // race condition possible here
_instance = new CentralServer();
}
return _instance;
}
Two threads might enter this critical section and evaluate _instance==null to true, and two different instances will be created.
You can simply instantiate your instance statically.
private final static CentralServer INSTANCE = new CentralServer();
public static CentralServer getInstance() {
return INSTANCE;
}
However, the best way to implement singeltons is to use enums
public enum CentralServer { // the best way to implement singletons, due to the author of Effective Java
INSTANCE;
private CentralServer() {
}
}
This gives you serialisation for free.
However, I dont think that you need a singelton at all, singeltons are usually Anti patterns.
Check this out.
In your code, CentralServer has a high dependency on Configuration which I don't think is a good thing, you should see Configuration as a dependency
class CentralServer{
private final Configuration serverConf;
private CentralServer(Configuration serverConf){ // inject configuration
this.serverConf = serverConf;
}
public static CentralServer createCentralServer(Configuration serverConf){ // static factory perhaps
return new CentralServer(serverConf);
}
}
This will give you more flexibility to change or mock configuration. I think Factory pattern would be more appropriate here.
It is perfectly acceptable to make use of external resources during the initialization of your singleton. A common user of the Singleton pattern is loggers and they are almost always configured from external data files.
It does make initialization more complicated but it is not impossible to make a fully tread-safe singleton that accesses external resources such as configuration files. They can even make use of other singletons such as connection pools if their configuration requires database access.
The other answers to this question correctly deal with the actual problems with your singleton initialization.
Initialize singleton like this suitable or not, if not, please give
out more suitable approach:
It is not a suitable approach, because the implementation is not threadsafe yet and it can be broken f.e. via reflection. You should consider reading Effective Java by Joshua Bloch on this topic.
Better would be to create an enum singleton, because this approach is more flexible for later changes, has threadsafe instanciating and is unbreakable.
EDIT: example .
I also need configure all sub servers, so seems the Configuration
class is too heavy, should I split the Big Configuration class into
two sub class? class CentralConfiguration, and class SubConfiguration?
For configuration purposes, there is usually a config.xml file or a config.properties file somewhere to read important preconfigurations. After creating an instance, you should extract the information from such a file and write out necessary changes when shutting down. But as always, many ways lead to rome.

Instantiating objects through reflection in web environment

I need to instantiate few classes through the Java reflection api and invoke 'a' method (method invocation not through reflection) in the instantiated class. I know the reflection do impact the application performance, but I am not very sure how much it hits on the web-environment! Like the Struts framework that instantiates the Action classes using the reflection, my framework too gets the class name as string configured in the file, which I read and instantiate on different requests. How about the idea of having only one instance per class and invoke its method for every requests?
example,
package com.app.events;
public class event1 implements iEvent {
public event1() {
}
public void doprocess(Object info) {
// do necessary events
}
}
package com.app.events;
public class event2 implements iEvent {
public event1() {
}
public void doprocess(Object info) {
// do necessary events
}
}
config.xml
<events>
<event>com.app.events.Event2</event>
<event>com.app.events.Event1</event>
</events>
// servlet init
String clazName = parseXMLFile(); // not every time but only once, I have the bean
Class claz = Class.forName(clazName);
// how about this?
// I save this instance for later requests
events.put(request.getParameter("event"), claz.newInstance());
// later requests,I retrieve the event from the map and invoke its method,
// just a rough code...
events.get(request.getParameter("event")).doprocess(info);
First of all, start by respecting the Java naming conventions. Classes are CamelCased and methods are camelCased.
Using a single instance is perfectly fine. That's what servlets do, as well as Struts1 actions, and Spring beans (by default) for example. But this should be documented, because it forces every implementation of your interface to be thread-safe (preferrably, by being stateless), unless your framework makes sure only one thread uses each instance at a time, which would considerably reduce the performance of your application.
Creating many instances used to be slow, many years ago. It's not anymore now, so I would create a new instance every time, unless having a single instance is important (because initializing an instance might be slow).

How to use eclipse 4 DI in classes that are not attached to the application model?

I have created a OSGI service with declarative services to inject an object that implements an interface. If I inject the object in a class that is attached to the application model (handler,part,....) it is working fine. If I inject it in a class that is not attached to the application model it is always returning null.
Is it possible to use DI in classes that are not attached to the application model? I looked in the vogella tutorials but somehow I don't find a solution.
I know of three ways of how Eclipse 4 can inject objects in your classes:
During start-up the Eclipse runtime looks for relevant annotations in the classes it instantiates.
Objects injected in 1. are tracked and will be re-injected if changed.
Manually triggering injection using the ContextInjectionFactory and IEclipseContext.
What you want may be possible with the third option. Here is a code example:
ManipulateModelhandler man = new ManipulateModelhandler();
//inject the context into an object
//IEclipseContext iEclipseContext was injected into this class
ContextInjectionFactory.inject(man,iEclipseContext);
man.execute();
The problem is, however; that the IEclipseContext already needs to be injected into a class that can access the object that needs injection. Depending on the number of necessary injections, it might be more useful to use delegation instead (testability would be one argument).
#Inject
public void setFoo(Foo foo) {
//Bar is not attached to the e4 Application Model
bar.setFoo(foo);
}
Therefore, a better solution is probably using the #Creatable annotation.
Simply annotate your class, and give it a no-argument constructor.
#Creatable
public class Foo {
public Foo () {}
}
Using #Inject on that type as in the method above, will let Eclipse instantiate and inject it.
The disadvantage is that you cannot control the object creation anymore, as you would with ContextInjectionFactory.inject(..).
I refactored out some part of e(fx)clipse in order to achieve that. Have a look at this. Sorry for the shameless plug...

Categories

Resources