Injecting Constants via Custom Annotation - java

I have a bunch of constants throughout my code for various adjustable properties of my system. I'm moving all of them to a central .properties file. My current solution is to have a single Properties.java which statically loads the .properties file and exposes various getter methods like this:
public class Properties {
private static final String FILE_NAME = "myfile.properties";
private static final java.util.Properties props;
static {
InputStream in = Properties.class.getClassLoader().getResourceAsStream(
FILE_NAME);
props = new java.util.Properties();
try {
props.load(in);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static String getString(Class<?> cls, String key) {
return props.getProperty(cls.getName() + '.' + key);
}
public static int getInteger(Class<?> cls, String key) {
return Integer.parseInt(getString(cls, key));
}
public static double getDouble(Class<?> cls, String key) {
return Double.parseDouble(getString(cls, key));
}
}
The only problem with that is that for every constant that I get from this file, I have some boilerplate:
private final static int MY_CONSTANT = Properties.getInteger(
ThisClass.class, "MY_CONSTANT");
I don't think I want to use Spring or the like as that seems like even more boilerplae. I was hoping to use a custom annotation to solve the issue. I found this tutorial, but I can't really sort out how to get the functionality that I want out of the annotation processing. The Java docs were even less helpful. This should be a thing I should be able to do at compile time, though. I know the names of the class and field.
What I'm thinking is something like this:
#MyAnnotation
private static final int MY_CONSTANT;
Anyone know how I would go about doing this or at least best practices for what I want to do?

First of all, you shouldn't do it. It's practical, but too hacky and if you ever want to write a test using different settings, you'll run into problems. Moreover, nobody's gonna understand how it works.
An annotation processor can probably do nothing for you. A Lombok-style-hacking processor can. You want to make
#MyAnnotation
private static final int MY_CONSTANT;
work like
private final static int MY_CONSTANT =
Properties.getInteger(ThisClass.class, "MY_CONSTANT");
The original expression doesn't compile (due to the uninitialized final variable), but it parses fine and Lombok can do its job. There's already something related there:
#Value changes the modifiers to final private
#UtilityClass makes all fields static
So actually, you could write just
#MyAnnotation
int MY_CONSTANT;
and let your annotation change also the modifiers. I'd look at the eclipse and javac handlers for #UtilityClass, I guess all you need is to generate the initializer (which is quite some work because it's all damn complicated).
I don't think Lombok itself will implement this anytime soon, since
all the static stuff is non-testable and mostly bad style
and not everyone wants this in their code
it's not that much boilerplate
it also magically refers to the class Properties, but this could be solved via configuration
but I guess a contribution might be accepted.

Actually not quite clear why and what do you want to archive.
As I correctly undestand, you want use special kind of annotations to automatically assign values for static final constants from some properties file. Unfortunatelly it is impossible without special hacks. And annotations have nothing to do with this.
The reason is that final fields must be initialized and it is compiler's request. There aren't special annotations in java which will provide such syntactic sugar which you want.
But if you insist on this there are two ways:
Extrim way. Init all properties field with default value. Then using this hack in some static init section initialize this value using reflection mechanism and you code via reading values from properties.
Less extrim way: refuse request of final modifiers for properties fields, and using only reflection fill these fields values.
And additionally, for these ways, yes you can use annotations. But you will have to solve following technical issues:
1) Find all fields in all classes in classpath, which are annotated with you special annotation. Look at:
Get all of the Classes in the Classpath and Get list of fields with annotation, by using reflection
2) Force your Properties class to be initialized in all possible enter points of your application. In static section in this class you will load your properties file, and then using (1) method with reflection and classloader, assign values to all constants.

Related

nameof equivalent in Java

