Attributes in property file returns null - java

I have a DBconfig property file with the attributes as follows;
DB_url = jdbc:mysql://localhost:8080/studentdb
DB_username = root
DB_password = abc123
i want to print the values inside my a Database service class (DBconnect.class),
#PropertySource("classpath:DBconfig.properties")
public class DBconnection {
private Connection con= null;
#Value("${DB_url}")
private String url;
#Value("${DB_username}")
private String username;
#Value("${DB_password}")
private String password;
public DBconnection() {
System.out.println(url); // Output = null
System.out.println(username); // Output = null
System.out.println(password); // Output = null
}
}
the exact same code works and the values are printed when i try to print the values from the controller;
#Controller
#PropertySource("classpath:DBconfig.properties")
public class HomeController {
#Value("${DB_url}")
private String url;
#Value("${DB_username}")
private String username;
#Value("${DB_password}")
private String password;
#RequestMapping(value="/", method=RequestMethod.GET)
public String Message() {
System.out.println(url); //jdbc:mysql://localhost:8080/studentdb
System.out.println(username); //root
System.out.println(password); //abc123
DBconnection conn = new DBconnection();
return "home";
}
}
why does it work in the controller and not my Service package ? how do i get this to work in my service package ?
I only have 2 packages in src/main/java;
controller package( HomeController.class included)
service package (DBconnect.class included)
src/main/resources contain the DBconfig.properties file

When you use #Value, the Spring container when inject the value via BeanPostProcessor
Hence in your constructor, your value are all null.
In your controller, you can access the injected value because the bean now fully instantiated
If you want to access your injected value in service, add #Configuration to your class and add #PostConstruct annotation to your method:
#Configuration
#PropertySource("classpath:DBconfig.properties")
public class DBconnection {
#PostConstruct
public void init() {
System.out.println(url); //jdbc:mysql://localhost:8080/studentdb
System.out.println(username); //root
System.out.println(password); //abc123
}
}

Related

Spring Boot create #Bean based on #Values

I want to get values from my application.properties from spring.datasource.* fields but those fields are null.
Here is what I'm doing:
#Configuration
#ComponentScan
public class DatabaseConfig {
#Value("${spring.datasource.url}")
private String url;
#Value("${spring.datasource.username}")
private String username;
#Value("${spring.datasource.password}")
private String password;
#Bean(name = "database_url")
public String getDatabaseUrl() {
return url+"?user="+username+"&password="+password;
}
}
application.properties
spring.datasource.url=jdbc:postgresql://db:5432/endlessblow_db
spring.datasource.username=kuba
spring.datasource.password=pass
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.platform=postgres
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
this db in url is my docker postgre container host and it works fine.
EDIT
DatabaseConnection.java
public class DatabaseConnection {
private String databaseUrl;
#Autowired
void setDatabaseUrl(#Qualifier("database_url") String databaseUrl) {
this.databaseUrl = databaseUrl;
}
private static DatabaseConnection instance;
private Connection connection;
private DatabaseConnection() {
try {
Class.forName("org.postgresql.Driver");
this.connection = DriverManager.getConnection(databaseUrl);
} catch (Exception ex) {
System.out.println("Database Connection Creation Failed : " + ex.getMessage());
}
}
public Connection getConnection() {
return connection;
}
public static DatabaseConnection getInstance() throws SQLException, URISyntaxException, IOException {
if (instance == null) {
instance = new DatabaseConnection();
} else if (instance.getConnection().isClosed()) {
instance = new DatabaseConnection();
}
return instance;
}
}
What's wrong with this code? Thank you!
For some reasons #Value annotated fields are not initialized I guess. try sending values as #Bean method params.
#Configuration
#ComponentScan
public class DatabaseConfig {
#Bean(name = "database_url")
public String getDatabaseUrl(#Value("${spring.datasource.url}") String url,
#Value("${spring.datasource.username}")String username,
#Value("${spring.datasource.password}") String password
) {
return url+"?user="+username+"&password="+password;
}
}
String is immutable class, meaning each time a new String is created normally a new String might be created in the string pool and a new reference might be returned.
For this reason you can't have String object as a bean in your application context.
#Bean(name = "database_url")
public String getDatabaseUrl() { <----------------The return type of String is wrong
return url+"?user="+username+"&password="+password;
}
So just create a custom object in this #Bean method which could be transferred and used in the application context
Why not return a DatabaseConnection from that #Bean method this would seem the optimal solution in your problem.
You have to create a new file where you 2st read data from property file
#Configuration
#Getter
#Setter
#ConfigurationProperties(prefix = "spring.datasource")
public class DatabaseLoginProperties{
private String url;
private String username;
private String password;
}
----Now above value you can uses in your java file -------------------
#Configuration
public class DatabaseConfig {
#Autowired
private DatabaseLoginProperties databaseLoginProperties;
#Bean
public String getDatabaseUrl() {
return databaseLoginProperties.getUrl()+"?user="+databaseLoginProperties.getUsername()+"&password="+databaseLoginProperties.getPassword();
}
}

