Make instance of class available to all classes in spring? - java

I have a class which basically just contains a HashMap.
The class also has a simple getter method which allows other parts of my application to send the "key" and get back the value from the map.
That much works, however, I don't want to keep instantiating that class every time I need to access it, because this particular data doesn't really change, and I only want it in the map for the sake of querying it quickly for the value I need.
I would like my main application class to create an instance of this, and then have it be available to all of my other classes automatically.
I have been reading about this a lot this morning, but am kind of confused about how it could be achieved, am I trying to do some sort of singleton? Or am I trying to use a service?
Anyway, if anyone has a snippet I can learn from - that would really help me out. I am currently using Annotations for most stuff in spring, and would LIKE to keep it that way.

I think you may not even need a separate class to hold your map. Directly create a bean of the Map which you may want and then Autowire the map where ever you need them.
#Configuration
public class MapConfiguration {
#Bean
public Map<String, Object> dataMap() {
// Create and return your Map here
}
}
Whereever you want your map, just use autowiring.
#Autowired
#Qualifier("dataMap")
private Map<String, Object> dataMap;

If you want to continue to use Spring, you can use the #Component to create a simple component. By default all components are singletons. You can use the #PostConstruct to initialize the data. Below is an example. I'm using a String as the map key, but you can modify it to match your application.
#Component
public class MyMap {
private Map<String, Object> theMap = new HashMap<>();
// PostConstruct runs after the application context instantiates the bean
#PostConstruct
public void init() {
// initialize the data in theMap
}
public Object get(String key) {
return theMap.get(key);
}
}
You can then use the #Autowired annotation or your application context to retrieve the bean:
public class AnotherClass {
#Autowired
MyMap myMap;
// ...
}
If you would like to avoid Spring, another option is to create a simple Java singleton. Here's an example
public class MyMap {
private final static Map<String, Object> theMap = new HashMap<>();
// Use a static block to initialize the map with data
static {
// populate theMap with data
}
public Object get(String key) {
return theMap.get(key);
}
}
One thing to note is that if your map ever does actually get updated, then you will need to handle concurrent reads and updates.

Related

How to simply handle a factory of multiple parameter-diverging classes with Guice?

I have the following very simple interface:
public interface IDataSource<T> {
Observable<T> observable();
}
Now I'll be having multiple implementations of it. Each of those implementation may rely on varying parameters (different storage objects: JDBC, Cassandra, Redis...). So for instance I'll have:
public class CassandraDataSource implements IDataSource<MyCassandraObject> {
#Inject
public CassandraDataSource(Keyspace ks) {
// ...
}
}
public class OtherCassandraDataSource implements IDataSource<MyOtherCassandraObject> {
#Inject
public OtherCassandraDataSource(Keyspace ks) {
// ...
}
}
public class JDBCDataSource implements IDataSource<MyJdbcObject> {
#Inject
public JDBCDataSource(Database db) {
// ...
}
}
And so on.
What I would like is to reference each of those with a string so that i can call a factory which would return the appropriate IDataSource. Something that would behave like that:
public class DataSourceFactory {
public static final Map<String, Supplier<IDataSource<?>>> map = new HashMap<>();
#SuppressWarnings("unchecked")
public <T> IDataSource<T> get(String ref) {
return (IDataSource<T>) map.get(ref).get();
}
}
I could be giving N Providersas parameters (or direct field injection) to my factory (N being the number of IDataSource I use) and map strings to those in the constructor or use a switch in the get method but this would become quite a mess once I reach 10 to 20 IDataSource (or more!)
Is there some simpler solution I've been overlooking ?
Thanks
If you have to have a factory, then no—as in this question a manual factory is probably the best you can get.
However, if you bind all of your IDataSource implementations to IDataSource with different binding annotations, then you might be able to skip the factory and simply inject #Source("foo") IDataSource and get back the instance you want. The configuration between String and implementation still has to live somewhere, but you can have it live in a Guice module if you'd like. And, by injecting the Injector and supplying a compatible annotation implementation, you can even write a factory like DataSourceFactory that defers to Guice.
As a side note, beware of your DataSourceFactory; get will have no safe way to supply a value for its type parameter T.

Access a HashMap from a separate jar

So I have this code in JarFile1.jar:
public static HashMap<String, Double[]> myHashMap = new HashMap<String, Double[]>();
How would I access that variable in a separate JarFile2.jar using import?
Put getter and setter to that var in jar1File:
class MyClass {
public HashMap<String, Double[]> getMyHashMap() {
return myHashMap;
}
public void setMyHashMap(HashMap<String, Double[]> myHashMap) {
this.myHashMap = myHashMap;
}
}
Once you are in jarFile2 just you the Class name, Because this is static member.
class MyClassJar2 {
public MyClassJar2() {
MyClass.getMyHashMap();
}
}
So when you will import you can access that var
Hope that help :)
Firstly, that doesn't sound like a good practice at all. It's not a good idea to allow access to an atribute of an object like a Map (you could clutter the data easily and without noticing).
If you want to access data from another class, you could implement a public method like public double[] getData(String key) and importing it in the other jar. Also, note that you need to add the first jar to the classpath while executing the second one.