C# 6.0 introduced the nameof() operator, that returns a string representing the name of any class / function / method / local-variable / property identifier put inside it.
If I have a class like this:
class MyClass
{
public SomeOtherClass MyProperty { get; set; }
public void MyMethod()
{
var aLocalVariable = 12;
}
}
I can use the operator like this:
// with class name:
var s = nameof(MyClass); // s == "MyClass"
// with properties:
var s = nameof(MyClass.OneProperty); // s == "OneProperty"
// with methods:
var s = nameof(MyClass.MyMethod); // s == "MyMethod"
// with local variables:
var s = nameof(aLocalVariable); // s == "aLocalVariable".
This is useful since the correct string is checked at compile time. If I misspell the name of some property/method/variable, the compiler returns an error. Also, if I refactor, all the strings are automatically updated. See for example this documentation for real use cases.
Is there any equivalent of that operator in Java? Otherwise, how can I achieve the same result (or similar)?
It can be done using runtime byte code instrumentation, for instance using Byte Buddy library.
See this library: https://github.com/strangeway-org/nameof
The approach is described here: http://in.relation.to/2016/04/14/emulating-property-literals-with-java-8-method-references/
Usage example:
public class NameOfTest {
#Test
public void direct() {
assertEquals("name", $$(Person.class, Person::getName));
}
#Test
public void properties() {
assertEquals("summary", Person.$(Person::getSummary));
}
}
Sadly, there is nothing like this. I had been looking for this functionality a while back and the answer seemed to be that generally speaking, this stuff does not exist.
See Get name of a field
You could, of course, annotate your field with a "Named" annotation to essentially accomplish this goal for your own classes. There's a large variety of frameworks that depend upon similar concepts, actually. Even so, this isn't automatic.
You can't.
You can get a Method or Field using reflection, but you'd have to hardcode the method name as a String, which eliminates the whole purpose.
The concept of properties is not built into java like it is in C#. Getters and setters are just regular methods. You cannot even reference a method as easily as you do in your question. You could try around with reflection to get a handle to a getter method and then cut off the get to get the name of the "property" it resembles, but that's ugly and not the same.
As for local variables, it's not possible at all.
You can't.
If you compile with debug symbols then the .class file will contain a table of variable names (which is how debuggers map variables back to your source code), but there's no guarantee this will be there and it's not exposed in the runtime.
I was also annoyed that there is nothing comparable in Java, so I implemented it myself: https://github.com/mobiuscode-de/nameof
You can simply use it like this:
Name.of(MyClass.class, MyClass::getProperty)
which would just return the String
"property"
It's also on , so you can add it to your project like this:
<dependency>
<groupId>de.mobiuscode.nameof</groupId>
<artifactId>nameof</artifactId>
<version>1.0</version>
</dependency>
or for Gradle:
implementation 'de.mobiuscode.nameof:nameof:1.0'
I realize that it is quite similar to the library from strangeway, but I thought it might be better not to introduce the strange $/$$ notation and enhanced byte code engineering. My library just uses a proxy class on which the getter is called on to determine the name of the passed method. This allows to simply extract the property name.
I also created a blog post about the library with more details.
Lombok has an experimental feature #FieldNameConstants
After adding annotation you get inner type Fields with field names.
#FieldNameConstants
class MyClass {
String myProperty;
}
...
String s = MyClass.Fields.myProperty; // s == "myProperty"

Suggestions for implementing a solution using Singleton design pattern