service annotated class throws nullpointer exception on a repository call

In a Spring application, I have a class called Utility.java and the class is annotated with the #Service annotation. In that class I am trying to fetch a user in a function to be used globally in the project.
Upon calling the user in a controller using the utility method created it throws nullpointer exception from the repository. Below is the code
//Utility.java file
#Service
public class Utility{
#Autowired static UserDao userDao;
public static User findActiveUser(String auth){
System.out.println("here is the username: " + auth);
User user = null;
try {
user = Utility.userDao.findBy...("user1", "ACTIVE"); //throws null here
}catch (Exception ex){
ex.printStackTrace();
}
return user;
}
//Controller annotated class
#Autowired Utility utility;
#GetMapping(value = "/success")
public String success(Authentication auth,HttpServletRequest request){
if (auth == null) {
return "index";
}
System.out.println("#dashboard success");
User user = utility.findActiveUser(auth.getName());
Everything look fine and good to go but still not working
You can't #Autowired a static field.
You have to remove static word from this line #Autowired static UserDao userDao; or implement additional logic to autowire value to the static field.

How to inject List of bean properties by spring SpEL?

I have a properties file for defining dynamic endpoints (name, host and port).
So I created a bean named EndPoint with name, host and port as member variables.
How to inject server's host and port dynamically by using Spring #Value and SpEL?
endpoint.properties
names=server1,server2,server3
endpoint.server1.host=192.168.1.101
endpoint.server1.port=10101
endpoint.server2.host=192.168.1.102
endpoint.server2.port=10102
endpoint.server3.host=192.168.1.103
endpoint.server3.port=10103
EndPoint.java
public class EndPoint {
/** name */
private String name;
// hardcode server1 here
// how to inject server's host dynamically by name?
// #Value("${endpoint.#{this.name}.host}")
#Value("${endpoint.server1.host}")
private String host;
#Value("${endpoint.server1.port}")
private int port;
public EndPoint(String name) {
this.name = name;
}
}
EndPointBeanConfig.java
#Configuration
#PropertySource( //
value = { "classpath:conf/endpoint.properties" }, ignoreResourceNotFound = true//
)
public class EndPointBeanConfig {
#Autowired
private Environment env;
#Bean(name = "endPoints")
public List<EndPoint> endPoints() {
final List<EndPoint> endPoints = new ArrayList<EndPoint>();
final String[] names = env.getProperty("names").split(",");
for (final String name : names) {
final EndPoint endPoint = endPoint(name);
endPoints.add(endPoint);
}
return endPoints;
}
#Bean(name = "endPoint")
#Scope("prototype")
public EndPoint endPoint(String name) {
return new EndPoint(name);
}
}
I am just giving suggestion, Go with YAML/Properties for this type of implementation in your project.
This link helpful for your requirement

autowired component is null

I'm developing a web application with spring. I've had no problem autowiring and using database #Service classes. Now I'm trying to read a global property file and provide the values to all classes that need them. The solution I've come up with so far seem to be overly complicated (too many classes - AppConfig, ServerConfig iface, ElasticServerConfig) for such a trivial task but I could live with it if it worked.
my applicationContext.xml contains
<context:component-scan base-package="my.package" />
AppConfig.java:
package my.package.configuration;
#Configuration
#PropertySource("classpath:application.properties")
public class AppConfig {
}
ServerConfig.java:
public interface ServerConfig {
String getUrl();
String getUser();
String getPassword();
}
ElasticSearchConfig.java:
package my.package.configuration;
#Component(value = "elasticServerConfig")
public class ElasticServerConfig implements ServerConfig {
private static final Logger LOGGER = LogManager.getLogger(ElasticServerConfig.class);
private String url;
private String user;
private String password;
#Autowired
public ElasticServerConfig(final Environment env) {
this.url = env.getProperty("elastic_server.url");
this.user = env.getProperty("elastic_server.user");
this.password = env.getProperty("elastic_server.password");
LOGGER.debug("url=" + url + "; user=" + user + "; password=" + password); // this works!
}
#Override
public final String getUrl() {
return url;
}
#Override
public final String getUser() {
return user;
}
#Override
public final String getPassword() {
return password;
}
}
When the web application boots, the ElasticServerConfig constructor prints out the correct url/user/pwd as read from application.properties. However an instance of ElasticServerConfig is not injected into a Search object:
package my.package.util;
public class Search {
#Autowired
#Qualifier("elasticServerConfig")
private ServerConfig elasticServerConfig;
public final List<Foobar> findByPatternAndLocation() {
if (elasticServerConfig == null) {
LOGGER.error("elasticServerConfig is null!");
}
// and i get a NullPointerException further on
// snip
}
}
You have to register the Search class as a Spring Bean and take it from the Spring context when you want to use it. It's important to get the bean from the spring context. If you create an object of that class with new, Spring has no way to know about that class and mange it's dependencies.
You can get get a bean from the Spring context by #Autowire it somewhere or by accessing an instance of the context and use the getBean method:
#Configuration
#PropertySource("classpath:application.properties")
public class AppConfig {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(AppConfig.class, args);
ctx.getBean...
}
}
Either use #Component annotation on the class and make sure that the class is in package thats under my.package
or register it in the configuration class
#Configuration
#PropertySource("classpath:application.properties")
public class AppConfig {
#Bean
public Search search(){
return new Search();
}
}

