Alternative To Singleton Util Class - java

So I have a class like so:
public class HBaseUtil {
private final String fileName = "hbase.properties";
private Configuration config;
private HBaseUtil() {
try {
config = new PropertiesConfiguration(fileName);
} catch (ConfigurationException e) {
// some exception handling logging
}
}
// now some getters pulling data out of the config object
public static String getProperty(String fieldKeyName) {...}
public static String getColumnFamily(String fieldName) {...}
// ... some more getters
// NO setters (thus making this a read-only class)
}
Thus, basically I have for myself a Singleton class, that the very first time that it is put to use, sets up a configuration object, and then simply keeps listening for get calls. There are a number of problems with this class:
Unit testing the static methods within class HBaseUtil becomes difficult because of a tight-knit coupling between the Singleton and the configurations file.
What I really want is me being able to supply the filename/filename+path to the class so that it can go in there, read the configuration properties from that file and offer them to incoming read requests. One important note here though: I need this flexibility in specifying the properties file ONLY ONCE per JVM launch. So I certainly don't need to maintain state.
Here is what I was able to come up with:
Instead of a Singleton, I have a normal class with all static methods and no explicit constructor defined.
public class HBaseUtil {
// directly start with getters
public static String getProperty(Configuration config, String fieldKeyName) {...}
public static String getColumnFamily(Configuration config, String fieldKeyName) {...}
// ...and so on
}
And then, instead of using the class in my other code like such:
HBaseUtil.getProperty(String fieldKeyName)
I'd use it like so:
Configuration externalConfig = new PropertiesConfiguration("my-custom-hbase.properties");
HbaseUtil.getProperty(externalConfig, fieldKeyName)
My questions:
Am I even thinking in the right direction? My requirement is to have the flexibility in the class only ONCE per JVM. All that needs to be configurable in my project for this, is the location/contents of the HBase .properties file. I was thinking having a Singleton is overkill for this requirement.
What other better approaches are there for my requirement (stated in above point)?
Thanks!
Note: I've read this StackOverflow discussion, but now it's gotten me even more confused.

You should avoid all static methods and instead design a class which does not mandate its lifecycle: it can be a typical immutable POJO with a public constructor.
Then, when you need it as a singleton, use it as a singleton. For testing, use it in some other way.
Usually, dependency injection is the preferred avenue to solve these problems: instead of hard-coding a pulling mechanism for your configuration object, you have the object delivered to any class which needs it. Then you can decide late what bean you will deliver.
Since you are probably not using Spring (otherwise dependency injection would be your default), consider using Guice, which is a very lightweight and non-intrusive approach to dependency injection.

Related

Spring Service or Util for a generator class in Java?

I have barcode generator methods that I call from Controller in my Java (Spring Boot) project. The generator class is as shown below:
#Component
#NoArgsConstructor
public class QRCodeGenerator {
private static final int LABEL_X_POS = 45;
private static final int LABEL_Y_POS = 20;
#Value("${qr-code.margin}")
private int margin;
#Value("${qr-code.fontSize}")
private int fontSize;
public ResponseEntity<Resource> getQRCode(String data) throws IOException {
// code omitted for brevity
addLabel(image, label);
final ByteArrayResource resource = new ByteArrayResource(toByteArray(image));
return ResponseEntity.ok().body(resource);
}
private static byte[] toByteArray(BufferedImage image) throws IOException {
// code omitted for brevity
}
private void addLabel(BufferedImage source, String text) {
int x = LABEL_X_POS;
int y = LABEL_Y_POS;
// code omitted for brevity
}
}
First I started to use this class as static, but then I removed static to read the data in application.yml properly.
Here is some points that I need to be clarified:
1. I am new in Spring and as far as I see, spring services are generally used to provide data from database or any other service, endpoints, etc. Is that true?
2. Should I create a service for the class above (I do not need to access to database in that class)? Or it the approach is better (creating as a component and then injecting it to my Controller)?
3. There are many different opinions regarding to static Util classes. So, what about converting this class to a static Util class? Is it better than now or using it as a Spring Service?
Here are some opinions on your questions:
Classes annotated with #Service are used in business logic layer, it can provide data but it can also do actions as in your case.
Based on the point 1. you can make it a service because that provides logic for creating qr codes for representation layer (Controllers).
Having this kind of classes as #Component or more specific #Service makes it easier to inject dependencies using Dependency Injection and also it's easier to inject your class as dependency to other beans so it's easier also to test/mock. Keeping it as Spring Service is a better approach.
Make it a spring service, and you will be able to substitute a mock for it easily when you write a test for the controller. Otherwise you will not be able to mock it (unless you use things like Powernock). Since you're already injecting values into it, it's a lot easier to keep this as a Spring component.
Generally it's a premature optimization to use static util classes and it can get in the way of testing. I would use static util classes only if they contain only static methods that have no side effects, which don't need access to configuration data and which I don't mind not being able to mock. The methods I use in input validation code would be an example of something I might use static methods for. But you have the most flexibility, for instance to be able to inject configurations, if you keep these as Spring components.

