Managing configurations in java (initial config / save/load config) - java

I got a class Config wich looks like that:
public Class Config {
public static int someIntValue = 0;
public static String someText = "some text";
}
What i want to do now is saving and loading that config and there is also that inital config if there is no need to load another. So the config can change at any point in the programm.
What i came up with was a Singelton like pattern
public Class Config {
public static Config instance;
private int someIntValue = 0;
private int String someText = "some text";
public static Config getInstance(){
if(instance == null)
instance = new Config();
return instance;
}
public void setInstance(Config config){
this.instance = config;
}
//getter/setter
...
}
But in the end it doesnt look like the best approach and im not quite happy with it :/
Maybe you guys can help me out with a usual / "best practice" way to do that.
Best Regards
Made

I would just use java.util.Properties, or some wrapper around it. Another good approach is java bean and something like xstream to save/load stuff.

Usually in Java for configuration use properties files. And then use ResuorseBundle for reading properties.
Your "singleton" is not a Singleton in the conventional sense.
1) Field instance must be private
2) Remove SetInstance method
3) And you should make your singleton thread safe.

If you'd consider avoiding writing the boilerplate code around java.util.Properties, you can have a look at something that does it for you: OWNER API.
It's configurable to tailor your needs and it offers some additional neat features if compared to java.util.Properties (read the docs).
Example. You define an interface with your configuration parameters:
public interface ServerConfig extends Config {
int port();
String hostname();
#DefaultValue("42")
int maxThreads();
#DefaultValue("1.0")
String version();
}
Then you use it like this:
public class MyApp {
private static ServerConfig cfg = ConfigFactory.create(ServerConfig.class);
private MainWindow window;
public MyApp() {
// you can pass the cfg object as dependency, example:
window = new MainWindow(cfg);
}
public void start() {
window.show();
}
public static void main(String[] args) {
// you can use it directly, example:
System.out.println("MyApp version " + cfg.version() + " copyright (c) ACME corp.");
MyApp app = new MyApp();
app.start();
}
}
You can define the cfg object as member instance on the classes where you need, or you can pass the instance to constructors and methods where you need it.
Version 1.0.4 will be released soon and it will include also "hot reload" and many improvements.

Related

Is a Singleton pattern a good use case for RedissonClient?

I'm running a long running web service via Jetty/CometD, and I'm using the Redisson library for connecting to redis. I'm using a Singleton pattern for getting my RedissonClient/connection and I am not sure if that is the best way to go.
Class looks like this:
public class RedisClient {
// singleton instance of our RedisonClient/connection
private static RedissonClient _redissonInstance;
public static String REDIS_HOST = "my.redishost.com:6379";
private static RedissonClient setupRedis() {
org.redisson.Config config = new org.redisson.Config();
config.useSingleServer()
.setAddress(REDIS_HOST)
.setConnectionPoolSize(200);
return Redisson.create(config);
}
public static RedissonClient getRedis() {
if (_redissonInstance == null) {
_redissonInstance = setupRedis();
}
return _redissonInstance;
}
public static void setRedisHost(String redisHost) {
_logger.warn("Setting REDIS_HOST to: " + redisHost);
REDIS_HOST = redisHost;
}
}
I would say that this is a bad idea. I don't think singletons are a good idea in general but even so this is not a good way to do it. Your code is not thread-safe and it seems as if you want to support multiple hosts.
If you really don't want to pass your redis client around to every component and your host is not going to change and want something quick and dirty try this:
public class Redis {
public static final RedissonClient CLIENT;
static {
Config config = new Config();
config.useSingleServer()
.setAddress("my.redishost.com:6379")
.setConnectionPoolSize(200);
CLIENT = Redisson.create(config);
}
}
This has the benefit of being thread-safe without having any synchronization when getting the reference.

Is good to use object configuration into a Singleton?

