I can not test singleton without load() method - java

When I start the application, I need to load properties from different sources: war, file system, database, and JVM. I need to load properties once and use them within running my application. I do not need to refresh it. I don't have DI - it is a simple java application with singletons. I decide to create AppProperties singleton and load properties when starting the application. It is the best solution by the current time for me(I hope somebody makes the best solution). It is my Singleton:
import java.io.InputStream;
import java.util.Properties;
public class AppProperties {
private static AppProperties instance;
private Properties propertiesFromWar;
private Properties propertiesFromFile;
private Properties propertiesFromDB;
private AppProperties() {
propertiesFromWar = new Properties();
try {
propertiesFromWar.load(getPropertiesAsInputStreamFromWar());
propertiesFromFile.load(getPropertiesAsInputStreamFromFile());
propertiesFromDB.load(getPropertiesAsInputStreamFromDB());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private InputStream getPropertiesAsInputStreamFromDB() {
//some implementation
return null;
}
private InputStream getPropertiesAsInputStreamFromFile() {
//some implementation
return null;
}
private InputStream getPropertiesAsInputStreamFromWar() {
return getClass().getResourceAsStream("META-INF/application.properties");
}
public static AppProperties getInstance() {
if (instance == null) {
instance = new AppProperties();
}
return instance;
}
public String getProperty(String key) {
String value;
value = System.getProperty(key);
if (value == null) {
value = propertiesFromDB.getProperty(key);
if (value == null) {
value = propertiesFromFile.getProperty(key);
if (value == null) {
value = propertiesFromWar.getProperty(key);
}
}
}
return value;
}
}
But I do not understand, How can I use it in tests. Because I hardcode paths for aplication.properties files. And when I will create this instance in the tests, I will create AppProperties with real properties.
I tried to add a public method like load(filePath). But with this method, it will be not a singleton. If somebody will call this method in another place of application - my singleton will be reloaded with new data. Now I have 2 problems.
If I add load() method - it will be dangerous for reloading data. But I can use it in tests.
If I do not add this method - I can not test it.
P.S I read this article The Little Singleton
But I do not understand some moments. If I have singleton with private constructor, I can not extend it like in article.

In your test resources directory, create META-INF directory. Here create a file application.properties and add some properties for testing purposes in it.
Make sure the above directory is in the classpath when you will run the tests. This way, when getPropertiesAsInputStreamFromWar() is called, it will look for META-INF/application.properties in the classpath.

Being tests allow specifying JVM launch arguments, this can be "solved" pretty easily.
This also adds some flexibility.
java -DpropertiesPath="..." -jar yourJar.jar
And, adapting your code
private InputStream getPropertiesAsInputStreamFromWar() {
final String propertiesPath = Objects.requireNonNull(System.getProperty("propertiesPath"));
return getClass().getResourceAsStream(propertiesPath);
}
Instead of requireNonNull, you could use a default value, e.g.
META-INF/application.properties.

Related

Can value return from method are assignable for constant?

I want to format some files in SpringBoot with one request for each file. With each request, I have to call the getOutputFolder(dirName) method to get an output path in order to save the file in the expected path but my solution comes with high at overhead cost. I want to define one constant and then when I have to call the function I instead call this. But I feel it seems to be wrong or at least like a sneaky way to do. Is there any better way to solve this problem?
private static final String OUTPUT_FOLDER_PATH = getOutputFolderPath();
private String getOutputFolder(String dirName) {
String pathStr = getOutputFolderPath() + dirName + File.separator + "submit" + File.separator;
Path outputDirPath = Paths.get(pathStr);
Path path = null;
boolean dirExists = Files.exists(outputDirPath);
if (!dirExists) {
try {
path = Files.createDirectories(outputDirPath);
} catch (IOException io) {
logger.error("Error occur when create the folder at: {}", pathStr);
}
}
return dirExists ? pathStr : Objects.requireNonNull(path).toString();
}
You might want to look at jcache.
To do this, you need to install it to your Spring Boot project
implementation 'org.springframework.boot:spring-boot-starter-cache'
implementation 'javax.cache:cache-api:1.1.0'
// or the maven equivalent if you are using maven
Then create a org.springframework.cache.CacheManager bean to configure the cache.
#Bean
public CacheManager cacheManager() {
CachingProvider cachingProvider = Caching.getCachingProvider();
CacheManager cacheManager = cachingProvider.getCacheManager();
// The class arguments is <String, String> because the method to cache accepts a String and returns a String
// just explore this object for the config you need.
MutableConfiguration<String, String> configuration = new MutableConfiguration<>();
String cacheName = "OUTPUT_FOLDER_CACHE";
cacheManager.createCache(cacheName, configuration);
return cacheManager;
}
When this is setup, you can now annotated the method to be cached.
#Cacheable(
cacheNames = { "OUTPUT_FOLDER_CACHE" }, // The same string in config
unless = "#result == null" // Dont' cache null result; or do, if you need it.
)
String getOutputFolder(String dirName) {
// method contents...
}
When properly configured: the method will return the cache value if it exists, or run the actual method, cache the result and return the result if the cached value does not exist.
You can solve that issue by using ThreadLocal.
A threadlocal can store value and you can make useful for yourself. Suppose if your getOutputFolderPath() is different for different request then you can
store the getOutputFolderPath() value while a new request dispatched on server and you can do your all operation upto your request live.
See Threadlocal Docs
#Service
public class FileSaveService {
private static final ThreadLocal<String> path=new ThreadLocal<>();
#PostConstruct
public void init() {
setPath(getOutputFolderPath());
}
public void setPath(String pathString) {
path.set(pathString);
}
public String getPath() {
if(path.get() == null) return getOutputFolderPath();
return path.get();
}
#PreDestroy
public void destroy() {
path.remove();
}
}

Hadoop singleton pattern uasge

I'm trying to implement singleton which is going to cache and validate configuration of map reduce jobs in hadoop. Let's name it ConfigurationManager.
Here is what I have for now:
public class ConfigurationManager {
private static volatile ConfigurationManager instance;
private static final String CONF_NAME = "isSomethingEnabled";
private boolean isSomethingEnabled;
private ConfigurationManager(Configuration configuration) {
this.isSomethingEnabled= configuration.getBoolean(CONF_NAME, false);
}
public static void init(Configuration configuration) {
if (instance == null) {
synchronized (ConfigurationManager.class) {
if (instance == null) {
this.instance = new ConfigurationManager(configuration);
}
}
}
}
public static ConfigurationManager get() {
return instance;
}
public boolean isSomethingEnabled() {
return isSomethingEnabled;
}
}
As you can see it is designed to be thread-safe. Moreover it is not standard singleton: I separated initialization and accessor methods not to enforce presence of hadoop's Configuration instance on get call. So to use it I prematurely call init in the ancestor of Tool and then trying to access my singleton using get in reducers (like this ConfigurationManager.get().isSomethingEnabled()), but for some reasons get returns null. Could somebody, please, explain such a behaviour? Maybe maps/reducers are initiated as separate processes?
Each reduce task runs on a different jvm. Which would explain the null.
You can do it per reduce task in : Reducer - configure

What is the best practice for variables loaded in initialization

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.

Singleton with Arguments in Java Again

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.

Where to initialize a java Properties object?

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.

Categories