What I want to do is quite straight forward. I want to create a config object in my code and some of the values should be references. I then want to save that config to a file and later, when reading it, the references will be substituted with the correct value.
I use lightbends typesafe config library and the scala wrapper pureconfig (but don't mind about pureconfig)
Now to read and substitute values correctly the config needs to look something like this:
"name" {
"someNormalValue" : "v"
"subsitute" : ${substitute-value}
}
The question is, how can I actually generate such a config using the mentioned library.
Ps. I'm looking for a nicer solution than just rendering the config and going back to 'manually' remove the double quotes around ${substitute-value}
Thanks for you responses!
Related
I have a configuration property that needs to be sent to another system as part of a post body.
lets say for example if have an application.properties file with
my.property.raw=${parameter:some-identifier}
I also have a #ConfigurationProperties annotated class that might look like this
#ConfigurationProperties(prefix = "my.property")
public class Properties {
private String raw;
// getters and such
}
The problem i have is that Spring will see ${parameter:some-identifier} and immediately assumes i want it to be injected with a property names "parameter" and if its not there, put "some-identifier". i have tried to set the property to ${parameter:${parameter:some-identifier}} but Spring seems to have accounted for recursive property injection and it still comes out as "some-identifier".
I know i can write some code around that and replace the ":" with something else and change it back after the fact but i'm trying to make this work without any code change.
So in summation, Spring boot sees this as a configuration property ${parameter:some-identifier} upon injection into the ConfigurationProperties annotated class, the value ends up being some-identifier. What i want to happen is the value in the Properties class after Spring does its variable replacement process is ${parameter:some-identifier} as this injectable format of a value is intended for a down stream system that is expecting that format. Preferably, without changing any code. Maybe there is some special formatting i can use to tell spring to ignore this specific property.
Thanks for your time! and yes i realize this is probably the opposite of what people normally want from Spring.
As stated by #Kayaman this is indeed a duplicate of
Escape property reference in Spring property file
The solution i pulled from there, with some modification, was this:
${dollar:$}{parameter:some-identifier}
https://stackoverflow.com/a/48897422/4621716
I did this because i also don't have control over the process that is generating that application.properties beyond changing existing values.
I hope this helps and i wish i could give #Kayaman credit for pointing me in the right direction but i guess i'll accept my own answer. Thanks.
I'm parsing json with Gson but I'm struggling with the data I'm getting. This is part of an API out of my control (openFDA) so changing that might not be an option.
Here's the json I'm strugling with: https://api.fda.gov/device/event.json?search=device.generic_name:generator&limit=10
There are some fields that are not consistent, for example remedial_action. Sometimes it comes out like this:
"remedial_action": [
"Recall"
]
and in other results like this:
"remedial_action": ""
So it's either an array or a plain string. Is there a way to handle this? If not possible in Gson, any other json parsing library that can help?
I created my pojos here in case someone needs the code. There are a few files created from that and didn't want to spam them here. I can add them if needed.
Update: The bug has been confirmed and it's scheduled for a fix.
It is possible through GSON, by using a TypeAdapter.
Here are the initial steps I would use to do that:
Create a POJO that contains the array and the String. Let's call it RemedialAction.
In your original POJO, create an attribute of the new class.
Create a class that extends TypeAdapter<RemedialAction>.
Override the read() and write() methods and create the logic in them.
That should be a little hard to parse, though. Read this tutorial for more information.
Note: you can customize getRemedialAction() to give you only the valid return -- array or String.
For example, I have a JSON format like this:
{"class":"MySpecialClass", "attri1":"value1", "attri2":"value2"}
I would like to create a Object, which is a MySpecialClass Object, and get two attribute, attri1 and attri2 with the value of value1 and value2.
Here is the requirement:
I have a class file, named, MySpecialClass, and have attri1, and attri2, can I create this object, and assign the value in this?
I DONT'T have the class file MySpecialClass, I would like to generate it on the runtime, is this possible to do so? Thanks.
Your first case is perfectly feasible using any Java/JSON parser.
Your second case is possible, but hard work.
You can construct classes at runtime using bytecode engineering - e.g. using Apache BCEL. Note that the JSON will contail fields only, and not behaviour nor type.
Take a look at https://github.com/google/gson it does what you want
You want a JSON processor, like Jackson. I'm not sure you can easily do your second case this way, for that you may be best looking at a JVM JavaScript implementation unless you want to get into stuff like on the fly bytecode manipulation. There's one in the Java6 runtime.
Does exist any method in witch i can add a wildcard into a properties file, and have the meaning of everything, like a.b.*.c.d=lalalala, or set a regex for all that ends in a.b.c=anything?
A normal Java properties file doesn't handle this, no. Bear in mind that it's a hashtable really, usually mapping strings to strings.
It sounds like you probably want to create your own class for this - but perhaps you could use a Properties object as a simple way of inserting the data?
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.