Escape " (doublequote) in #Value property name - java

I have the following structure for a property:
my {
property {
item {
"1" {
value="some value"
}
"2" {
value="another value"
}
}
}
}
How do you refer to a property called "1" using the #Value annotation?
The example I have doesn't work. I tried the following options:
#Bean(name = "myProperty")
public String myProperty(#Value("${my.property.item.\"1\".value}") String myProperty) {
return myProperty;
}
#Bean(name = "myProperty")
public String myProperty(#Value("${my.property.item.'1'.value}") String myProperty) {
return myProperty;
}
#Bean(name = "myProperty")
public String myProperty(#Value("${my.property.item.1.value}") String myProperty) {
return myProperty;
}
None of which work.
Any advice appreciated!

Best way to fix that, is to just rename the properties, since java doesn't like when there are quotes inside of names.

Okay so Java definitely doesn't like the quotes in the name so my solution has instead (in my case) been to refer to the property using an alias although I realise this isn't apparent in the small example I gave (I didn't want to overcomplicate it).
In my example there's a set of property files that are imported into a Spring application.conf file.
Inside this application.conf file I put the following property:
myProperty.value=true
This overrides the other property
Then inside my original property file I simply refer to it.
my {
property {
item {
"1" {
value=${myProperty.value}
}
}
}
}
That means when I bind the property in a *Config.java file I can do:
#Bean(name = "myProperty")
public String myProperty(#Value("${myProperty.value}") String myProperty)
{
return myProperty;
}
Hope this helps people.

Related

Is there a way to check if a class is empty in java?

Sorry if the title is a bit confusing, I didn't really know how to word what I wanted to ask.
Basically, I am making an api call to a database that returns data as such:
[{"profiles":{"testexample":{"addresses":[{"city":"","street1":"","street2":"apt 320"}],"addressType":"HOME","city":"","dateOfBirth":"","emailAddress1":"","emailAddress2":"","emailAddresses":[{"email":"","preferred":1,"type":"BUSINESS"},{"email":"","preferred":0,"type":"PERSONAL"}],"firstName":"","lastName":"","phoneNumber":"","phoneNumbers":[],"phoneType":"HOME","postalCode":"","preferred":1,"street1":"","street2":""}]
The code I have below works fine when the database returns a non-empty profiles {}. I have the following Java classes that looks like the following:
public class Account {
#JsonProperty("profiles")
private Profiles profiles;
#JsonProperty("profiles")
public Profiles getProfiles() {
return profiles;
}
#JsonProperty("testexample")
public void setProfiles(Profiles profiles) {
this.profiles = profiles;
}
}
public class Profiles {
#JsonProperty("testexample")
private Profile testExample;
#JsonProperty("testexample")
public Profile getTestExample() {
return testExample;
}
#JsonProperty("testexample")
public void setTestExample(Profile testExample) {
this.testExample = testExample;
}
}
public class Profile {
#JsonProperty("dateOfBirth")
private String dateOfBirth;
#JsonProperty("dateOfBirth")
public String getDateOfBirth() {
return dateOfBirth;
}
#JsonProperty("dateOfBirth")
public void setDateOfBirth(String dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
}
So what I want to do when I get the data is check whether the getProfiles() returns empty, so I don't make the calls to anything within that object.
Please note, for the sake of simplicity I omitted other parts of the classes to focus primarily on what I wanted
This is what I have so far, and it works when the profiles {} is not empty
Account response = access.lookup(id, type); //This is to grab the response from the database, which is working.
response.getProfiles(); //This is the part that works when it has a profiles {} not empty, but fails on empty.
So what happens is that I don't get an error for response.getProfiles(), but if I tried to do response.getProfiles().getDateOfBirth(), it won't work because it will give a null pointer exception since the dateOfBirth isn't there.
I want to avoid calling anything within response.getProfiles() by skipping it if it's empty.
You need some basic null checking. The most basic way is to assign a new variable and check.
Profiles profiles = account.getProfiles();
if(profiles != null) {
//dosomething with profiles.getDateOfBirth()
}
The more "modern" functional Java way would be to use the Optional class.
String dateOfBirth = Optional.ofNullable(account.getProfiles())
.map(profile -> profile.getDateOfBirth)
.orElse(null);
(A note about your example: In the Account class, you have this.
#JsonProperty("testexample")
public void setProfiles(Profiles profiles) {
this.profiles = profiles;
}
Which appears to be an incorrect #JsonProperty annotation and might be causing some problems.
That said, it is not necessary to annotate the getters and setters. The one annotation on the field is sufficient.)

Spring not picking up value defined in properties file

I have a class with inject attributes like so:
#RestController
public class MyController {
private final String myValue;
#Autowired
public MyController(
#Value("${config.myValue}") String myValue) {
this.myValue = myValue;
}
#PostMapping("/dostuff")
public String dostuff(#RequestBody String message) {
// stuff
}
}
And then I have a config file defined inside src/main/resources/application.yml like so:
config:
myValue: "some value"
But my IntelliJ (and cmd) tell me the value is not found:
Could not resolve placeholder 'config.myValue' in value "${config.myValue}"
Why is my defined value not being recognized? (I tried renaming file to application-default.yml and application.properties but that didn't help either)
Could you please try renaming file as application.properties and define property like below and check if it works?
config.myValue = some value

Handle Json non existent keys spring boot

I am creating a requestModel and let say a person doesn't send me some keys.
If that key is not present I want to put null if i get the value of the key.
I don't want to investigate if a key is present or not .
public class CustomerModel {
private Optional<String> s3Bucket;
private Optional<String> docType;
public String getS3Bucket() {
if(s3Bucket.isPresent()) {
return s3Bucket.get();
} else {
return null;
}
}
public void setS3Bucket(Optional<String> s3Bucket) {
this.s3Bucket = s3Bucket;
}
public Optional<String> getDocType() {
return docType;
}
public void setDocType(Optional<String> docType) {
this.docType = docType;
}
}
Do we have any library or something where.
1. If i get the key and it is not present in the coming request json, i will get the null out of it and if the key is present and has value . It will be stored as value.
2. When writing the getter for s3bucket (getS3Bucket), i dont want to write it for everykey value. Is there a automatic way to do this.
I looked at lot of posts but the scenario is not there.
P.S - I am new to java
I believe Jackson is exactly what you need. And if you are using Spring - it already uses Jackson under the hood I guess.
Here you can find some examples and documentation of how JSON mapping on to model class is done.
If you need to customize some behavior, you can use annotations like #JsonProperty (there are many).
If properties in your model class have the same names as properties in JSON, most probably you won't need to provide any further configs.
Here is a simple example:
public class User {
#JsonProperty("userName")
private String name;
private int age;
// getters and setters
}
And if you have JSON like this:
{
"userName" : "Foo Bar",
"age" : 18
}
Jackson will do all the magic for you unless you need something very specific.
If something is not in JSON you get (let's say you received JSON without age) - corresponding property in model class will be null if it is object type and default value (0, false, etc.) for primitives (in our case age would be 0).

When does #JsonProperty rename object field?

#Data
public class Tests {
#JsonProperty("comment")
private String notes;
}
I know how to use #JsonProperty to rename field as another name, but when does it rename the object field? For example, notes is renamed to comment.
I try to read the source code and find that there is some relative code in com.fasterxml.jackson.databind.ser.std.BeanSerializerBase#serializeFields and com.fasterxml.jackson.databind.ser.BeanPropertyWriter#serializeAsField. But the field has already been renamed as comment. So where does #JsonProperty rename object field?
Property name resolving happens in com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector
Have a look at this fragment:
public PropertyName findNameForDeserialization(Annotated a) {
...
// Get JsonProperty value for the field
JsonProperty pann = (JsonProperty)this._findAnnotation(a, JsonProperty.class);
if (pann != null) {
// here we are !!!
return PropertyName.construct(pann.value());
} else {
return !useDefault && !this._hasOneOf(a, ANNOTATIONS_TO_INFER_DESER) ? null : PropertyName.USE_DEFAULT;
}
}
All it happens in POJOPropertiesCollector.collectAll()
I created a simple Pojo class
public class JsonTest {
#JsonProperty("greetings")
String hello;
}
and run ObjectMapper#writeValueAsString method. After debugging for a while, I found that Jackson renames property name in the following method.
com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector#_renameProperties

Spring - Set property value using annotations without using properties file

I have a bean class like, for example
class Sample {
private String message;
public void setMessage(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
and I want to set this property's value.
In Xml Configuration, I could do
<bean id = "sample" class = "Sample"
<property name = "message" value = "Hello there!"/>
</bean>
How do I achieve the same thing i.e. set property's value using Java Annotation? Now I have read that we can use #Value annotation using some properties file but cannot it be done without using properties file, doing the way I did it through xml file? Or using properties file is necessary?
I was able to do it by including #Value("Hello there!") above the setter method. But I could feel that is not a good idea. How to set the property values for different instances using Java Annotations?
Thanks.
The value inserted into the #Value can come from places other than a properties file, for example it can also use system properties.
Using the guide here as a starting point should help you understand a little better.
As a basic and mostly useless usage example we can only inject “string
value” from the annotation to the field:
#Value("string value")
private String stringValue;
Using the #PropertySource annotation allows us to work with values
from properties files with the #Value annotation. In the following
example we get “Value got from the file” assigned to the field:
#Value("${value.from.file}")
private String valueFromFile;
We can also set the value from system properties with the same syntax.
Let’s assume that we have defined a system property named systemValue
and look at the following sample:
#Value("${systemValue}")
private String systemValue;
Default values can be provided for properties that might not be
defined. In this example the value “some default” will be injected:
#Value("${unknown.param:some default}")
private String someDefault;
You have a few options, depending on your requirements. In both of these examples you can set the annotation on a setter instead of the field.
Custom PropertySource
This lets you continue using #Value with greater control for how the properties are supplied. There are a large number of PropertySource implementations, but you can always create your own.
References:
How to add custom property source to Spring's Environment
PropertySource JavaDoc
Example:
#Configuration
class MyConfiguration {
#Bean
PropertySource myPropertySource(ConfigurableEnvironment env) {
MapPropertySource source = new MapPropertySource("myPropertySource", singletonMap("myPropertyValue", "example"));
env.getPropertySources().addFirst(source);
return source;
}
}
class Sample {
#Value("${myPropertyValue}")
private String message;
public String getMessage() {
return message;
}
}
String Bean
Define a bean as a String and auto-wire it using its qualifier.
Example:
#Configuration
class MyConfiguration {
#Bean
String myPropertyValue() {
String value;
// do something to get the value
return value;
}
}
class Sample {
#Autowired
#Qualifier("myPropertyValue")
private String message;
public String getMessage() {
return message;
}
}

Categories

Resources