Ladies & Gentlemen,
I´m new to Java, forgive me if it´s obvious, but I haven´t found much about it.
I´d like to create dynamic properties (variables) for a class at runtime (define an object that can be altered at runtime by adding or changing properties and methods).
Reason: I want to store a data model in GAE that can be extended dynamically after compilation of the app (yes, the DataStore allows that). What properties should be added are stored in the DataStore as well (It´s like using Robots to built Robots...funny).
Python allows me to add properties at Runtime. Groovy seems to allow that, too. The only thing in the "pure" Java world indicating in that direction seems to be "Dynamic Proxies".
But I couldn´t figure out yet if they do the trick.
Java doesn't have the capability to dynamically add properties. Nor does it have the ability to dynamically create classes at runtime or change them at runtime. Java is strongly and statically typed. The best you can do is put such properties into a Map or similar.
Edit: Ok, apparently some clarifications are in order. The OP specifically mentioned GAE, which none of these methods will work on but I'll mention them since some seem to take exception to their absence.
The Java Compiler API (Java 6+) allows you to compile Java classes at runtime. Technically you could write out a Java source file to look exactly how you want, compile it and load it.
Java bytecode libraries can rewrite classes at runtime. This is used by such libraries as JPA (and others). You could modify classes this way.
What the OP is referring to however is a) in reference to working on GAE and b) more in the order of how Javascript allows you to modify classes or particular instances at runtime by dynamically adding, removing or change properties. Java certainly doesn't do this and specifically doesn't on the GAE.
The above is not an exception to this just like casting a class to char * in C++ so you can read private members doesn't mean C++ doesn't have private members. You're essentially bypassing the Java runtime with both of these methods even though they're part of Java.
Java doesn't support it. Your best bet is to store/manage in some external datastore which you can access from inside the Java code. As a basic and builtin example, you can make use of java.util.Properties API which you load on every request, or cache and reload at timed intervals, or reload programmatically. You can then store the key-value pairs in a .properties file which you just place in the classpath. Here is a Sun tutorial about the subject.
A properties file can look like
key1=value1
key2=value2
key3=value3
If you put it in the classpath, then you can load it as
Properties properties = new Properties();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
properties.load(classLoader.getResourceAsStream("file.properties"));
String key1 = properties.getProperty("key1"); // value1
Other alternatives are for example XML files (which you can access using any Java XML API) or just a database (which you can access using JDBC API).
I don't know if this is an option on GAE (I didn't checked the restrictions) and if this will suit your needs but maybe have a look at the BeanGenerator class from CGLIB (an alternative to the ugly DynaBean from BeanUtils). Quoting "Death to DynaBeans" (have a look at the post):
Not one to let my CGLIB Golden Hammer
go to waste, I have checked
in a BeanGenerator class into CVS. You
use it like so:
BeanGenerator bg = new BeanGenerator();
bg.addProperty("foo", Double.TYPE);
bg.addProperty("bar", String.class);
Object bean = bg.create();
The generated class is an real
JavaBean, which means you can use
standard bean utilities. This includes
all of the classes in the
net.sf.cglib.beans package
(BeanCopier, BeanMap, and BulkBean).
Do your part to end the tyranny of
DynaBeans!
It is possible using Dynamic Proxies. It is also possible to do this on GAE.
First create the class "SomeObject" that exposes methods to get and set property values (i.e. getProperty(name) and setProperty(name, value)).
Then, create an interface "PropertyModel" that contains the methods that you would like your generated objects to have.
Call TransparentProxy.newInstance(someObjectInstance, MyPropertyModel.class) to create a dynamic proxy.
What happens is that Java will extend your object someObjectInstance with the specified interface (btw. you could specify more than one). When you call a method on the proxy object, the method invocation will be redirected to the "invoke(...)" method defined below, you'll need to modify that code to handle both getters and setters and include some exception handling etc. But in general, this is the way dynamic proxies work in Java.
public class TransparentProxy implements InvocationHandler
{
private final SomeObject someObject;
private TransparentProxy(SomeObject someObject)
{
this.someObject = someObject;
}
public static Object newInstance(SomeObject someObject,
Class<? extends PropertyModel> propertyModel)
{
return Proxy.newProxyInstance(someObject.getClass().getClassLoader(),
new Class[] { propertyModel }, new TransparentProxy(someObject));
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
return this.someObject.getProperty(method.getName());
}
}
There is DynaClass library that can be used this way to dynamically create JavaBeans
Map<Object, Object> properties = new HashMap<Object, Object>();
roperties.put("title", "The Italian Job");
roperties.put("dateOfRelease", "new GregorianCalendar(1969, 0, 1).getTime()");
Object movieBean = BeanCreator.createBeanFromMap(properties);
Related
Just another Java problem (I'm a noob, I know): is it possible to use dynamic property binding in a Custom Control with a dynamic property getter in a Java bean?
I'll explain. I use this feature extensively in my Custom Controls:
<xp:inputTextarea id="DF_TiersM">
<xp:this.value><![CDATA[#{compositeData.dataSource[compositeData.fieldName]}]]></xp:this.value>
This is used in a control where both datasource and the name of the field are passed as parameters. This works, so far so good.
Now, in some cases, the datasource is a managed bean. When the above lines are interpreted, apparently code is generated to get or set the value of ... something. But what exactly?
I get this error: Error getting property 'SomeField' from bean of type com.sjef.AnyRecord which I guess is correct for there is no public getSomeField() in my bean. All properties are defined dynamically in the bean.
So how can I make XPages read the properties? Is there a universal getter (and setter) that allows me to use the name of a property as a parameter instead of the inclusion in a fixed method name? If XPages doesn't find getSomeField(), will it try something else instead, e.g. just get(String name) or so?
As always: I really appreciate your help and answers!
The way the binding works depends on whether or not your Java object implements a supported interface. If it doesn't (if it's just some random Java object), then any properties are treated as "bean-style" names, so that, if you want to call ".getSomeField()", then the binding would be like "#{obj.someField}" (or "#{obj['someField']}", or so forth).
If you want it to fall back to a common method, that's a job for either the DataObject or Map interfaces - Map is larger to implement, but is more standard (and you could inherit from AbstractMap if applicable), while DataObject is basically an XPages-ism but one I'm a big fan of (for reference, document data sources are DataObjects). Be warned, though: if you implement one of those, EL will only bind to the get or getValue method and will ignore normal setters and getters. If you want to use those when present, you'll have to write reflection code to do that (I recommend using Apache BeanUtils).
I have a post describing this in more detail on my blog: https://frostillic.us/f.nsf/posts/expanding-your-use-of-el-%28part-1%29
I'm developing a Scala extension to an existing Java ORM (Ebean). The goal of this project is to add as much type safety as possible to the ORM.
Instead of
Ebean.find(Product.class).fetch("name", "unit").findList()
I would finally like to be able to write something like
(objects of entity[Product] with attributes name and unit) getIt
(note that this is just a very first DSL approach).
The ORM model is already defined as
#Entity
public class {
public String name;
public String unit;
}
In order to achieve type safety at compile time for the attributes in the query, I would need to access them on e.g. a dummy object like (new Product()).name.
I think this is the best way to ensure that only such model members are used that exists on that class, but, at runtime, I need a way to recognize that this variable was accessed. Otherwise I would just call that member name and wouldn't know about this in my query.
Does anybody know a way how to achieve this? Is there a possibility to trace when a variable is accessed and to give that information, at runtime, to any other object?
I already thought about hooking into getters and setters instead of using public members in the model classes, but this would either make the query or the model very ugly. Another problem is that any additional specific methods would have to be added manually for each model.
I would be happy if anyone could suggest possible solutions. Thanks!
If you are willing to define the fields of your model objects as something like the Record Fields, what Emil suggested could work, but if you're building your solution on top of a Java ORM using custom types might be an issue. If you need to track field access I think your best bet will be runtime bytecode instrumentation using a library like CGLib or Javassist. You can pass an instrumented "dummy" object into the body of your function, then track which field was accessed in a thread local. That's how it's done in Squeryl.
You could take a gander at how the Lift folks have implemented Mapper and Records. It allows for type safe queries using companion objects (as well as using raw sql). It does require inheriting traits into your model and the fields are specified as objects and not regular vals. Might be helpfull though. You can find the source for the persistance stuff here.
do you know if there is anyway that I can populate a javabean but i don't want to use reflection.
For example I have this xml template to pouplate it
Sample XML File
<property name = "card" value = "cdd"/>
public class Customer {
private String card;
public void setCard(String card) {
this.card = card;
}
public String getCard() {
}
}
I want to call setCard on the Java bean but I don't want to use reflection
since I've used it before and it's quite slow,
Are there any alternatives? How does Hibernate do it for example?
Thanks
Carlo
The only faster way (i.e. faster than using reflection) to populate a JavaBean from XML is to either write or generate some binding code that calls the setters with values extracted from the XML (in this case, from the XML attributes).
Hand writing the binding code is the simplest approach ... provided you don't have much to write.
Code could be generated as source code and compiled.
Code could be generated using a bytecode generation technology such as BCEL or ASM.
There may some existing XML-to-JavaBean binding generator, though existing bindings may well use reflection rather than code generation.
However, it is not clear this is worth going to the bother of avoiding reflection. While reflection is relatively expensive, XML is probably significantly more expensive. I'd recommend doing some profiling before you decide to use a more complicated implementation approach.
I'm pretty sure Hibernate uses reflection APIs deep under the hood. Groovy also has some nice support for automatically generating and using bean getters/setters which also ultimately use reflection under the hood as well.
Now there is an option where you could hard code your parser to read the xml and call the appropriate setter given the name attribute, but you run into the problem of your parser becoming brittle (when your model changes if that makes sense).
If the Bean is your's you may implement an interface like this:
/** Tries to set the property named key with the value given and returns true for success or false otherwise. */
boolean set(String key, Object value);
Then simply cast to that interface and try to use that method to set the properties. It sure needs some work in the bean - but avoids reflection.
I have a series of application properties which all have different types.
The types could include, booleans, dates, timestamps, or strings.
I need to be able to provide the ability for administrative users to change these properties and have the system to remember / persist them to a file.
I am looking for a best practice way to store these application properties and be able to persist them on change and load them on start up.
Message from the future: the link is already dead.
Java has a facility built specifically for this purpose - Properties.
Here is very good article about it
https://docs.oracle.com/javase/tutorial/essential/environment/properties.html
Since you have a requirement of storing and reading various properties of different types like boolean, integers, etc. I think the java.util.prefs API is a good choice for you. It allows you to store and read various data types.
Here's the API documentation
java.util.Properties is the easiest way. A Properties object can be created from a properties file (a file containing properties in the format name=value) or even a simple XML file. You can modify the object in memory and then write it back to a properties or XML file.
If you need more flexibility in structuring the properties, you can consider designing your own XML configuration file, although it will be a bit more work to read and write. You can however use a marshalling/unmarshalling API like JAXB, XStream etc to make that task easier.
These files can easily be modified manually as well.
Assuming you are using Java, take a look at apache commons DatabaseConfiguration (http://commons.apache.org/configuration/apidocs/org/apache/commons/configuration/DatabaseConfiguration.html).
Basically, what it does is pretty simple. It scans a table that has key-value pairs and exposes that table as a java.util.Properties. You can use this to load your application properties from the database.
Once loaded, you can cache these properties in your application. Remember to invalidate this cache whenever you make changes to the application properties.
I use this code and it works quite good for me (only partial code, coding from memory..):
(This is used in conjunction with the Properties class of java, but it makes it easier to add properties and keep your property file template in sync.)
to use:
Date date = Conf.value(Prop.SOME_DATE,Date.class);
and
enum Prop {
SOME_DATE(Date.class, "2009-10-28", "Some date"){
Object parse(String value){
return new Date(value);
}};
private final Class<?> type;
private final String description;
private final Object default;
Properties(Class<?> type, String defaultValue, String desc){
this.type = type;
this.description = desc;
this.default = this.parse(defaultValue);
}
abstract Object parse(String value);
}
and
class Conf {
private static final String PROP_FILE_NAME = "some.properties";
private volatile Map<Prop,Object> store;
public void load(){
//Read from property file and use default if not given.
//I code it in a way that it will not permit null as value, so
//if default is null the user is forced to provide setting.
}
public <T> T value(Prop prop, Class<T> clazz){
return (T)this.store.get(prop);
}
public static void main(String[] args){
//code to autogenerate property file
//Something like:
//#Default : 2009-10-28 Description : Some date. Type:Date
//#SOME_DATE=2009-10-28
}
}
The class argument makes the method a little verbose, but sometimes it is irritating if you can only let java infer the type, like this:
CountDownLatch latch = Conf.value(Prop.SOME_INTEGER);
//Compilation error! Since it expects int and won't unbox.
CountDownLatch latch = Conf.value(Prop.SOME_ITEGER,Integer.class);
//Verbose, but works everytime. Of course you could get a
//ClassCastException, but you should notice that early
//in the development...
You can store them in your Database, however due to the difference in data types of your properties you'll have to store them in their String representation. You could use another column to specify maybe the data type.
That form of application parametrization is something you've used successfully at my work. That's the general idea, I hope you could arrive to your solution with this.
You can use SQLite
Firefox uses it to persist properties
Even though you should use Preferences API or Properties, here is a hack that might also work:
Create a HashMap<String, Object> and use XMLEncoder/XMLDecoder for saving/loading. Most of the standard java classes can be serialized this way as java beans. You can make a simple wrapper class for getting various properties, handling default values etc. This way you can also store nested collections which is handy sometimes. It's really easy to implement.
Is there way to get properties files as strongly typed classes?
I guess there are code generators but doing it with annotations would be much cooler.
What I mean is;
foo.properties file
keyFoo = valuefoo
keyBar = valuebar
maybe with
#properties(file="foo.properties")
class foo { }
becomes
class foo {
String getKeyFoo() { }
String getKeyBar() { }
}
if not shall I start an open source project for that?
ADDITION TO QUESTION;
Think we have a foo.properties file with let say more than 10 entries;
and think it is used as a simple configuration file. What I believe is that this configuration entries should be provided as a configuration class with related getXXX methods to other parts of the design. Then rest of the system accesses the configuration via provided class instead of dealing with key names and don't need to bother where configuration comes. Then you can replace this class with a mock when you are testing callers and dependency to file system goes away. On the other hand it is really nice to
get all entries in a strongly typed fashion.
So this issue is a code generation issue behind the scenes, it is nothing related to runtime. But code generation with an external something instead of annotations didn't seemed nice to me. Although I am not very much familiar with annotations, I guess this could be achieved (but I'll keep in mind that annotations can not generate classes as McDowell points)
There are countless of framework that achieve that for XML with various degree of configuration needed. The standard one bundled with Java is JaxB but it is not exactly a one liner xml persistence framework ...
The problem is that using properties file will only works better than XML (or JSON, ...) on the most trivial classes. When the class become a bit more complex, the properties file will become a nightmare. Another problem is that with trivial classes - there is not much difference between Xml and properties.
That means that the scope of the project will be rather limited. Mostly useful for project having loads of simple properties files.
In big application I worked with, strongly-type reading of properties file is done quite often using a simple factory-method.
Foo foo = Foo.loadFrom("foo.properties");
class Foo {
static Foo loadFrom(String fileName) {
Properties props = new Properties();
props.load(...);
Foo foo = new Foo();
foo.setKeyFoo(props.get("KeyFoo"));
...
return foo;
}
...
}
There is a somewhat similar project for doing configuration as statically typed files. It requires to declare an interface, but it fills in the implementation itself:
public interface AppConfig extends Config {
long getTimeout ();
URL getURL ();
Class getHandlerClass ();
}
The Annotation Processing Tool (apt) cannot modify classes (though it can create new ones). In order to modify the class at compile time, you'd probably need to edit the AST (as Project Lombok does). The simplest approach would probably be to generate the classes and then use the generated library as a dependency for other code.
Yet another way is to use a data binding framework that does this. Even one that does not seem to directly support that could work: for example, Jackson JSON processor would allow this to be done by something like:
ObjectMapper m = new ObjectMapper();
MyBean bean = m.convertValue(properties, MyBean.class);
// (note: requires latest code from trunk; otherwise need to write first, read back)
which works as long as entries in Properties map match logical bean properties, and String values can be converted to matching underlying values.
Something like JFig (ugly IMO), Commons Configuration or EasyConf?
If you want to do it statically, its a code generation problem that may be solved quite easily (for each item in file, produce a new getXXX method).
But if you want this at runtime, then you have the problem of having your code referencing method that did not exists at compile time; I don't think it can be done.
(Note that if you are looking for a project idead, the reverse, having an interface with accessor method and annotation, and an implementation generated at runtime, that relies on the annotated methods, can be done.)
The OP would like to map a property file to a Java API such that each named property in the file corresponds to a similarly named getter method in the API. I presume that an application would then use this API to get property values without having to use property name strings.
The conceptual problem is that a property file is fundamentally not a statically typed entity. Each time someone edits a property file they could add new properties, and hence change the "type" of the property file ... and by implication, the signature of the corresponding API. If we checked that there were no unexpected properties when the Java app loaded the properties file, then we've got an explicit dynamic type-check. If we don't check for unexpected (e.g. misnamed) properties, we've got a source of errors. Things get even messier if you want the types of property values to be something other than a String.
The only way you could do this properly would be to invent the concept of a schema for a property file that specified the property names and the types of the property values. Then implement a property file editor that ensures that the user cannot add properties that conflict with the schema.
And at this point we should recognize that a better solution would be to use XML as the property file representation, an XML schema driven editor for editing property files, and JAXP or something like it to map the property file to Java APIs.
I think this will solve your problem
I have written on this property framework for the last year.
It will provide of multiple ways to load properties, and have them strongly typed as well.
Have a look at http://sourceforge.net/projects/jhpropertiestyp/
It is open sourced and fully documented
Here is my short description from SourceForge:
JHPropertiesTyped will give the developer strongly typed properties. Easy to integrate in existing projects. Handled by a large series for property types. Gives the ability to one-line initialize properties via property IO implementations. Gives the developer the ability to create own property types and property io's. Web demo is also available, screenshots shown above. Also have a standard implementation for a web front end to manage properties, if you choose to use it.
Complete documentation, tutorial, javadoc, faq etc is a available on the project webpage.