Java - properties as a static fields directly on class - java

I was trying to find out any info about that on google, but without any result.
Can someone please explain me, if there is any reason why we should load properties via config.properties, then declaring "Properties prop", then readinng it… instead of directly defining static fields as properties on some class (simpler and quicker i guess).
Public ConfigClass{
public static string SERVERNAME = "some hostname";
public static string USERNAME = "some username"
}
And then, just calling it inside code if we need that, e.g.
ConfigClass.SERVERNAME
I'm talking about simple scenarios, where i want to use simple properties like, servername, username, etc…

One advantage would be that you can change the values without having to recompile and re-deploy your code. Also, this might work for private projects but imagine you're a company with several customers where the values might be different for each customer.

Related

How to get default application name in cli?

I want to create a framework that shows the application name on statup. Targeting command line interface applications.
Question: how can I get such an application name in a generic way?
Eg spring offers a property, but which is not set by default:
#Value("${spring.application.name}")
private String appname;
And I don't want to set that property explicit. Looking for some kind of "default application name".
In a Java EE container there is also the following option:
String myApplicationName = (String) initialContext.lookup("java:app/AppName");
But how about CLI apps? How can I get some kind of generic application name?
The closest you can get, if I interpreted correctly your question, is to:
find which class is running public static void main(String [] args) method
get its simpleName
store aforementioned name into a system property
and in order to do so, you have two options:
call Thread.currentThread().getStackTrace(), and inspect its tail element. But this has to be executed in the main thread as well, otherwise you wont retrieve the correct StackTraceElement;
call Thread:getAllStackTraces(), and parse the entire map to identify the main Thread, get the corresponding value, and pick its last StackTraceElement
Once you have StackTraceElement, you can call StackTraceElement:getClassName() which will return something like
scala.tools.nsc.MainGenericRunner
Split the string, save it into a system property, and you're good to go.
Hope it will help you.

How to change values of "private static final String filePath" for unittesting

I have my class as
public class MappingLoader
{
private static final String filepath = "/tmp/mapping.properties" // unix path of production system
private static Map<String,String> mapping = new HashMap<String,String>()
static
{
loadMappingFile()
}
#VisibleForTesting
static void loadMappingFile()
{
//reading properties files here
final Properties prop = new Properties();
try (final InputStream input = Files.newInputStream(Paths.get(filepath)))
{
prop.load(input);
}
catch (final Exception e)
{
...
...
throw new RuntimeException(e);
}
//now load "mapping" from properties file
....
....
}
}
For testing, I need to change the value of string variable "filepath" such that it should take development system path(say c:\project\target\mapping.properties)
I have tried powermocks in junits, but it always throws exception and terminates.
annotations at class level:
#RunWith(PowerMockRunner.class)
#SuppressStaticInitializationFor("some.package.ClassWithStaticInit")
and in test case:
Whitebox.setInternalState(Mappingloader.class, "filepath", testfilepath);
Mappingloader.loadMappingFile();
I also tried to change this via reflection as given in(Change private static final field using Java reflection) but it always throws the FileNotFoundException for "filepath" and does not takes the changed path "testFilePath"
Is there any way i can change this variable such that it does not throw FileNotFoundException without any modification in source code?
If I remove "throw new RuntimeException(e);" in source code, powermocks works for me. but i want to achieve this without modifying source code, either via powermock, reflection api.
Well, you can try your luck with Powermock; and that should work (maybe if you spend some more hours reading its documentation and making experiments); but honestly: your problem is not testing. Your problem is that you created untestable code. And now you are trying to use the big powermock hammer to "fix" what is your broken design.
You see, when using static methods and constants; people think they "save" on performance (which is true; but to a very small degree; which probably doesn't matter for 99.999% of all applications); but they keep forgetting that using static leads to direct coupling of different functionalities. static is an abnormality in good OO design; and should be used with great care.
So, in your case, you could replace the whole thing with something along these lines:
interface MappingLoader {
Map<String, String> loadMappingsFrom(String fileName);
}
class MappingLoaderImpl implements MappingLoader {
...
and you see, all of a sudden you are only dealing with "real" interfaces and classes; and non-static methods; and surprise: now you can fully unit-test the whole thing; and most likely, you don't even need a mocking framework. You just create a temp file with mappings somewhere; and then you make sure that your impl class gives you the mappings from that file.
Zero mocking; zero testing of internal implementation details; just a few asserts.
And another advantage on top: all your client code that should only be using the MappingLoader interface can also be tested. Because ordinary frameworks like EasyMock or Mockito will allow you to mock out instances of that interface ... because: no static calls any more!
That is how you change the value of private final static fields - by not using them!
(and if I made you curious: watch this to learn how to write testable code from the beginning)
While I completely agree with #GhostCat's response, I understand you are looking for a solution not involving to change the source code. Have you thought of changing the contents of /tmp/mapping.properties before the test runs (and restore them later)?
static final String fields or any final static primitives fields cannot be modified in runtime. If speed honestly you can modify these fields, but your change will not affect code which uses these fields, because during compile time reference is replaced by value.
My suggestion: use static mock to Files.newInputStream()call and then return ByteArrayInputStream with expected data. In this case you will avoid fragile disk IO operation which could affect your test stability.

Spring MVC : Saving a string in servlet-context and accessing from java code

I am working on a Spring-MVC application, in which I have to save a String value which would be required in many other places but from within the java code. I checked out some solutions on net, but I only found how to declare it, not access it.
I require something like this :
<bean id="commontoAllProperty" value="String_value"/>
And access above from java code something similar to this :
class someClass {
private String getValueInBeanWithId(commontoAllProperty);
}
A very vague description but I am going nuts typing that String all the time. Its a FileSystem path by the way. Any help would be nice. Thanks a lot. :-)
You can store the value in your properties file and access it all throughout your Spring using the #Value annotation. You have an example in this blog post, note the
#Value("${msg}")
private String msg;

Java/JSTL: is it a good idea to put all URLs in an enum?

I'm working on a web app with Java servlets and JSP pages with JSTL.
I'd like to find a way to:
1) Easily refactor URLs
2) For any url, easily discover exactly what pages/servlets reference it. This way when making changes it should be easier to know the potential impact elsewhere.
I'm considering using an enum to store URLs.
Is this a good idea? If so, what's the best way to reference it via JSTL? Is there an alternative way to achieve the same goal?
//example code
public enum SiteUrl {
HOME("/"),CART("/cart"),PROFILE("/my-profile");
private final String url;
private SiteUrl(String url){
this.url = url;
}
public String getUrl(){
return url;
}
}
No. You can define all this navigation-related stuff in the deployment descriptor file(s). Putting it into code is a retrograde step.
I prefer DB rather then enum. Reasons as below:
Not easy to maintain the enum class because other people need to
update it too.
If your application is not support hot-deploy, u need to restart app
when add a new url.
Normally, u need to handle request at first, like clean parameters
part, before direct.A DB interface can do this.