Store bean instance in Spring

I have an authenticating method in my web application, which gets a http parameter from another application. I load my user from the database and store it in a spring bean. In my login controller it is instantiated, but when I inject it in another controller, it losts its properties and I get 'null' when I want to reach my user. How can I make a bean's property available in all other controller? I don't want to use static properties... I tried to make the bean 'session scoped', but it doesn't work.
The suerBean:
#Service
#SessionScoped
public class SessionUserBean {
public Dolgozo user;
public Boolean userIsDolgozo;
public Boolean userIsIranyito;
public Boolean userIsVezeto;
public Boolean userIsOsztalyVezeto;
public void setUser(Dolgozo user) {
this.user = user;
}
public Dolgozo getUser() {
return user;
}
}
I set the value of the user property:
#Autowired
private SessionUser sessionUser;
#Autowired
private SessionUserBean user;
#Autowired
private HttpServletRequest request;
#RequestMapping("index.htm")
public String doLogin(#RequestParam String token) {
if (login.isUserAuthanticated(token)) {
user.setUser(sessionUser.getDolgozo());
return "sikeresBelepes";
}
return "sikertelenBelepes";
}
And this is where I want to use it:
#Autowired
private SessionUserBean user;
public void setUp() {
employees = drp.findByCsoportID(user.getUser().getCsoportid().getId());
}
What a mess!
Why not use Spring Security? It automatically manages Security Context for you by setting up a set of filters. And you have access to user information in any place of your app.
If no, you must set up your user in session somewhere in your code, you cannot just autowire it. Like this:
#RequestMapping("index.htm")
public String doLogin(#RequestParam String token) {
if (login.isUserAuthanticated(token)) {
user.setUser(sessionUser.getDolgozo());
return "sikeresBelepes";
session.addAttribute("securityUser", user);
}
return "sikertelenBelepes";
}
and then get it from session with getAttribute()

Categories

Resources