Inject a different Spring bean depending on a target class - java

Say I have this:
interface Something {
}
interface Fetcher {
}
class FetcherImpl implements Fetcher {
private final Class<?> klass;
public FetcherImpl(Class<?> klass) {
this.klass = klass;
}
public Something fetch() {
// Fetch an instance Something depending on the klass
}
}
class ClassA {
private final Fetcher fetcher;
public ClassA(Fetcher fetcher) {
this.fetcher = fetcher;
}
public void someMethod() {
// ...
Something something = fetcher.fetch();
// ...
}
}
class ClassB {
private final Fetcher fetcher;
public ClassB(Fetcher fetcher) {
this.fetcher = fetcher;
}
public void someMethod() {
// ...
Something something = fetcher.fetch();
// ...
}
}
So, the idea is:
I have an data class, Something
I have a fetcher for that data class, Fetcher, that fetches it depending on the class. For example, it creates it depending on the contents of the file from the path /tmp/<class-name>.txt
There are a lot of classes that are using (their respective instance of) the fetcher, ClassA and ClassB in the above example
Some important points:
All clients of the fetcher are doing constructor injection, i.e. using a final field to store the fetcher. Thus bean post processors cannot be used
The set of classes using the fetcher is an open one
The creation of the fetcher instances should not be manually configured. I.e. when adding a class ClassC above that uses its own instance of the fetcher similar to ClassA and ClassB, there should not be additional Spring configuration for that particular class
Some real world examples of a similar pattern:
Loggers, e.g. instead of using
final Logger logger = LoggerFactory.getLogger(this.getClass())
the logger would be injected via the constructor
Cache implementations (i.e. get a cache for a specific class)
DAO objects (i.e. get a DAO for a particular bean, provided it can be generic enough)
Is this possible using Spring? If so, can you please provide some pointers or similar examples that I can read through? I am using Java configuration for Spring if that matters.

Related

Passing one instance of an object to different classes without using static or singleton

