I have a java web application that needs to read information from an external file when initialized (ie: when jboss server is started).
Since reading and parsing this text file is an expensive operation, we decided to load it only one time and then set it to memory so it can be accessed anywhere (the variable doesn't need to be modified after initialitazion).
I've read everywhere that global variables should be avoided, so what is the best practice for this scenario?
Edit: I should have mentioned that the information should be stored in a simple List variable.
it strongly depends on the framework you are using. In general you are right, global variables are often treated as anti-pattern. But you have to understand the reason, which is mainly testability.
To get "global" things tested you usually use patterns like Factories, Provider often in combination with dependency injection (e.g. Spring, Guide).
In the end you are caching. For caching you can also use some framework like EHCache. But maybe that's to much overhead for you.
To keep it simple and in plain Java I would suggest something like this (just first draft, not tested):
public class FileCache {
Map<String, String> fileContents = new HashMap<String, String>();
public void loadFile(String path) {
if (fileContents.contains(path)) {
return fileContents.get(path);
}
// Loading logic
String content = loadContentOfFile(path);
fileContents.put(path, content);
return content;
}
}
With this you keep your caching a bit scalable (you can cache as many files as you want) and it will be easy to test this class. But in the end you end up with some global place where you need to access this class.
And then you either have Dependency Injection, a static variable or some Singleton.
With a singleton you should care to keep it simple, since it's again hard to test.
public class FileContentProvider {
private static FileContentProvider instance;
private final FileCache fileCache = new FileCache();
public static FileContentProvider getInstance() {
if (instance == null) {
instance = new FileContentProvider();
}
return instance;
}
public FileCache getFileCache() {
return fileCache;
}
}
A static Configuration-Object that is global accessible is pretty common. You could use a Singleton-Pattern to access the Config. That could look like this:
public class Config {
private static Config myInstance;
private Config() {
// Load the properties
}
public static getInstance() {
if (myInstance == null) {
myInstance = new Config();
}
return myInstance;
}
public String getConfigPropertyBla()
...
}
If you use Spring you could let Spring load the properties to a Bean. You can then access the Bean via autowiring everywhere in your application. I personally think, that this is a very nice solution.
DI, IoC container. Have a look at Guice, very nice thing.
Related
In project I am working on we have a bunch of commonly used helpers. Consider the following example:
public class ServiceHelper {
public HttpServletRequest() getRequest() { ... }
public Model getModel() { ... }
public UserCache getUserCache() { ... }
public ComponentContainer getComponentContainer() { ... }
}
Imagine this helper is being used across the whole application by every web service we have. Then, in order to test these services I need to mock it. Each time. But what if I create a factory of some kind instead, something like:
public class ServiceHelperMockStore {
public static ServiceHelper create() {
return init();
}
public static ServiceHelper create(final Model model) {
final ServiceHelper helper = init();
when(helper.getModel()).thenReturn(model);
return helper;
}
private static ServiceHelper init() {
final ServiceHelper helper = mock(ServiceHelper.class);
final HttpServletRequest request = mock(HttpServletRequest.class);
final Model model = mock(Model.class);
final UserCache userCache = mock(UserCache.class);
final ComponentContainer container = mock(ComponentContainer.class);
final BusinessRules businessRules= mock(BusinessRules.class);
final ModelTransformer modelTransformer = mock(ModelTransformer.class);
when(helper.getRequest()).thenReturn(request);
when(helper.getModel()).thenReturn(model);
when(helper.getUserCache()).thenReturn(userCache);
when(helper.getComponentContainer()).thenReturn(container);
when(container.getComponent(BusinessRules.class)).thenReturn(businessRules);
when(componentContainer.getComponent(ModelTransformer.class)).thenReturn(modelTransformer);
return helper;
}
}
This factory nicely fit my purposes and oftentimes I can completely avoid using 'mock' and 'when' in the actual test suites. Instead, I can do the following:
#RunWith(MockitoJUnitRunner.Silent.class)
public class ModelServiceTest {
private final Model model = new Model();
private final ServiceHelper serviceHelper = ServiceHelperMockStore.create(model);
private final BusinessRules businessRules = serviceHelper.getComponentContainer().getComponent(BusinessRules.class);
private final ModelType modelType1 = new ModelType();
private final ModelType modelType2 = new ModelType();
private final ModelService modelService = new ModelService(serviceHelper);
#Before
public void setUp() {
modelType1.setItemId("item1");
modelType2.setItemId("item2");
model.setTypes(modelType1, modelType2);
when(businessRules.get("type")).thenReturn(modelType1);
}
...tests...
}
So instead of creating a lot of mocks in the ModelServiceTest, I can just access the predefined ones, like:
BusinessRules businessRules = serviceHelper.getComponentContainer().getComponent(BusinessRules.class);
and this even reflect my helper's API. Also, I can provide my own mock or stub passing parameters to my factory method or using some different approach.
The only problem I have is UnnecessaryStubbingException being thrown by Mockito as normally I don't use all those stubbings I've created per each test file. So I have to use MockitoJUnitRunner.Silent runner to silent the error and according to the mockito api docs it is not recommended.
So I am seeking for an advice what kind of approach must be chosen in this case. Am I doing it right or there is some other way? Or, maybe, using such kind of factories is a bad style of programming in relation to unit tests as it hides some initialization and makes happening things less evident so I must do just a plain copy of my code between test suits?
The fact that you need this identical complex mock configuration at different places shows that your code violates the Law of Demeter (Don't talk to strangers).
A unit should only get dependencies it actually interacts with (other than only to getting another dependency from it).
So instead of creating a lot of mocks in the ModelServiceTest, I can just access the predefined ones,
You Unittests are not only verification of correct behavior but also minimal examples how to use the CUT (Code under test).
The configuration of the CUTs dependencies is an essential part of that example and should be easily accessible to the reader of the tests.
I'd strongly discourage from "factories for mocks" especially it they were moved to other classes (in the test folder).
Assume there is a simple class:
public class SingletonClass {
private static SingletonClass singObj;
private string variable1;
private string variable2;
.....
public static synchronized SingletonClass getInstance() {
if (singObj == null) {
singObj = new SingletonClass();
}
return singObj;
}
}
If there are lot of string variables and they need to be stored in multiple language, what's the standard method to manage this in Java?
Currently i use:
public class SingletonClass {
private static SingletonClass singObj_LANG1;
private static SingletonClass singObj_LANG2;
private static SingletonClass singObj_LANG3;
private string variable1;
private string variable2;
.....
public static synchronized SingletonClass getInstance(String lang) {
if (lang.equals("English")) {
if (singObj_LANG1 == null) {
singObj_LANG1 = new SingletonClass();
}
return singObj_LANG1;
}else if (lang.equals("Chinese")) {
if (singObj_LANG2 == null) {
singObj_LANG2 = new SingletonClass();
}
return singObj_LANG2;
}else{
if (singObj_LANG3 == null) {
singObj_LANG3 = new SingletonClass();
}
return singObj_LANG3;
}
}
}
which i think is a bad practice, any better implementation?
What you need is internationalization
Internationalization is the process of designing an application so
that it can be adapted to various languages and regions without
engineering changes. Sometimes the term internationalization is
abbreviated as i18n, because there are 18 letters between the first
"i" and the last "n."
Instead of a string variable for lang you need to use Locale.
You store the messages in a ResourceBundle.
Resource bundles contain locale-specific objects. When your program needs a
locale-specific resource, a String for example, your program can load
it from the resource bundle that is appropriate for the current user's
locale. In this way, you can write program code that is largely
independent of the user's locale isolating most, if not all, of the
locale-specific information in resource bundles. This allows you to
write programs that can:
be easily localized, or translated, into different languages handle
multiple locales at once be easily modified later to support even more
locales
The Java Platform provides two subclasses of ResourceBundle, ListResourceBundle and PropertyResourceBundle, that provide a fairly simple way to create resources. ListResourceBundle manages its resource as a list of key/value pairs. PropertyResourceBundle uses a properties file to manage its resources.
What i recommend is the PropertyResourceBundle because you should be keeping your translated values in a properties file.
A properties file is a simple text file. You can create and maintain a properties file with just about any text editor.
Read more backing a ResourceBundle with Properties Files here
You can read more about the concept here.
In the end you will end up getting the messing like this:
ResourceBundle messages = ResourceBundle.getBundle("MessagesBundle", currentLocale);
System.out.println(messages.getString("locale.language.key.example"));
The links i provided represent lessons in a wider course on internationalization. You can navigate and read more about it there and you will end up learning the best practices. Using a framework it becomes even easier.
Taking this approach you will be using a single class.
I wouldn't use the Singleton approach at all. Java Internationalization is what you need:
https://docs.oracle.com/javase/tutorial/i18n/intro/steps.html
I would use a Map as storage for your language-specific singletons
private static Map<String, TheClass> map = new HashMap<>();
public static SingletonClass getInstance(String lang) {
synchronized(map){
if(map.containsKey(lang)) return map.get(lang);
else{
SomeClass it = new SomeClass();
map.put(lang, it);
return it;
}
}
}
But the better solution for your problem is Internationalization (see other answers)
Good morning,
I am currently developing a java web application that exposes a web service interface. In order to keep a global object in memory, I use the following class as a Singleton:
public class SingletonMap {
private static final SingletonMap instance = new SingletonMap();
private static HashMap couponMap = null;
private static long creationTime;
private SingletonMap() {
creationTime = System.currentTimeMillis();
couponMap = new HashMap();
}
public static synchronized SingletonMap getInstance() {
return instance;
}
public static long getCreationTime() {
return creationTime;
}
}
I am using the above class in order to have the same instance of the HashMap for all the threads of the web service. The Web service class that maintains the SingletonMap object is the following:
#WebService()
public class ETL_WS {
private String TOMCAT_TEMP_DIR;
private final int BUFFER_SIZE = 10000000;
private static SingletonMap couponMap;
private static SingletonProductMap productCategoryMap;
private String dbTable = "user_preferences";
public ETL_WS() {
Context context = null;
try {
context = (Context) new InitialContext().lookup("java:comp/env");
this.TOMCAT_TEMP_DIR = (String) context.lookup("FILE_UPLOAD_TEMP_DIR");
}catch(NamingException e) {
System.err.println(e.getMessage());
}
public long getCouponMapCreationTime() {
return couponMap.getCreationTime();
}
}
The reason i have the method getCouponMapCreationTime() is to check that all the threads of the web service are accessing the same object. Is the above approach correct? How about performance overheads? Do you think I need the Singleton properties, or could I just use a static HashMap for all the threads? If I use a static HashMap, is it going to be garbage collected in case no thread is active?
Thank you for your time.
A JAX-WS web service is by itself a Singleton. This means that all the request will be handled using a single web service instance (like a Servlet).
So, any member of the class will be 'shared' between all the request. In your case, you do not need to make your members (i.e. couponMap) an static attributes.
Conclusion: Don't worry, all your threads (request) will be accessing the same 'couponMap'. Because you don't need the getCouponMapCreationTime anymore, I think that you can eliminate the SingletonMap abstraction and use directly a Map in your web service class.
But I have something very important to add. If several threads (request) will be accessing your Map you have to make it thread-safe!!! There are a lot of way to do this, but I will give an idea: Use a ConcurrentHashMap instead of a HashMap. This will make all your get(), put(), remove() operations thread-safe! If you need a larger scope you can use synchronized blocks, but please avoid synchronize methods because the scoop is too large and always synchronize over this object.
JAX-WS has its own patterns for creating singletons, you don't need to use static fields. You use the #Inject annotation into each service. See this blog post: http://weblogs.java.net/blog/jitu/archive/2010/02/19/jax-ws-cdi-java-ee-6-0 (but don't use #SessionScoped, use #Singleton)
Some other points:
HashMap isn't thread-safe, you need ConcurrentHashMap.
This catch(NamingException e) { System.err.println(e.getMessage()); is unhelpful. Rethrow it as a RuntimeException. You can't recover from it.
Don't worry about performance overhead at this stage. Measure it once you have something working.
First, I have to admit my problem is similar to Singleton with Arguments in Java
I read it, but the solution doesn't work for me. I know the factory pattern is the best solution to that problem.
Here is my problem.
I create a "singleton" class to provide some common function, for example get a global configuration parameter. This class need a handler to access the system resources, for example read the configuration file. Cause this class just act as a lib, the handler must pass in from outside, and the Handler is a system class.
So, I write my code in this way:
public class SingletonGlobalParameters {
private static final SingletonGlobalParameters instance = new SingletonGlobalParameters ();
private boolean initial = false;
private String aParameter = null;
private SingletonGlobalParameters () { }
public static SingletonGlobalParameters getInstance() {
if (initial == false) {
throw exception...
}
return instance;
}
public void init(Handler h) {
if (initial == false) {
Handler fileHandler = h;
aParameter = fileHandler.read(); // something like this
initial = true;
}
}
public int getParameter() {
return aParameter;
}
}
I remove synchronization stuff to make question clear.
This implement looks ugly, right? The class must guarantee to initialize before use.
Any good ideas? Thanks very much, this problem has troubled me for some time.
OK! I give the real world problem. This is a Android problem.
public class Configuration {
private static final Configuration instance = new Configuration ();
private boolean initial = false;
private long timeStamp = -1;
private Configuration () { }
public static Configuration getInstance() {
if (initial == false) {
throw exception...
}
return instance;
}
public void load(Context context) {
if (initial == false) {
SharedPreferences loader = context.getSharedPreferences("Conf", Context.MODE_PRIVATE);
timeStamp = loader.getInt("TimeStamp", 0);
initial = true;
}
}
public int getTimeStamp() {
return timeStamp;
}
}
Is this make question clearer?
The right pattern is the one allowing you to do things you need. Do not be so dogmatic. Singleton with a parameter is widely used and acepted in android environment (parameter is usually context). But in plain java environment, dependency injection would be better as it
decouples code using you singleton from the fact it is singleton, and modalities of its creation. There are a plenty of DI frameworks,like picocontainer, spring, google guice - just pick your favorite
EDIT: When I wrote this answer, the question had no context - we didn't know it was an Android app. It may be that it's not a bad solution in this case; but I would at least think about other approaches. I'm leaving my answer below for the more general case.
I would attempt to move away from the singleton pattern to start with.
Why is each configuration parameter needed from many places? Could you encapsulate each aspect of configuration (possibly multiple parameters in a single aspect in some cases) and then use dependency injection (e.g. with Guice) to make those encapsulated versions available to the components that need them?
It's hard to give concrete advice when we really don't know what kind of app you're writing, but in general it's a good idea to move away from global state, and dependency injection often provides a clean way of doing this. It's not a panacea, and it could be that in some cases you can redesign in a different way, but it would be my first thought.
I inherited an application which uses a java properties file to define configuration parameters such as database name.
There is a class called MyAppProps that looks like this:
public class MyAppProps {
protected static final String PROP_FILENAME = "myapp.properties";
protected static Properties myAppProps = null;
public static final String DATABASE_NAME = "database_name";
public static final String DATABASE_USER = "database_user";
// etc...
protected static void init() throws MyAppException {
try {
Classloader loader = MyAppException.class.getClassLoader();
InputStream is = loader.getResourceAsStream(PROP_FILENAME);
myAppProps = new Properties();
myAppProps.load(is);
} catch (Exception e) {
threw new MyAppException(e.getMessage());
}
}
protected static String getProperty(String name) throws MyAppException {
if (props==null) {
throw new MyAppException("Properties was not initialized properly.");
}
return props.getProperty(name);
}
}
Other classes which need to get property values contain code such as:
String dbname = MyAppProps.getProperty(MyAppProps.DATABASE_NAME);
Of course, before the first call to MyAppProps.getProperty, MyAppProps needs to be initialized like this:
MyAppProps.init();
I don't like the fact that init() needs to be called. Shouldn't the initialization take place in a static initialization block or in a private constructor?
Besides for that, something else seems wrong with the code, and I can't quite put my finger on it. Are properties instances typically wrapped in a customized class? Is there anything else here that is wrong?
If I make my own wrapper class like this; I always prefer to make strongly typed getters for the values, instead of exposing all the inner workings through the static final variables.
private static final String DATABASE_NAME = "database_name"
private static final String DATABASE_USER = "database_user"
public String getDatabaseName(){
return getProperty(MyAppProps.DATABASE_NAME);
}
public String getDatabaseUser(){
return getProperty(MyAppProps.DATABASE_USER);
}
A static initializer looks like this;
static {
init();
}
This being said, I will readily say that I am no big fan of static initializers.
You may consider looking into dependency injection (DI) frameworks like spring or guice, these will let you inject the appropriate value directly into the places you need to use them, instead of going through the indirection of the additional class. A lot of people find that using these frameworks reduces focus on this kind of plumbing code - but only after you've finished the learning curve of the framework. (DI frameworks are quick to learn but take quite some time to master, so this may be a bigger hammer than you really want)
Reasons to use static initializer:
Can't forget to call it
Reasons to use an init() function:
You can pass parameters to it
Easier to handle errors
I've created property wrappers in the past to good effect. For a class like the example, the important thing to ensure is that the properties are truly global, i.e. a singleton really makes sense. With that in mind a custom property class can have type-safe getters. You can also do cool things like variable expansion in your custom getters, e.g.:
myapp.data.path=${myapp.home}/data
Furthermore, in your initializer, you can take advantage of property file overloading:
Load in "myapp.properties" from the classpath
Load in "myapp.user.properties" from the current directory using the Properties override constructor
Finally, load System.getProperties() as a final override
The "user" properties file doesn't go in version control, which is nice. It avoids the problem of people customizing the properties file and accidentally checking it in with hard-coded paths, etc.
Good times.
You can use either, a static block or a constructor. The only advice I have is to use ResourceBundle, instead. That might better suit your requirement. For more please follow the link below.
Edit:
ResourceBundles vs Properties
The problem with static methods and classes is that you can't override them for test doubles. That makes unit testing much harder. I have all variables declared final and initialized in the constructor. Whatever is needed is passed in as parameters to the constructor (dependency injection). That way you can substitute test doubles for some of the parameters during unit tests.
For example:
public class MyAppProps {
protected static final String PROP_FILENAME = "myapp.properties";
protected Properties props = null;
public String DATABASE_NAME = "database_name";
public String DATABASE_USER = "database_user";
// etc...
public MyAppProps(InputStream is) throws MyAppException {
try {
props = new Properties();
props.load(is);
} catch (Exception e) {
threw new MyAppException(e.getMessage());
}
}
public String getProperty(String name) {
return props.getProperty(name);
}
// Need this function static so
// client objects can load the
// file before an instance of this class is created.
public static String getFileName() {
return PROP_FILENAME;
}
}
Now, call it from production code like this:
String fileName = MyAppProps.getFileName();
Classloader loader = MyAppException.class.getClassLoader();
InputStream is = loader.getResourceAsStream(fileName);
MyAppProps p = new MyAppProps(is);
The dependency injection is when you include the input stream in the constructor parameters. While this is slightly more of a pain than just using the static class / Singleton, things go from impossible to simple when doing unit tests.
For unit testing, it might go something like:
#Test
public void testStuff() {
// Setup
InputStringTestDouble isTD = new InputStreamTestDouble();
MyAppProps instance = new MyAppProps(isTD);
// Exercise
int actualNum = instance.getProperty("foo");
// Verify
int expectedNum = 42;
assertEquals("MyAppProps didn't get the right number!", expectedNum, actualNum);
}
The dependency injection made it really easy to substitute a test double for the input stream. Now, just load whatever stuff you want into the test double before giving it to the MyAppProps constructor. This way you can test how the properties are loaded very easily.