Accessing CDI from simple objects?

Assume I have a configuration class accessible via the stock CDI that defines some application-wide parameters:
#ApplicationScoped
class AppConfig {
public double getMaxAllowedBrightness() { ... }
};
And I have a simple class for my data objects:
class LightSource {
double brightness;
...
boolean isValid() {
double maxAllowedBrightness = ...; // Somehow use AppConfig#getMaxAllowedBrightness() here
return brightness <= maxAllowedBrightness;
}
}
How can my data object access the single AppConfig instance?
Somehow I hate the idea of autowiring AppConfig into every single data object (there are lots of them). Is there any other way to get access to AppConfig in the above example from my data object?
What's the best pattern to use here?
The simplest example is a runtime lookup akin to:
import jakarta.enterprise.inject.spi.CDI;
CDI.current().select(cls).get();
With cls being the class that you're looking up. (Note the package name, this is the latest version of CDI 2.x in the new jakarta namespace, the original is in javax.)
It gets more detailed from there, but that's the gist of it.
Note, that semantically there's little difference between autowiring something and doing a runtime lookup, especially for something mostly static at the instance level. It's still a dependency. You still have to touch the code of the classes to pull it off.
A nice thing of relying on the autowiring is that you can disable it situationally, and the class reverts to a simple bean, that you can do with what you will. Coding in the lookup, it's a little bit more than that.
Dynamic lookup is more for special circumstances.
On my current project, our team has been doing this using the #Value annotation. In our case, we have all the properties in a properties bean, which I'll call mainAppConfiguration. The bean is populated from a properties file like main-app-config.properties (which was read into the bean with a Properties prop = new Properties().load(mainAppConfigFilePath) method.
Assuming you have something like that set up, then we inject the properties into the classes that need them using a little SpEL magic something like:
private Integer refreshRateSeconds;
#Value("#{ mainAppConfiguration.getProperties()['funny-property-base-name.refreshRateSeconds'] }")
public void setRefreshRateSeconds(Integer refreshRateSeconds) {
if (refreshRateSeconds == null) {
throw new IllegalArgumentException("Required config property 'funny-property-base-name.refreshRateSeconds' was not found"));
}
this.refreshRateSeconds = refreshRateSeconds;
}
Baeldung has examples (without defaults) and more with defaults.

Testing with java owner aeonbits

