How to persist configuration settings in Spring? - java

I have a set of configuration settings (key/value) pair, which is meant for customization (through an admin panel for example) through Spring MVC. Are there any wide-accepted way of accomplishing this?
One has suggested using a one-row table to persist, but other has dismissed this as a bad design. What are my options? I am thinking that a property file should be sufficient in this case, but it is not exactly clear to me how to map this property file to a java object, as a model, save and update it ...
Thanks for your help
Oliver

Where I work we often simply have a configuration table with two columns, one for key, one for value. This seems to work well. This is context-less, but can be put into context simply by adding another column for 'customer_id' for example, or 'site_id'.
class ConfigurationValue {
String key, String value;
// blah, blah
}
Then just use the JDBC template to do reads/inserts/etc...
No magic here.

java.util.Properties gives you a simply interface to read/write .properties files in Java. That might be suitable for your case, but depends largely on your application.

Related

Java - Model class with so many properties vs one single HashMap<key,value>

I am trying to read multiple text files ( each file having different layouts / schema's).
Currently my Model class have more than 40 properties and its kind of hard coded.
I am planning to use HashMap<>, so everytime any new file comes, i can read the file without changing the model class by adding more properties.
But is this correct way to do it?
Please advise.
Both approaches have their pros and cons. Map gives you flexibility for schemas unknown in advance but could become nightmare in maintenance, and it is not error safe - i.e. your types are not checked. The bean with predefined properties is the opposite. In general it is better option but you will have to change it every time the schema changes. You can have a combined approach. Say you have a set of properties that will always be there. And then you may or may not have some other properties that are unknown in advance. So you have a bean with predefined setters and getters and add another setter and getter for a Map property that will deal with unknown properties. I hope this helps

Freemarker Customize TemplateCache storage want to read the information from TemplateKey

I have my own customized freemarker template storage configured over freemarker, it is working fine.
Recently I want to make some changes on the cache management, I need to read the properties from the cache key which is typeof "TemplateKey". Unfortunately the "TemplateKey" is "private final static class". I have no access to this class and I cannot cast the Key object back into TemplateKey object.
I see the simplest way is to make source code change in TemplateCache.java to update the TemplateKey to be expose as public class.
Question to Freemarker designer: Is it any special reason to make this TemplateKey not be exposed? Is it possible to expose it in next build?
Thanks.
Rocky
At the first glance, I would keep the key class private, because exposing it would introduce a backward-compatibility constraint that can be in the way of further development. But what exactly is your use case that require information from the key?
We disabled localelookup, in this case, one FTL file are working for all locales. But the key includes locale, so sampe template was cached per locale, it is duplicated in memory.
One solution is: remove locale in key when manage it in cache, so I need read key properties. But it still need combine with other changes such as make template clone-able.
Please refer to this POS for detail: Freemarker Template Cache are in same content when locale are different, is it a concern on wasting memory?
Thanks.

How to use map lookups using Log4j2?

I have been looking over these three sites on how to create a map lookup (or any other lookup for that matter) using log4j2:
http://logging.apache.org/log4j/2.x/manual/extending.html#Lookups
http://logging.apache.org/log4j/2.x/manual/lookups.html
http://logging.apache.org/log4j/2.x/manual/configuration.html#PropertySubstitution
I understand the general idea behind what I am reading, I am just having a difficult time putting all the bits and pieces together.
Goal
To be able to place a variable, of some sort, in a log4j2.xml file that at configuration time, or runtime, replaces that variable with the values in a resource bundle. This is what i have so far:
Configuration File
Lookup Class
The getValue(key) method looks in a resource bundle for the email values associated with that key.The #Plugin name is "map" which, if i have read correctly, is related to prefixes in the .xml file that are also "map". So, wouldn't "error.notification.emails" get passed into the lookup(String key) method in the MapPropertiesLookup class? What do i need to do in order to get this to work?
Yes, map is the name of the lookup you are creating. Since Log4j already has a Lookup named map creating another is going to cause problems.
Yes, error.notification.emails should be passed as the key value to the Lookup. Assuming that getValue(key) works your lookup would probably work if it was named something else.
However, it might make more sense for you to file a Jira and ask for a ResourceBundleLookup where the syntax could be something like: ${bundle:bundleName:key}. Of course, "bundleName:key" would be passed to the lookup as the key and it would split the key into the component parts.
If you have further problems you might consider asking on the Log4j developers mailing list.
I added a new lookup for the next release (whether it is a beta or release candidate):
Committed revision 1531064.
You can use it now if you build Log4J from source. The format is documented if you build the site, it is used as follows:
${bundle:BundleName:BundleKey}
For example:
${bundle:com.domain.Messages:MyKey}
The java.util.ResourceBundle class will look for com/domain/Messages.properties on the classpath.
Our JIRA issue: https://issues.apache.org/jira/browse/LOG4J2-420

Loading Settings - Best Practices

I'm at the point in my first real application where I am adding in the user settings. I'm using Java and being very OO (and trying to keep it that way) so here are my ideas:
Load everything in the main() and
pass it all 'down the line' to the
required objects (array)
Same as above, but just pass the
object that contains the data down
the line
Load each individual setting as
needed within the various classes.
I understand some of the basic pros and cons to each method (i.e. time vs. size) but I'm looking for some outside input as to what practices they've successfully used in the past.
Someone should stand up for the purported Java standard, the Preferences API... and it's most recent incarnation in JDK6. Edited to add, since the author seems to savvy XML, this is more appropriate than before. Thought I believe you can work XML juju with Properties too, should the spirit take you.
Related on SO: Preferences API vs. Apache solution, Is a master preferences class a good idea?
(well, that's about all the standing up I'm willing to do.)
Use a SettingsManager class or something similar that is used to abstract getting all settings data. At each point in the code where you need a setting you query the SettingsManager class - something like:
int timeout = SettingsManager.GetSetting("TimeoutSetting");
You then delegate all of the logic for how settings are fetched to this single manager class, whose implementation you can change / optimize as needed. For instance, you could implement the SettingsManager to fetch settings from a config file, or a database, or some other data store, periodically refresh the settings, handle caching of settings that are expensive to retrieve, etc. The code using the settings remains blissfully unaware of all of these implementaton decisions.
For maximum flexibility you can use an interface instead of an actual class, and have different setting managers implement the interface: you can swap them in and out as needed at some central point without having to change the underlying code at all.
In .NET there is a fairly rich set of existing configuration classes (in the System.Configuration) namespace that provide this sort of thing, and it works out quite well.
I'm not sure of the Java equivalent, but it's a good pattern.
Since configuration / settings are typically loaded once (at startup; or maybe a few times during the program's runtime. In any way, we're not talking about a very frequent / time-consuming process), I would prefer simplicity over efficiency.
That rules out option number (3). Configuration-loading will be scattered all over the place.
I'm not entirely sure what the difference is between (1) and (2) in your list. Does (1) mean "passing discreet parameters" and (2) mean "passing an object containing the entire configuration"? If so, I'd prefer (2) over (1).
The rule of thumb here is that you should keep things simple and concentrated. The advantage of reading configuration in one place is that it gives you better control in case the source of the configuration changes at some point.
Here is a tutorial on the Properties class. From the Javadocs (Properties):
The Properties class represents a
persistent set of properties. The
Properties can be saved to a stream or
loaded from a stream. Each key and its
corresponding value in the property
list is a string.
A property list can contain another
property list as its "defaults"; this
second property list is searched if
the property key is not found in the
original property list.
The tutorial gives the following example instantiation for a typical usage:
. . .
// create and load default properties
Properties defaultProps = new Properties();
FileInputStream in = new FileInputStream("defaultProperties");
defaultProps.load(in);
in.close();
// create application properties with default
Properties applicationProps = new Properties(defaultProps);
// now load properties from last invocation
in = new FileInputStream("appProperties");
applicationProps.load(in);
in.close();
. . .
You could, of course, also roll your own system fairly directly using a file-based store and an XML or YAML parser. Good luck!
We have recently started using JSR-330 dependency injection (using Guice from SVN) and found that it was possible to read in a Properties file (or any other map) and bind it inside Guice in the module in the startup code so that the
#Inject #Named("key") String value
string was injected with the value corresponding to the key when that particular code was called. This is the most elegant way I have ever seen for solving this problem!
You do not have to haul configuration objects around your code or sprinkle all kinds of magic method calls in each and every corner of the code to get the values - you just mention to Guice you need it, and it is there.
Note: I've had a look at Guice, Weld (Seam-based) and Spring which all provide injection, because we want JSR-330 in our own code, and I like Guice the best currently. I think the reason is because Guice is the clearest in its bindings as opposed to the under-the-hood magic happening with Weld.

Dynamically create table and Java classes at runtime

I have a requirement in my application. My tables won't be defined beforehand.
For example, if a user creates a form by name Student, and adds its attributes like name, roll no, subject, class etc, then on runtime, there should be a table created by name student with columns name, roll no, subject, class etc. And also its related class and its Hibernate mapping file.
Is there any way of doing so?
Thanks in advance,
Rima Desai
Hibernate supports dynamic models, that is, entities that are defined at run-time, but you have to write out a mapping file. You should note a couple things about dynamic models:
You may be restricted in how you define these at run-time (viz. you will have to use the Session directly instead of using a helper method from HibernateTemplate or something like that).
Dynamic models are supported using Maps as the container for the fields of an entity, so you will lose typing and a POJO-style API at run-time (without doing something beyond the baked-in dynamic model support).
All of that said, you didn't mention whether it was a requirement that the dynamically defined tables be persistent across application sessions. That could complicate things, potentially.
It's possible, but it's not clear why would you want to do something like that, so it's hard to suggest any specific solution.
But generally, yes, you can generate database tables, hibernate classes and mappings dynamically based on some input. The easiest approach is to use some template engine. I've used Velocity in the past and it was very good for this task, but there are others too if you want to try them.
EDIT:
Following OP clarification the better approach is to use XML to store user defined data.
The above solution is good but it requires recompiling the application whether forms are changed. If you don't want to stop and recompile after each user edit, XML is much better answer.
To give you some head start:
#Entity
public class UserDefinedFormData {
#Id
private long id;
#ManyToOne
private FormMetadata formMetadata;
#Lob
private String xmlUserData;
}
Given a definition of the form it would trivial to save and load data saved as XML.
Add a comment if you would like some more clarifications.
last week I was looking for same solution and then I got idea from com.sun.tools.javac.Main.compile class, you create the Entity class using java IO and compile using java tools, for this you need tools.jar to locate on CLASS_PATH, now I am looking for run time hibernate mapping without restart.
some one was saying in the post regarding to this type of requirement that "but it's not clear why would you want to do something like that" answer is this requirement is for CMS(Content Management System). and I am doing the same. code is as below.
public static void createClass()
{
String methodName=“execute”;
String parameterName=“strParam”;
try{
//Creates DynamicTestClass.java file
FileWriter fileWriter=new FileWriter(fileName,false);
fileWriter.write(“public class “+ className +” {\n”);
fileWriter.write(“public String “+methodName +“(String “+parameterName+“) {\n”);
fileWriter.write(“System.out.println(\” Testing\”);\n”);
fileWriter.write(“return “+parameterName +“+ \” is dumb\”;\n }\n}”);
fileWriter.flush();
fileWriter.close();
String[] source = { new String(fileName) };
com.sun.tools.javac.Main.compile(source);
}

Categories

Resources