Spring Boot Environment Variable in Config does not resolve - spring-boot

I have the following application.properties where I have a Service definition
service.user=${SERVICE_USER}
service.password=${SERVICE_PASSWORD}
service.url=http://someurl.com/api
In the Environment I then specify User and Password
SERVICE_USER=test
SERVICE_PASSWORD=test
The configurations is read in as follows
#Configuration
#ConfigurationProperties(prefix = "service")
public class ServiceConfiguration {
private String url;
private String user;
private String password;
// setters and getters
}
The issue is that ${SERVICE_PASSWORD} seems not to be resolved. When checking in Debugger it's exactly the value of the variable password. Therefor I can't connect to the Service as it gives the Error "Authentication failed". When I enter the values directly like
service.user=test
service.password=test
service.url=http://someurl.com/api
everything works as expected. Must Environment Variables, that are needed in the Code, be read in directly?

You can refer below configuration to read values from properties file.
#Configuration
public class ServiceConfiguration {
#Value("${service.url}")
private String url;
#Value("${service.user}")
private String user;
#Value("${service.password}")
private String password;
}

You can use prefix and do the same like this:
#Configuration
#ConfigurationProperties(prefix = "service")
public class ServiceConfiguration {
#Value("${url}")
private String url;
#Value("${user}")
private String user;
#Value("${password}")
private String password;}

Related

Spring boot properties with array

With an application.properties like that
application:
api:
clients:
api1:
url: http://url1
api2:
url: http://url2
basicAuth:
username: user2
password: password2
I can do
#Configuration
#ConfigurationProperties(prefix = "application.api")
#Data
public class ApiProperties {
private Map<String, Client> clients;
#Data
public static class Client {
private String url;
private BasicAuth basicAuth;
}
#Data
public static class BasicAuth {
private String username;
private String password;
}
}
And it is working.
But is there a way of retrieving only one client ? So In place of
private Map<String, Client> clients;
I'd like to have something like
#Value("${application.api.clients['api1']}")
private Client client1;
I tried multiple ways of writing it but I always have Could not resolve placeholder...
Is there a solution ?
Looks like this is not possible with nested properties or hierarchal properties.
#Value("${application.api.clients['api1']}")
private Client client1;
But you can try this if you want to retrieve only one client.
#Configuration
#ConfigurationProperties(prefix = "application.api.clients")
#Data
public class ApiProperties {
private Client api1;
#Data
public static class Client {
private String url;
private BasicAuth basicAuth;
}
#Data
public static class BasicAuth {
private String username;
private String password;
}
}

Spring boot using Autowire Cofiguration property class in Entity class

I have to use some set data member class in Spring entity class
Current Entity class
Entity(name="users")
public class Users{
#Id
#GeneratedValue
#Column(name=ID")
private long Id;
#Column(name=NAME")
private String name;
#Column(name=AGE")
private String age;
#Column(name=PIN")
private String pin;
public Users(String name, String age, String pin)
{
this.name = name;
this.age = age;
this.pin = pin;
}
}
Now I need to add a new Member which is unique to that place
areaId, we run sperate application per each area so this will be passed from command line arguments or config properties during application starts.
My properties class looks like below
#Component
#ConfigurationProperties("user.info")
public class UserProperties{
public String areaId;
public String getAreaID(){return this.areaId;}
public void setAreaID(String areaId){ this.areaId = areaId;}
}
users:
info:
areaId:124
I have to store this and initializes also during Users object constructing, here I am trying to make simple
Entity(name="users")
public class Users{
#Id
#GeneratedValue
#Column(name=ID")
private long Id;
#Column(name=NAME")
private String name;
#Column(name=AGE")
private String age;
#Column(name=PIN")
private String pin;
#Column(name=AREAID")
private String areaId;
public Users(String name, String age, String pin)
{
this.name = name;
this.age = age;
this.pin = pin;
this.areaId = ""//?? how to get area id directly ?
}
}
I can not change the constructor of Users because it demands changes in the other application which are using this lib
Want to Autowire a users properties class inside Entity class(but this is not suggestable as read in some articles )
What would be the best way to initialize that default kind of variable?
It seems that your property is something static.
Then get it from a static way at start.
There's several ways to get command line value at start directly or in a static block:
static {
(your code here)
}
You'll can put #Column on a getter on this property after that.

Reading property values in constructor using prefix