I've been using java OWNER for property based configuration.
I've create a static method
public static final ApplicationConfiguration config = ConfigFactory.create(ApplicationConfiguration.class,
System.getProperties(), System.getenv());
and I import the class everywhere I need conf.
Needless to say, unit testing is a PITA. I couldn't find a good way of override the values in the configuration.
I would like to avoid passing the config as a dependency in every class.
It adds a lot of verbosity and it doesn't make sense from a design point of view.
Same applies for calling the config factory in every class
ApplicationConfiguration config = ConfigFactory.create(ApplicationConfiguration.class,
System.getProperties(), System.getenv());
Have you got any suggestion? is there a best practice?
Two things:
You can create a class that provides the properties and all users use it:
public class PropertiesAccessor {
private static MyConfiguration mMyConfig = ConfigFactory.create(MyConfiguration.class);
private PropertiesAccessor()
// No need to allow instantiation of this class
}
/**
* Get properties for this application
*
* #return Properties
*/
public static MyConfiguration getProperties() {
return mMyConfig;
}
// for unit testing
#VisibleForTesting
public static void setProperties(MyConfiguration config) {
mMyConfig = config;
}
}
Now, everywhere you need a property, you can use this static method
PropertiesAccessor.getProperties()
Notice that there is a method for testing, setProperties(). There are different ways to use this method. You can create a test property file, load it in, then call the setProperties() method. I like to have a utility method like this:
public static void initProperties(String fileName) {
Properties testProperties = new Properties();
File file = new File(fileName);
FileInputStream stream = null;
try {
stream = new FileInputStream(file);
testProperties.load(stream);
} catch (IOException e) {
// Log or whatever you want to do
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
// Log or whatever you want to do;
}
MyConfiguration config = ConfigFactory.create(MyConfiguration.class, testProperties);
PropertiesAccessor.setProperties(config);
}
Then, you can have various properties files.
Or, if you just want to set a few properties, do this:
Properties testProperties = new Properties();
testProperties.setProperty("key1", "data1");
testProperties.setProperty("key2", "data2");
final MyConfiguration myConfig = ConfigFactory.create(MyConfiguration.class, testProperties);
PropertiesAccessor.setProperties(myConfig);
Needless to say, unit testing is a PITA. I couldn't find a good way of override the values in the configuration.
You can have Mutable configuration objects. No PITA when you read the manual.
But there are better approaches.
Interfaces are super easy to test and to deal with while testing, when you know SOLID principles.
import static org.mockito.Mockito.*;
MyConfig cfg = mock(MyConfig.class); // mock object
when(cfg.myConfigurationThing()).thenReturn("whateverYourObjectNeeds");
ObjectThatYouNeedToTest targetObject =
new ObjectThatYouNeedToTest(cfg); // Dependency Injection
// see: http://wiki.c2.com/?ConstructorInjection
assertEquals("expected result", targetObject.whateverYouNeedToTest());
// then you can also verify interactions:
verify(cfg, times(1)).myConfigurationThing();
The above snippet shows a Mockito example, but there are plenty of similar testing frameworks.
Check what Mock Objects are, what is Dependency Injection and Interface Segregation.
I would like to avoid passing the config as a dependency in every class.
If your objects need the configuration, you should pass the configuration to your objects. It's the way things should be.
If it's verbose, there's something in your application design that needs to be revised. For instance, you chosed to have a singleton with a static member in a class, and that's not very good, especially for testing.
Same applies for calling the config factory in every class
Calling the config factory in every class, it's a bad idea. Maybe you can split your configuration file in many component-specific ones. That's one way (my way).
But if you need a single huge configuration file (which is not my favorite approach), your config interfaces don't need to respect the same structure: you can have several component-configuration interfaces reading from the same file: it's not the best if you use hot reload, and I probably could do more to modularize configurations objects in a tree of nested configuration interfaces.
But hey, I did it in my spare time for myself and I shared it for free; if people do things differently than me and they need me to support the way they work, maybe they could support the development contributing good code or hire my time to improve it.
Sorry for the PITA.

Using guice for a framework with injected classes, proper way to initialize?