I know this would seem to be something blasphemic and it (may) break the singleton nature so, please, don't hurt me! I'm just asking.
Assuming that the example below is just a random situation (and actually MY SITUATION, coincidence? I don't think so...) my question is generic.
I've got a singleton class like this:
public class SingleSessionFactory {
private SingleSessionFactory() {
}
private static class SingleSessionHelper {
private static final SessionFactory SESSION_FACTORY = getSingleSession();
private static SessionFactory getSingleSession() {
if (SESSION_FACTORY == null) {
Configuration hConf = new Configuration();
//hibernate configuration I wish to set by an object or sth dynamic not hard-coded!
try {
return hConf.buildSessionFactory();
} catch (ExceptionInInitializerError ex) {
System.out.println(ex.getMessage());
}
}
return SESSION_FACTORY;
}
}
public static SessionFactory getInstance() {
return SingleSessionHelper.SESSION_FACTORY;
}
}
which instead of the line //hibernate config...bla bla bla & bla... i used to call the setProperty(..) and addAnnotatedClass(..) hard-coded.
I wish to know if it's good to use a custom property object (by instance: MyHibernateConfiguration class) to use inside my getSingleSession(), which inside some attribute to store Hibernate properties (as "hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect") and annotated class. Injecting or passing or...whatever... in this way "all that things" could be passed dynamically and that would be veeeeeryveryvery cool, isn't it right?
Anyway:
Q: Is it possible?
A1: Yeah of course! And the bestt way to do that is...
A2: NO! This is madness! I'm gonna underrate this question and send you to hell! Muha-ha-ha-haaaa... (yeah, evil laugh...)
That's all folk!

Wicket: Define Application wide variable

I wanted to make a little "log" on what the user is doing. I have different panels and all of these have Ajax functions such as "onclick", "onevent" and "onchange". What I planned was to define an Application wide ArrayList of Strings to log all the things.
I wrote following into WicketApplication.java
public class WicketApplication extends WebApplication {
private List<String> log = new ArrayList<String>();
#Override
public Class<? extends WebPage> getHomePage() {
//code
}
#Override
public void init() {
//code
}
public List<String> getLog() {
return log;
}
public void setLog(List<String> log) {
this.log = log;
}}
Then in one of my panels:
public class Foo extends Panel{
private static final long serialVersionUID = 1L;
private WicketApplication wapp = (WicketApplication) Application.get();
public Foo(String id){
super(id);
}
public void bar(){
List<String> protocol = wapp.getLog();
protocol.add(foo.getBarName() + " has been added to " + selectedKontakt.getObject().getName());
wapp.setLog(protocol);
}
}
In a next panel I tried to create a new reference to WicketApplication. But it seems not to be the same.
Now I have these questions:
Isn't WicketApplication unique and therefore usable for this kind of manipulation?
Do I have to take a session for this?
Can I even parse Applcation to WebApplication? Because I have this error in the console
wapp <----- field that is causing the problem
Is there any other way to create an Application wide variable?
I think you are doing it wrong (on multiple levels).
Firstly: if you want to log, use a Logging framework. E.g. LogBack, preferably accessed through SLF4J
Secondly: if you don't want to use a log framework, create a log service (a dedicated object, not the Wicket Application), use Dependency Injection to inject the log service into all components where you need it. Wicket Supports both Spring and Guice
Third: Static access to the WebApplication as suggested by the accepted answer sounds like a very bad idea (but it is apparently suggested by Wicket, to be fair).
Normal way of use is (static) method. Its typical, don't be afraid.
MyApllication m = MyApllication.get();
So is genrally easy in every wicket object.
Usually "statically overrided" to return correct type, (and can give additional control).
public static MyApllication getMyApplication() {
return (MyApllication) get();
}
or
public static MyApllication get() {
return (MyApllication ) WebApplication.get();
}
When this static method returns correct type, Your problem is resolved.
Analyse how is build AuthenticatedWebApplication over WebApplication (or WebApplication over Application) , its from Wicket team and seems be canonical
BTW I You will have idea access / execute actions dependent on user / session similar idea exist : WebSession override in MySession

Refactoring static class so I can unit test it

I have a static class that I would like to refactor so I can change the name of the properties file etc., and to be able to unit test it easier.
Current I have this:
public enum MySettings {
INSTANCE;
//priv vars
private string applicationUrl;
private MySettings() {
MappingJsonFactory jf = new MappingJsonFactory();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream mySettingsInputStream = classLoader.getResourceAsStream("a.properties");
Properties mySettingsProperties = new Properties().load(mySettingsInputStream);
// code below to load json and set priv vars etc.
}
public String getApplicationUrl() {
return applicationUrl;
}
}
How could I set the name of the properties file to something else in my unit tests?
"Inversion of control." The simplest way to do this here would be to take it in as a constructor arg. At the higher end would be an IOC framework, such as Spring.
Worse case since you're dealing with an enum - may need to factor out an interface then provide an implementing enum. Or better:
public enum Settings {
PRODUCTION("prod.xml"), UNIT_TESTING("dev.xml");
//...
you could fiddle all the stuff from the enum class into a real instantiable class (via package protection or protected) and then make an instance of it accessible via the enum (getter). Like this you can unit test everything like a charm and also have it as a singleton :). With this you don't need a second Enum constant (as pointed out in the comments).
If you are using protected instead of package protection you can unit test it by creating a dummy class that inherits from the actual class and instantiate it in the test like this:
private static class Dummy extends NewClass {
public Dummy() {
super();
}
}

Java Properties File binding to Java Interface

With GWT you have stuff like this:
public interface LoginConstants extends Constants {
#DefaultStringValue("Wellcome to my super app")
#Key("appDescription")
String appDescription();
#DefaultStringValue("Ok")
#Key("okButtonLabel")
String okButtonLabel();
}
Then you can use from your classes doing GWT.create(LoginConstant.class), in this way the interface is backed by dynamic implementation that, when I call loginConstants.appDescription() returns the value contained from a property file using the #Key annotation to reference the key in the property file. If the property file misses the property, then de #DefaultStringValue is returned. This is used for internationalization, but can possibly work also for configuration.
But with GWT, this is meant to be used on the client side (ie. translated to JavaScript), and for i18n, not for configuration.
But, I find this idea very convenient also for configuration handling.
I wonder if somebody knows a framework to do a similar thing on the server side, without necessarily bind your code to GWT. ie. if there is any library that implements this kind of logic specifically designed for the configuration handling. I am not aware of anything like this.
Reference to the feature in GWT: https://developers.google.com/web-toolkit/doc/latest/DevGuideI18nConstants
I implemented my own solution to the question:
BASIC USAGE
The approach used by OWNER APIs, is to define a Java interface
associated to a properties file.
Suppose your properties file is defined as ServerConfig.properties:
port=80
hostname=foobar.com
maxThreads=100
To access this property you need to define a convenient Java interface
in ServerConfig.java:
public interface ServerConfig extends Config {
int port();
String hostname();
int maxThreads();
}
We'll call this interface the Properties Mapping Interface or just
Mapping Interface since its goal is to map Properties into an easy to
use a piece of code.
Then, you can use it from inside your code:
public class MyApp {
public static void main(String[] args) {
ServerConfig cfg = ConfigFactory.create(ServerConfig.class);
System.out.println("Server " + cfg.hostname() + ":" + cfg.port() +
" will run " + cfg.maxThreads());
}
}
But this is just the tip of the iceberg.
Continue reading here: Basic usage || Website || Github
I still have a couple of features in mind, but the current implementation goes a little forward than the basic functionalities described in the questions.
I need to add samples and documentation.
I loved the idea so much that I quickly assembled some code using Java Dynamic proxies.
So basically you create an interface with relevant methods and annotate them with #Key, #DefaultStringValue annotations.
Below is the sample Java code:
Main.java
package net.viralpatel;
import net.viralpatel.annotations.DefaultStringValue;
import net.viralpatel.annotations.Key;
interface LoginConstants extends Constants {
#DefaultStringValue("Wellcome to my super app")
#Key("appDescription")
String appDescription();
#DefaultStringValue("Ok")
#Key("okButtonLabel")
String okButtonLabel();
}
public class Main {
public static void main(String[] args) {
LoginConstants constants = DynamicProperty.create(LoginConstants.class);
System.out.println(constants.appDescription());
System.out.println(constants.okButtonLabel());
}
}
Also the property file in background that we load is
config.property
okButtonLabel=This is OK
Just execute the Main java class, following output will be displayed:
Output:
Wellcome to my super app
This is OK
Here is the rest of code: http://viralpatel.net/blogs/dynamic-property-loader-using-java-dynamic-proxy-pattern/
You could mimic that with spring (but I'm not sure it's worth it):
#Component
public class SomeBean {
#Value("${appDescription:Wellcome to my super app}")
private String appDescription;
#Value("${okButtonLabel:Ok}")
private String okButtonLabel;
// accessors
}
with a PropertyPlaceHolderConfigurer.
I would like to consider the CDI as the following :-
The Qualifier
#Qualifier
#Retention(RetentionPolicy.RUNTIME)
#Target({
ElementType.METHOD,
ElementType.FIELD,
ElementType.PARAMETER,
ElementType.TYPE
})
#Documented
public #interface MessageTemplate {
#Nonbinding
String baseName();
#Nonbinding
Locale locale() default Locale.ENGLISH;
#Nonbinding
String key();
}
The Producer
public class CustomizedProducer {
#Produces
#MessageTemplate(baseName = "",
key = "")
public String createMessageTemplate(final InjectionPoint ip) {
MessageTemplate configure = null;
ResourceBundle bundle = null;
try{
configure = ip.getAnnotated().getAnnotation(MessageTemplate.class);
bundle = ResourceBundle.getBundle(configure.baseName(),
configure.locale());
return bundle.getString(configure.key());
} finally{
configure = null;
bundle = null;
}
}
}
The Service Configure
public class MyServiceConfigure {
#Inject
#MessageTemplate(baseName = "com.my.domain.MyProp",
key = "appDescription")
private String appDescription;
#Inject
#MessageTemplate(baseName = "com.my.domain.MyProp",
key = "okButtonLabel")
private String okButtonLabel;
//Getter
}
The working class
public class MyService {
#Inject
private MyServiceConfigure configure;
public void doSomething() {
System.out.println(configure.getAppDescription());
System.out.println(configure.getOkButtonLabel());
}
}
Regarding to the coding above you may use the java.util.Properties instead of the java.util.ResourceBundle and provide the default member to the Qualifier as well.
If you are running these under the JavaEE 6, the CDI is already enable for you. Just put the empty beans.xml to the META-INF or WEB-INF. If you are running under the Java SE you may need a bit further work as mentioned at the Weld web site and its documentation.
I'm using the CDI as a main part of my current production project and it works quite well.
EDITED:-
The good point to use the CDI is the Scope, we may produce the #MessageTemplate as the #ApplicationScope,#SessionScoped, #RequestScoped, #ConversationScoped or the pseudo-scope as #Singleton or #Depenendent
If you annotate the MyServiceConfigure as #Named, it is ready to use at the JSF as well.

Categories

Resources