How to use the prefix in the below code?
Properties:
height.customer.feet=10
height.customer.eu.timezone=UTC
#Configuration
#EnableConfigurationProperties
#ConfigurationProperties(prefix = "height.customer")
public class Customer {
private final int age;
private final String timezone;
public Customer(int age, String timezone){
this.age = age;
this.timezone = timezone;
}
}
Here i want to set the default value for both age and timezone. Default values are read from application.properties file. Can someone help me please?
I could use like below.
#Value("${height.customer.age}")
private final int age;
#Value("${height.customer.eu.timezone}")
private final String timezone;
But if i use like this, i may not able to use constructor injection
There is no relationship between the #ConfigurationProperties and #Value annotation. Check here. What you should be using is the #PropertySource annotation. If you use #ConfigurationProperties then you should have hierarchical properties
#Configuration
#ConfigurationProperties(prefix = "height.customer")
public class Customer {
private final int age; // This maps to height.customer.age
private final String timezone; // This does NOT map to height.customer.eu.timezone but maps to height.customer.timezone
public Customer(int age, String timezone){
this.age = age;
this.timezone = timezone;
}
}
Use the #PropertySource with this example
#Configuration
#PropertySource("classpath: demo.properties") // your properties file
public class Customer {
#Value("${height.customer.age}")
private final int age;
#Value("${height.customer.eu.timezone}")
private final String timezone;
public Customer(int age, String timezone){
this.age = age;
this.timezone = timezone;
}
public Customer(){}
}
And there won't be a conflict with the existing constructor because, values injecting via #PropertySource will be default values. If you provide values in the constructor, these will get overridden.

SpringBoot check if injected Properties are set NotNull

I know I can easily inject a property file in SpringBoot 2.2 with the following construct
#ConstructorBinding
#ConfigurationProperties(prefix = "example")
#Data
#AllArgsConstructor
public final class MyProps {
#NonNull
private final String neededProperty;
#NonNull
private final List<SampleProps> lstNeededProperty;
public String getFirstSample(){
return lstNeededProperty.get(0); //throws NPE
}
}
#ConstructorBinding
#AllArgsConstructor
#Data
public class SampleProps {
String key;
String label;
}
and yml file like:
expample:
neededProperty: test1
lstNeededProperty:
-key: abc
label: input
The #NonNull works quite well for the String but fails for the List - since the NPE is thrown even when the list will be set.
Is there a simple way to check if the List is initialized? I've tried #Postconstruct but this isn't called at all.
Try to check for the size and intialize the list:
#ConstructorBinding
#ConfigurationProperties(prefix = "example")
public final class MyProps {
#NonNull
private final String neededProperty;
#Size(min=1)
private final List<String> lstNeededProperty = new ArrayList<>();
}

Object is not an instance of a persistable class warning with Spring boot and Neo4j

I have a pretty straightforward class called User which is supposed to create user objects containing user information and login details.
package com.example.domain;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;
import java.util.HashSet;
import java.util.Set;
#NodeEntity
public class User {
public User() {}
#GraphId
private Long id;
private String username;
private String password;
private String name;
private String email;
private String Role;
#Relationship(type="BELONGS_TO", direction = Relationship.INCOMING)
Set<Item> items = new HashSet<>();
public User(String name, String username, String password, String email) {
this.name = name;
this.username = username;
this.password = password;
this.email = email;
}
// Getters and setters below for private fields...
}
The controller creating the object looks like this:
#RequestMapping(value = "/register",method = RequestMethod.POST)
public String register(Model model,
#ModelAttribute(value="name") String name,
#ModelAttribute(value="username") String username,
#ModelAttribute(value="email") String email,
#ModelAttribute(value="password") String password,
#ModelAttribute(value="confirmPassword") String confirmPassword) {
if(!password.equals(confirmPassword)) {
model.addAttribute("error", true);
return "register";
}
User userEntity=new User(name,username,password,email);
userManagementService.save(userEntity); //<------The object is created but the error occures during persistance
return "login";
}
and my user management service looks like this:
public interface UserManagementService {
List<User> listAll();
User save(User user);
User findUser(String username);
}
What makes the User class, not an instance of a persistable class. What are the characteristics of a persistable class and how can I make User a persistable class?
Have you configured the OGM somewhere? Either in a Java configuration or in a ogm.properties file? You'll need to specify the driver type and tell the SessionFactory where to look for your domain objects.
OGM config reference: https://neo4j.com/docs/ogm-manual/2.1/reference/#reference:configuration
SessionFactory config reference: https://neo4j.com/docs/ogm-manual/2.1/reference/#reference:connecting:session-factory

Resources