I'm trying to write a framework where arbitrary bean classes are injected with classes from my API, and they can interact with both those classes as well have triggered callbacks based on defined annotations. Here's an example bean:
#Experiment
static class TestExperiment {
private final HITWorker worker;
private final ExperimentLog log;
private final ExperimentController controller;
#Inject
public TestExperiment(
HITWorker worker,
ExperimentLog expLog,
ExperimentController controller
) {
this.worker = worker;
this.expLog = expLog;
this.controller = controller;
}
#SomeCallback
void callMeBack() {
... do something
log.print("I did something");
}
}
I'm trying to use Guice to inject these beans and handle the interdependencies between the injected classes. However, I have two problems:
One of the classes I pass in (HITWorker) is already instantiated. I couldn't see how to move this to a Provider without significantly complicating my code. It is also persistent, but not to the Guice-defined session or request scope, so I am managing it myself for now. (Maybe if the other issues are overcome I can try to put this in a provider.)
More importantly, I need a reference to the other injected classes so I can do appropriate things to them. When Guice injects them, I can't access them because the bean class is arbitrary.
Here's some really bad code for what I basically need to do, which I am sure is violating all the proper dependency injection concepts. Note that hitw is the only instance that I need to pass in, but I'm creating the other dependent objects as well because I need references to them. With this code, I'm basically only using Guice for its reflection code, not its dependency resolution.
private void initExperiment(final HITWorkerImpl hitw, final String expId) {
final ExperimentLogImpl log = new ExperimentLogImpl();
final ExperimentControllerImpl cont = new ExperimentControllerImpl(log, expManager);
// Create an experiment instance with specific binding to this HITWorker
Injector child = injector.createChildInjector(new AbstractModule() {
#Override
protected void configure() {
bind(HITWorker.class).toInstance(hitw);
bind(ExperimentLog.class).toInstance(log);
bind(ExperimentController.class).toInstance(cont);
}
});
Object experimentBean = child.getInstance(expClass);
expManager.processExperiment(expId, experimentBean);
// Initialize controller, which also initializes the log
cont.initialize(expId);
expManager.triggerStart(expId);
tracker.newExperimentStarted(expId, hitw, cont.getStartTime());
}
Am I screwed and just have to write my own injection code, or is there a way to do this properly? Also, should I just forget about constructor injection for these bean classes, since I don't know what they contain exactly anyway? Is there any way to get the dependencies if I am asking Guice to inject the bean instead of doing it myself?
For context, I've been reading the Guice docs and looking at examples for several days about this, to no avail. I don't think I'm a complete programming idiot, but I can't figure out how to do this properly!
Your "experiment" seems to be something like a "request" in the sense that it has a defined lifecycle and some associated stuff the experiment can pull in at will.
Therefore I think you should wrap all that into a custom scope as described in the docs about Custom Scopes. This matches your case in several points:
You can "seed" the scope with some objects (your HITWorker)
The lifecycle: do "enter scope" before you setup the experiment and "exit scope" after you finished your work.
Access to "shared" stuff like ExperimentLog and ExperimentController: Bind them to the scope. Then both the framework and the experiment instance can simple #Inject them and get the same instance.

java Properties - to expose or not to expose?

This might be an age old problem and I am sure everyone has their own ways.
Suppose I have some properties defined such as
secret.user.id=user
secret.password=password
website.url=http://stackoverflow.com
Suppose I have 100 different classes and places where I need to use these properties.
Which one is good
(1) I create a Util class that will load all properties and serve them using a key constant
Such as :
Util is a singleton that loads all properties and keeps up on getInstance() call.
Util myUtil = Util.getInstance();
String user = myUtil.getConfigByKey(Constants.SECRET_USER_ID);
String password = myUtil.getConfigByKey(Constants.SECRET_PASSWORD);
..
//getConfigByKey() - inturns invokes properties.get(..)
doSomething(user, password)
So wherever I need these properties, I can do steps above.
(2) I create a meaningful Class to represent these properties; say,
ApplicationConfig and provide getters to get specific properties.
So above code may look like:
ApplicationConfig config = ApplicationConfig.getInstance();
doSomething(config.getSecretUserId(), config.getPassword());
//ApplicationConfig would have instance variables that are initialized during
// getInstance() after loading from properties file.
Note: The properties file as such will have only minor changes in the future.
My personal choice is (2) - let me hear some comments?
Do it the most straightforward way (a class with static values):
package com.domain.packagename
public class Properties {
private static String hostName;
public static getHostName() { return hostName; }
private static int port;
public static int getPort() { return port; }
public static void load() {
//do IO stuff, probably
hostName = ??;
port = ??;
//etc
}
}
I find the first approach to be more verbose than necessary. (Especially if the properties are not expected to change very much.) Also, by using the second approach you can handle casting/type issues when the properties are loaded instead of when they are used.
Your option (2) to keep application specific getters sounds better and clean.
public static final keys from an interface had been a bad design in Java for ages.
I guess my first question is why you want to create an instance of something you're saying is a singleton (you mentioned using code like Util.getInstance()). A singleton only has 1 instance so you shouldn't try to instantiate multiple copies in your code.
If the data is static (like this appears to be) I'd create a singleton and retrieve the values from it.
I don't think there is any significant advantage of one method over the other and I don't think the solution (1) is more secure, just because it provides a property key instead of a java getter for getting passwords.
If I had to chose one though I would take option (2).

Categories