Unit testing a print method

How to create a class that add some stuff to a map and display it.
I was wondering about the best interface considering that all the code usually need to be covered with unit tests and it's a problem to test a method that display data.
This was my first thought:
class MyFirstProgram {
private Map<String, String> map = new HashMap<String,String>();
public int insertData(...) {...}
public void displayData(...) {...}
}
...but it's not possible to test anything about the retrieval and there is this display method... so I thougt this:
class MyFirstProgram {
private Map<String, String> map = new HashMap<String,String>();
public int insertData(...) {...}
private Map<String, String> retrieveData(...) {...}
public int displayData(...) {...call ; return status}
}
In this it's possible to test the private method with reflection but there is still this display method...
Any idea about the design?
The pragmatic way is to allow access to the Map (via a default/package access method with a comment // for unit tests, and access that. Actually, even better, name the method forUnitTestGetMap() to make it extra clear and avoid confusion with the standard getXXX naming convention. I'm usually fine with just calling toString() on the Map and comparing to what it should be, YMMV. If your insertData() is just calling standard methods on HashMap (e.g. put()) there isn't that much you can and should test, as most of the code is Java library code.
Alternatively, in the displayData() method, does it create an alternative representation of the Data? Such as XML, JSON, maybe a JPanel? If so, look at that to see that the contents of the Data are correct. Obviously XML is much easier than a JPanel for that, but you can still do something like checking that the JPanel has 3 children and the first is a Button named "OK"...
You can try creating getter and setter for the Map variable.
class MyFirstProgram {
private Map<String, String> map = new HashMap<String,String>();
public setMap(Map data) {...}
public Map getMap(...) {...}
}
And then wherever you want to print the map value use getMap method.
If you don't want to use the setters and getters we can have any method which takes a Map as input and print it.
public void PrintMap(Map data){print(data)}

Overriding key strings of an #autowired/#Inject Map<String,Object>?

I have several Spring beans of type CustomerApiLink, say the name of those beans are 'ableCustomer', 'bravoCustomer' and 'charlieCustomer' respectively (this is just an example). Now I inject all of them into a Map through
//DI through annotation
#Inject
private Map<String,CustomerApiLink> apis;
But I found that by default Spring IoC container always use their name as map key, I want to override this, to get a Map of:
able-> bean ref="ableCustomer";
bravo-> bean ref="bravoCustomer";
charlie-> bean ref="charlieCustomer";
Is it possible to do this with annotation? Or I have to create another util bean in an xml file?
I have done this multiple times. I usually #Inject a Set of the object I want to the constructor or a setter, and create a Map at that point.
public class MyObject {
private Map<String, CustomerApiLink> apiLinks;
#Inject
public MyObject(Set<CustomerApiLink> apis) {
apiLinks = new HashMap<String, CustomerApiLink>();
for(CustomerApiLink api : apis) {
apiLinks.put(api.getName(), api);
}
}
}
Of course, with this solution, it requires a way to get the key from the CustomerApiLink object. In this case, I assumed a method called getName() would be present.
No XML needed, but you can annotate a setter method instead of a field and process the supplied map yourself in the method.
#Inject
public void setApis(Map<String,CustomerApiLink> apis){
this.apis = new HashMap<String,CustomerApiLink>();
// now copy values from the incoming map to your internal map
// using keys of your own choice
}
private Map<String,CustomerApiLink> apis;

Getters/setters of a class having a map

What is the best practice in implementing/providing getters/setters for a class containing a map?
The most common implementation I see is:
public class MyClass {
private Map<String, String> myMap;
public getMyMap() { /* Return an unmodifiable map */ }
public setMyMap(Map<String, String> myMap) { ... }
}
Or would it be better to provide an interface like:
public getMyMap() { /* Return a modifiable map */ }
public addToMap(String key, String value) { myMap.put(key, value); }
And why is such method better?
Both have their uses. The methods exposed by a class should be of a proper level of abstraction. For example if the class is a registry of dogs backed by a Map<String, Dog>, then it could provide methods like:
void addDog(String name, Dog dog);
Dog findByName(String name);
If it's say a rule engine that allows clients to specify the entire rule set in one call, then it could expose methods like:
void setRules(Map<String, Rule> rules);
Map<String, Rule> getRules();
In general I would say try not to return the map at all. Have a method that takes the key and returns the value. Taking a map is ok, as long as you copy it, but a method that takes the key/value and puts it into the map would be my preference.
If you must return the map you should return a read-only version or a copy of it. A set method should also copy the map.
It is a bad idea to allow callers to mutate the data inside of a class without the class knowing, passing or holding onto mutable data is a bad idea.
It totally depends on your requirement. This may suffice in most of the cases.
You may not even have a getter method that returns the map. If you use my plug-in, it may help you creating those methods : http://fast-code.sourceforge.net/documentation.htm#create-list-map as eclipse will not help you create the add method.
I would just provide one. Something like...
public Map<String,String> getMyMap()
{
return myMap;
}
and when you want to use it then
myClass.getMyMap().put(key,value);
DISCLAIMER: I did not compile this and test this answer ;)

Categories