I need to implement a solution as part of Test framework & I am considering singleton pattern for reasons explained below. However, I am not able to achieve my intended solution & therefore would need some suggestions/inputs on possible implementations.
Problem Statement :
I have a environment (env of the product I am testing) configuration properties file which I want to load & make the value of the parameters accessible globally to the test framework.
I figured using the singleton pattern because these properties are one-time values (should report an exception if tried to initialize more than once), should be available globally & have an one-point access to the methods.
However, the list of properties/parameters is really long & therefore it's wise to break it into modules (classes). For the below explanation, I tried with composition.
For e.g.
public class Configuration {
private static Configuration configObj;
private static Database dbDetails;
private static Machine macDetails;
//...
//... many more modules
public static synchronized void createInstance(Properities envProps){
//Should create only one instance of Configuration
// and should also initialize Database & Machine objects.
}
public static Configuration getConfigObject(){
return configObj;
}
}
public class Database {
private static String dbConnectString;
public Database(String dbcs){
dbConnectString = dbcs;
}
public static String getDbConnectString(){
return dbConnectString;
}
}
public class Machine {
private static String hostname;
private static String loginUsername;
public Machine(String hostname,String loginUsername){
this.hostname = hostname; //It may include some trimming/cleaning
this.loginUsername = loginUsername;
}
public static String getHostName(){
return hostname;
}
}
PS: Just a sample typed-in code for the understanding of my problem statement.
Expectation : The expectation now is that when trying to get the hostname, I should have a single point of access via Configuration static object (assuming that I have initialized all member variables successfully) i.e.
String hostname = Configuration.getHostname();
OR
String hostname = Configuration.getConfigObject().getHostname();
Current Issue :
How to create one static object that will refer to all methods using either composition or inheritance (Conceptually, composition would be the right approach).
Multiple Inheritance would have solved the issue but Java doesn't support so ruled out. Cannot consider Interfaces either because overriding all methods is tedious & lengthy & the parameters/methods will keep changing over-time.
All suggestions are welcome even if it requires to scrap this design pattern & try something different.
You will not be able to "automatically" delegate static calls to modules. And even if the calls were not static, as you stated, Java does not support multiple inheritance.
Option 1:
Have your main Configuration class provide static methods that return instances to your modules. Whenever you want to read a configuration entry, first get the module instance, then query the entry itself:
Configuration.getDatabaseConfiguration().getServerName();
This method has the advantage that it is very clear which part of your configuration you are referring to. If you would just use Configuration.getServerName(), you cannot distingish whether you want to retrieve the database's server name, or the webserver's.
Option 2:
If you are able to use Java 8 and your configuration is large, but very simple (statically known at compile time or extractable from very few instances), you could consider using the new default interface methods (https://blog.idrsolutions.com/2015/01/java-8-default-methods-explained-5-minutes/).
You would then create an interface for each module, where all getters have default implementations. Your main configuration class would implement all the module interfaces without overriding any of the methods. This way all configuration entries can be queried from one object, but you still have to obtain this object by a static method. This is as close to multiple inheritance as you can get. I would definitely recommend option 1 though.

respecting the DRY principle for variable containing the class name

How do you set variables which contain the class name, like TAG in android.util.Log, while respecting Dont-Repeat-Yourself?
These are some possibilities:
In Google code, it is often used like
public class Classname {
public final String TAG = "Classname";
which repeats the classname and was not refactor-renamed correctly in AndroidStudio (no Strings were).
Then, there is a dynamic variant
public class Classname {
public final String TAG = getClass().getName();
which does not repeat the Classname, thus seems better, yet is less readable.
Or, you could make TAG static (this might be premature optimization). Apart from the official version above, you could get the name in code like
public class Classname {
public final static String TAG
= new Object() { }.getClass().getEnclosingClass().getName();
which is way less readable, and does have problems with inheritance (being static).
What is the best practice concerning this?
Is there a better way than 1-3? (Or is this a wrong approach?)
I have gone with the dynamic approach in the past:
public class Classname {
public final String TAG = getClass().getName();
It is not that unreadable, and it is self-contained.
For more complex cases of DRY-ness, there is always the possibility of creating your own annotations, and then either
Use a two-step compile process to first generate non-DRY sources and then compile them into non-DRY .class files.
Use the annotations in an initialization step within your program to fill in the non-DRY parts at run-time, before running any logic that depends on those parts.
Using the second approach, you could have something like
#ReplaceWithClassName("TAG")
public class Classname {
public final String TAG;
And then you would iterate through all classes annotated with #ReplaceWithClassName filling in the blanks as an initialization step (more on iterating through annotated classes here; more on changing a final String here).
Annotations, introspection and code-generation provide great flexibility and power. Therefore, use wisely if you use them at all. For this particular case, the "dynamic approach" is much more readable.
retrieve class name dynamically
#JeffMiller gave the example in the ClassLogger class of his sormula project. In the class Logger, he uses
StackTraceElement[] stes = new Throwable().getStackTrace();
int e = stes.length - 1;
for (int i = 0; i < e; ++i) {
if (stes[i].getClassName().equals(classLoggerClassName)) {
// next on stack is the class that created me
log = LoggerFactory.getLogger(stes[i + 1].getClassName());
break;
}
}
to get the caller's class name.
use the class to get its name
#FlorentBayle said in the comments that
public final static String TAG = Classname.class.getName();
should be refactored correctly. (And is more readable than variant 3 above).
This is also the approach used by third-party logging frameworks like SLF4J. It is initialized via
Logger logger = LoggerFactory.getLogger(HelloWorld.class);

How to avoid reading property file multiple times

We have some data in properties file. This data is used across many classes. So, we create a Properties class object in each and every class and then read data using getProperty() method. This is leading to duplication of code.
Can someone please suggest some best practices to avoid this?
One thing that came to my mind is:
Create a class
Have a public variable for each property in property file in this class
Have a method that assigns values to each and every property
In the class where property values are required, create an object for this class and access the public variables
But, things i don't like with this approach are public variables and if at all a new property is added to the property file, i need to add code to read that property in the class.
Any help is appreciated.
Thank you!
You can create a Singleton class, that loads the properties the first time it gets invoked.. and a public method that retrieves the property value, for a given property key..
This is assuming you're using a standart Properties file... But you can extrapolate this to any key-value pair, changing Properties type to a Map or something else.
Something like
public class PropertyHandler{
private static PropertyHandler instance = null;
private Properties props = null;
private PropertyHandler(){
// Here you could read the file into props object
this.props = .....
}
public static synchronized PropertyHandler getInstance(){
if (instance == null)
instance = new PropertyHandler();
return instance;
}
public String getValue(String propKey){
return this.props.getProperty(propKey);
}
}
Then you can invoke this as needed.. from any code.. like this.
String myValue = PropertyHandler.getInstance().getValue(propKey);
Hope this helps
for me static inner class is the best possible way to do it. It will do it with lazily, as class loading is synchronized so thread safe, plus performant also. So with this we are achieving three things:
good performance because with synchronizing the liveliness will suffer, but here we are using static inner class.
thread safety because when inner class will be loaded than only map will be initialized as the class loading is thread safe hence all total thread safe.
Inner class will be loaded when we will call Singleton.initialize().get(key) so the map gets initialized lazily.
Below is the code...
public class SingletonFactory
{
private static class Singleton
{
private static final Map<String, String> map = new HashMap<String, String>();
static
{
try
{
//here we can read properties files
map.put("KEY", "VALUE");
}
catch(Exception e)
{
//we can do the exception handling
System.out.println(e);
}
}
private static Map<String, String> initialize()
{
return map;
}
}
public static String getValue(String key)
{
return Singleton.initialize().get(key);
}
}
One out of the box option is to use system properties. You can add your own system properties to your execution environment.
You can do this with a dedicated class having a static Properties object. See here for an example.
I could be misunderstanding your data flow here, but this is what seems "normal" to me:
Create a readPropFile method.
This should read a file and appropriately parse the properties it finds.
These properties can be stored in a Map<String, Object>, hashed by property name.
Read property file once (presumably when the application starts, or whenever it's appropriate to load properties) --> Properties object (say, props).
Pass props around to anything that needs access to those properties.
Or if you don't want to pass it around explicitly, use a static accessor as illustrated here.
Access properties using props.get("PROPERTY_NAME") (which just looks up that property in the internal Map).
If you don't want to use String lookups, you can keep an enum of valid property names somewhere, and do storage/lookups using that, but then you have to update that enum every time you add a new property to the file.
I've had success using an Enum, and in the constructor using the name() method to read a property of the same name. Be sure to handle exceptions in a reasonable way or else the whole class will fail to load and you won't get a helpful error message.
Benefits of this approach are that each enum value automatically corresponds to a property without having to write individual mapping code for each property. You do of course need an enum value for each property (that's unavoidable if you want DRY prop references), but you avoid repetitive per-property initialization code using unchecked Strings.
Drawbacks are that enums don't allow generic types, so if you wanted certain properties to return Integer and others to return String, then you might be better served with a classic singleton class design.
If you want to go crazy with this you could also write a script to generate your Enum or singleton java source code from the properties file, to keep your code extra DRY.

Control class loading order in Java

I've created a class which holds a bunch of properties values.
In order to initialize that class, I have to call some static method "configure()" which configures it from an XML file.
That class was supposed to act to store some data such that I could just write
PropClass.GetMyProperty();
I call the configure() from a static block in the main so I can use it anywhere
BUT
If I set a static constant member of some other class to a value from my "PropClass", I get null,
class SomeClass {
static int myProp = PropClass.GetMyProperty();
}
That's probably because that expression is evaluated before the call to configure.
How can I solve this issue?
How can I enforce that the call to configure() will be executed first?
Thanks
you could use a static code block to do that
static {
configure();
}
the syntax of a static initializer block? All that is left is the keyword static and a pair of matching curly braces containing the code that is to be executed when the class is loaded. taken from here
I would do the following:
class SomeClass
{
// assumes myProp is assigned once, otherwise don't make it final
private final static int myProp;
static
{
// this is better if you ever need to deal with exceeption handling,
// you cannot put try/catch around a field declaration
myProp = PropClass.GetMyProperty();
}
}
then in PropClass do the same thing:
class PropClass
{
// again final if the field is assigned only once.
private static final int prop;
// this is the code that was inside configure.
static
{
myProp = 42;
}
public static int getMyProperty();
}
Also. if possible, don't make everything static - at the very least use a singleton.
Can you not make the GetMyProperty() method check whether configure() has been called already ? That way you can call GetMyProperty() without having to worry about wheher our object is configured. Your object will look after this for you.
e.g.
public String getMyProperty() {
if (!configured) {
configure();
}
// normal GetMyProperty() behaviour follows
}
(you should synchronise the above if you want to be thread-safe)
Dude, sounds like you should be using Spring Framework (or some other Dependency Injection framework). In Spring, you already get everything that you need:
An XML format for defining beans with configurable properties, no need to code the logic for reading the XML and initializing the beans yourself.
Beans are initialized when you need them (provided that you access them in the correct manner). The best way would be to inject the beans into the callers.
Don't invent the wheel... Spring is one of the most commonly used frameworks in Java. IMHO, no large Java application should be coded without it.

Categories

Resources