I am trying to figure out a way to pass one instance of the same class to multiple classes so I am able to build an object. The problem is it cannot be static or use singleton because many users will be hitting the application at the same time and I may run into other issues. Are there any design patterns that would work best with this scenario or if there is some way to use global variables in java? I am trying implement this with an existing rest service that was not designed very well.
public class OneInstanceOf
{//I want to build this map object without static
private Map<String, String> mapIwantToBuild = new HaspMap<String, String>();
public void methodIwantToCall(String name, String value)
{mapIwantToBuild.put(name, value)
}
The common pattern for you task is dependency injection. You can use spring framework for that task.
1.Create configuration with your bean:
#Configuration
public class YourConfiguration {
#Bean
public OneInstanceOf oneInstanceOf {
return new OneInstanceOf();
}
}
2.Inject your bean whatever you want (simplest - use autowiring):
#Component
public class Client1 {
#Autowire
private OneInstanceOf oneInstanceOf;
public void someMethod() {
oneInstanceOf.methodIwantToCall();
}
}
Spring will insure single instance of oneInstanceOf will be injected in all clients.
U can create a setter with parameter of instance class variable, in every class in which you want to pass the instance. Then create a method in one of the classes that calls setter of all those classes and pass parameter instance as parameter to that method.
Like below.
class A{
B b = new B;
set(B b){
C.setB(b);
D.setB(b);
E.setB(b);
}
}

Guice inject based on scope

In my scenario I have a BaseObject which is an interface and then a BaseObjectImpl.
Then I have two clients, ClientA and ClientB which both reference BaseObjectImpl with the minor different being that the constructor argument to BaseObjectImpl should change depending on which client is using it. The setup looks like this:
BaseObject:
public interface BaseObject {
void doAction();
}
BaseObjectImpl:
public class BaseObjectImpl implements BaseObject {
#Inject
public BaseObjectImpl(RandomInjectedObject random, String inputString) {
this.inputString = inputString;
}
public void doAction() {
// print input string
}
Now for the clients:
ClientA:
public class ClientA {
#Inject
public ClientA(BaseObject baseObject) {
this.baseObject = baseObject;
}
ClientB:
public class ClientB {
#Inject
public ClientB(BaseObject baseObject) {
this.baseObject = baseObject;
}
Now the issue is that when inside my ClientAModule I want to provide the inputString argument such that it is set to clientAString and inside ClientBModule I want to provide clientBString instead.
What is the best way to go about doing this? Note that the BaseObjectImpl takes in two arguments (the other one has the same definition for both clients).
What I tried doing was inside the BaseObjectModule class that I have defined, I created a Builder inside which I could set a specific annotation and set a specific inputString. Then inside my Client<AB>Module I created a different BindingAnnotation in each of them. Then when I installed the BaseObjectModule I did so using the builder and each passed in their specific BindingAnnotation and inputString.
Then I try to bind the BindingAnnotation / inputString scope to a Provider for BaseObject is that I try to instantiate the BaseObjectImpl with the corresponding inputString and the injected RandomInjectedObject which I've provided also in the BaseObjectModule. I get an error saying:
This Provider cannot be used until the Injector has been created because I haven't created the injector inside the module itself.
I was looking at AssistedInjection so that I could make it so I just passed in the inputString at this time, but the problem is I still need the injector for that.

Guice: instantiating a singleton before creating the module

Is it possible to instantiate and assign a singleton to a reference with Guice before creating the Module and pass that instance to the Module constructor be bound during configuration?
Here is an example of what I mean:
I have a method that allows me to create objects depending on a custom implementation of an interface which is being passed in constructor as an Optional (if the user won't provide a custom implementation, we will use the default one), which is being done by binding the interface to that particular implementation in the Module class. :
public static MyClass createMyClassObject(Optional<SpecialInterface> customSpecialInterfaceObject) {
SpecialInterface specialInterfacebject;
if(customSpecialInterfaceObject.isPresent() {
specialInterfaceObject = customSpecialInterfaceObject.get()
} else {
/* here I would like to bind it to an instance of the DefaultSpecialInterfaceObject but can't really do something like:
Injector injector = Guice.createInjector(myClassModule);
DefaultSpecialInterface instance = injector.getInstance(DefaultSpecialInterface.class);
as the module is yet to be created */
}
MyClassModule myClassModule = new MyClassModule(specialInterfaceObject);
Injector injector = Guice.createInjector(myClassModule);
return injector.getInstance(MyClass.class);
}
I'm currently using classes instead of instances to solve this problem, such as in the example below, but I don't quite like this solution. Would be happy to see a better way of doing it:
private static Class resolveSpecialInterfaceObject(Optional<SpecialInterface> customSpecialInterfaceObject) {
Class specialInterfaceObjectClass;
if (customSpecialInterfaceObject.isPresent()) {
specialInterfaceObjectClass= customSpecialInterfaceObject.get().getClass();
} else {
specialInterfaceObjectClass = DefaultSpecialInterface.class;
}
return specialInterfaceObjectClass;
}
public abstract class MyClassModule extends AbstractModule {
private final Class<SpecialInterface> specialInterfaceObjectClass;
public MyClassModule(Class<SpecialInterface> specialInterfaceObjectClass) {
this.specialInterfaceObjectClass= specialIntefaceObjectClass;
}
#Override
protected void configure() {
bind(SpecialInterface.class).to(specialInterfaceObjectClass);
}
}
Edit, from a comment below:
one more thing- didn't want to make the question too long; actually, I also want to perform another operation on the resulting instance of SpecialInterface, but only if it is the instance of DefaultSpecialInterface and I don't think it should be done in the Module. I was thinking if I could just have this bean up and running before, such as in Spring, so I could just pass it to the Module, but also use it in another method call before?
Can you take the whole Optional and use bind(...).toInstance(...)?
public static MyClass createMyClassObject(
Optional<SpecialInterface> customSpecialInterfaceObject) {
MyClassModule myClassModule = new MyClassModule(customSpecialInterfaceObject);
Injector injector = Guice.createInjector(myClassModule);
MyClassFactory instance = injector.getInstance(MyClassFactory.class);
return instance.createMyClassObject();
}
class MyClassModule extends AbstractModule {
private final Optional<SpecialInterface> customObject;
MyClassModule(Optional<SpecialInterface> customObject) {
this.customObject = customObject;
}
#Override public void configure() {
if (customObject.isPresent()) {
// Singleton by necessity: Guice doesn't know how to create another one.
bind(SpecialInterface.class).toInstance(customObject.get());
} else {
// Default scoped. Add ".in(Singleton.class)" if necessary.
bind(SpecialInterface.class).toInstance(DefaultSpecialInterfaceClass.class);
}
}
}
If you want to perform additional initialization on DefaultSpecialInterface and nothing else, you have a number of options:
If some kind of initialization is important for all implementations and likely too heavy to put into a class constructor, add an initialize method on your SpecialInterface. Make the custom one a no-op, and implement it for DefaultSpecialInterface.
If the initialization is unique to DefaultSpecialInterface, I see no reason why it shouldn't be in the Module. Write a #Provides method or bind to a Provider<SpecialInterface> that creates and initializes DefaultSpecialInterface correctly.
If your real goal is to keep the business logic out of a Module, you can do so by extracting it into a free-standing Provider or DefaultSpecialInterfaceFactory that is responsible for that.
Remember, Guice is responsible for feeding fully-constructed objects into your object graph, and that means that injecting a SpecialInterface should get a ready-to-use implementor of the SpecialInterface general contract. If Guice needs to perform some initialization to make that happen, it's not unreasonable to have it do so, and a Module isn't a bad place to do it.

java separate file for global variables

I have a newbie question. If I have some global variables that are shared by two classes or more how can I have them in a separate file so that any class can read and update them. Is this possible without using Interfaces?
Yes, since interfaces variables are all implicitly static, so each of these variables has only one instance in the jvm.
However, a better way to do it [in my opinion] would probably be having them declared in some singleton class and using it.
The best way to do this is to have your shared application state accessible via interface methods, then have an implementing class that holds the variables, and pass this instance of the class to your other classes during construction (which they accept as an instance of the interface).
This is better than using a static class or singleton since it allows you to mock out the functionality of the shared state for testing, improves general code reusability, and allows you to change the implementation and configuration of the shared state without impacting any of the code using it.
E.g.
// Session interface for all application shared state.
public interface ApplicationSession
{
public int getMaxUserLimit();
}
// A backing for the interface (simple in memory version, maybe future versions use a database, who knows).
public class SomeApplicationSession implements ApplicationSession
{
private volatile int maxUserLimit = 0;
public void setMaxUserLimit(int limit) { this.maxUserLimit = limit; }
public int getMaxUserLimit() { return maxUserLimit; }
}
// ClassA uses the supplied session.
public class MyClassA
{
private ApplicationSession session;
public myClassA(ApplicationSession session)
{
this.session = session;
}
}
// usage...
public class MyMain
{
public static void main(String[] args)
{
// Create / get session (ultimately possibly from a factory).
ApplicationSession session = new SomeApplicationSession();
ClassA myClassA = new ClassA(session);
// do stuff..
}
}

I need to make a variable accessible to the whole program in Java

So my problem is this. I have a class called Globals that contains all the variables I need all over the program. It works fine for things like strings, integers and other things that you can use the = operation on. For example:
public class Globals {
public static int globalInteger = 23;
public static String globalString = "Hello, dude.";
public static UserProfile globalUserProfile;
}
Somewhere in the project, I access them using these:
Globals.globalInteger += 17;
Globals.globalString = "Why, hello there!";
However, I am trying to make a class that I wrote myself global (UserProfiles.class). This class does not use the = operation, hence, it is always null when I access it from somewhere else and I get java.lang.nullPointerException. For example if I do this (newProfile(String) is a method inside UserProfiles.class):
Globals.globalUserProfile.newProfile(profileName);
I get java.lang.NullPointerException. How can I make my UserProfile.class variable accessible all throughout the project? Thanks in advance.
Write a so called factory class which builds your whole project in one step.
Example:
// a class which store configuration parameters - must be instanstiable!
public class Configuration {
public Configuration() {
// get configuration from Properties file, Resource Bundle etc.
}
}
public class A {
private Configuration configuration;
public A(Configuration configuration) {
this.configuration = configuration;
}
}
public class B {
private Configuration configuration;
private A a;
public B(A a, Configuration configuration) {
this.a = a;
this.configuration = configuration;
}
}
public class C {
private Configuration configuration;
private B b;
public C(B b, Configuration configuration) {
this.b = b;
this.configuration = configuration;
}
}
Here you have 3 classes and one configuration class. All of them are dependent on the configuration class, C is dependent on B and B is dependent on A.
As you can see, the dependencies are reflected by the constructor parameters, which is good because dependencies are explicit (that means, you now which dependencies are needed without having too look at the source code).
But, how do you build this object graph? Well, by using a factory class (here, it's even a static factory):
public class ApplicationFactory {
// prevents instantiation
private ApplicationFactory() {};
public static C buildApplicationGraph() {
// first, build the leaf objects (objects without other dependencies), here
// Configuration
Configuration configuration = new Configuration();
// now, start injecting the dependencies needed
// a only need a Configuration object
A a = new A(configuration);
// B needs a Configuration and an A object
B b = new B(a, configuration);
// we're done here
return new C(b, configuration);
}
}
As you can see, you are building the object graph bottom up. All dependencies are explicit, and you are seperating the construction process from the business logic.
What we have done here is constructor dependency injection, i.e. we passed in the dependencies every class needs via the constructor. And for creating the objects needed, we wrote a factory.
In the end, we have lightweight classes (no construction work here), explicit dependencies (which you don't have using a Singleton), and maximum flexibility (the factory could even return a subclass of C).
EDIT
One further advantage is that you're able to test you classes in isolation, as you could easily mock the parameters (e.g. by passing in subclasses of the parameters).
Try Singleton design pattern.
http://en.wikipedia.org/wiki/Singleton_pattern
Examples of GoF Design Patterns in Java's core libraries
You can instantiate your class by default in your Globals class :
public static UserProfile globalUserProfile = new UserProfile();
or you have to declare a factory method inside of UserProfile class.

Categories