Registering and updating application properties using JMX

I have to access some application through an mbean so that I can change its application properties. Now i think this can be done in two ways:
First, either I ask the developer of that application to register all the application properties in an arraylist which my mbean will access.
Secondly, if there is any other way, such that the developer will only need to register editable properties and still my mbean can access both readable/editable(r/w) application properties.
Now since I don't know where these application properties are stored in the JVM, is there a way to implement my second point so that the mbean will just need to access that object and it will get all application properties?
Seems like you have some contradicting requirements here.
You want to change minimal code in the application.
You want to be cause to expose all properties for read and/or write.
You may or may not be talking about System.getProperty(...). If not then I guess you are talking about just fields in various objects.
There are (at least) two ways of doing this. Without knowing how you are exporting the mbeans from the source code right now, I can't tailor my answer to your specific config. My answer will instead show how you might use my SimpleJMX package to expose your properties.
If you are talking about System.getProperty(...) then you could write a JMX mbean that could query any property and return the value:
#JmxOperation(description = "Query for property")
public String queryForProperty(String name) {
return System.getProperty(name);
}
If, instead, you need to export of fields from some list of objects then you are going to either have to add annotations to each fields you are exporting or you are going to have to write beans that export the fields through delegation. I see no easy way and I know of no package that will easily export a series of objects for you without some sort of information about what is to be exported and how.
Using SimpleJMX, you can export a field by annotating either the field or the get method:
#JmxAttributeField(description = "Number of hits in the cache")
private int hitCount;
...
// this can also be specified as #JmxAttributeMethod on the getter/setter methods
#JmxAttributeMethod(description = "Number of misses in the cache")
private int getMissCount() {
return missCount;
}
The #JmxAttributeField supports a isWritable = true to allow the value to be set by JMX. You can also annotation the setter with #JmxAttributeMethod to make it writable.
If you don't want to add annotations to each of your classes, then you are going to have to write some sort of JMX container class that exports the values through delegation:
public class JmxPublisher {
private Class1 object1;
private Class2 object2;
...
public JmxPublisher(Class1 object1, Class2 object2) {
this.object1 = object1;
this.object2 = object2;
...
}
#JmxAttributeMethod(description = "Number of hits in the cache")
public int getClass1HitCount() {
return object1.getHitCount();
}
#JmxAttributeMethod(description = "Shutdown the background thread")
public void setClass2Shutdown(boolean shutdown) {
return object2.setShutdown(shutdown);
}
...
}
I also think you should express yourself more clearly.
From what I understood - why not providing a way to query the remote application, and get information on all properties and if they are Read-only, Write-only or RW?
This way the list of properties will not be mentioned at the source code of the client application - maybe you should let the user of the client application see the list of properties, and let him edit the properties he can edit, and prevent him from editing the properties he can't.

Categories

Resources