#PropertyResource is not working in Spring Boot - spring-boot

Below is my Property class:
package com.example.sdasDemo;
import lombok.Getter;
import lombok.Setter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
#Configuration
#PropertySource("classpath:info.properties")
#ConfigurationProperties(prefix = "feeder")
#Getter
#Setter
public class Properties {
public String[] id;
}
Below is the simple controller:
package com.example.sdasDemo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class controller {
#Autowired
Properties properties;
#RequestMapping("/get")
public String getData(){
System.out.println(properties.getId());
return properties.getId();
}
}
Below is the info.properties file
feeder.id=soumik,das,21022021
http://localhost:8080/get returns null pointer exception
Why this #PropertyResouce is not working? What am I missing here. Please suggest.

I found the problem. It was happening due to wrong profile name provided. For that reason, the property file location could not be found and resulting null pointer exception.

Related

Spring can't find repository bean

I'm using spring boot with spring data jdbc and I got trouble with run my app
I have StudentService class:
package ru.turnip.service;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import ru.turnip.model.Student;
import ru.turnip.repository.StudentRepository;
import ru.turnip.utils.student.BusyStudents;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
#Service
public class StudentService {
private final BusyStudents busyStudents;
private final StudentRepository studentRepository;
public StudentService(BusyStudents busyStudents, StudentRepository studentRepository) {
this.busyStudents = busyStudents;
this.studentRepository = studentRepository;
}
...
}
And StudentRepository interface:
package ru.turnip.repository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import ru.turnip.model.Student;
import java.util.UUID;
#Repository
public interface StudentRepository extends CrudRepository<Student, UUID> { }
So, when I try to run app, I get an eror, and I can't figure out where the problem is.
That my config class:
package ru.turnip;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.relational.core.mapping.event.BeforeSaveEvent;
import org.springframework.scheduling.annotation.EnableScheduling;
import ru.turnip.model.Student;
import java.time.Clock;
import java.util.UUID;
#ComponentScan
#Configuration
#EnableScheduling
public class ApplicationConfig {
#Bean
public Clock clock() {
return Clock.systemDefaultZone();
}
#Bean
public ApplicationListener<BeforeSaveEvent> idGenerator() {
return event -> {
var entity = event.getEntity();
if (entity instanceof Student) {
((Student) entity).setId(UUID.randomUUID());
}
};
}
}
And project structure:
I tried to explicitly set package to be scanned, and also moved the repository to the package with the config. Also I tried to annotate with #Autowired field and constructor in StudentService

Spring ignores Beans, Qualifier and Transactional

Hi trying to set simple rest controller with several databases. Problem is Spring ignores both Transactional from my service, it always go to #Primary. Also Spring ignores the Qualifier inside DataSourceTransactionaManager and seems to go to default #Primary. Anyone help much appreciated.
edit: added import statements.. hikari imports i due too i changed the code little bit and instead use hikari database and also tried entitymanager..but neither of those things helped..
package com.example.miniredditbackend.user;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
#Service
public class UserService implements UserSer{
private UserRepo userRep;
#Autowired
public UserService(UserRepo userRep){
this.userRep = userRep;
}
#Override
#Transactional("tm1")
public User createUser(User user){
return userRep.save(user);
}
}
package com.example.miniredditbackend.user;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
entityManagerFactoryRef = "entityuser",
transactionManagerRef = "tm2",
basePackages = {
"com.example.miniredditbackend.user"
}
)
public class userDatabase {
#Bean(name = "userdb")
#ConfigurationProperties(prefix = "userdatabase.datasource")
public DataSource userdb(){
return DataSourceBuilder.create().build();
}
#Bean(name = "entityuser")
public LocalContainerEntityManagerFactoryBean entityU(EntityManagerFactoryBuilder builder,
#Qualifier ("userdb") DataSource datasource){
return builder.dataSource(datasource).packages("com.example.miniredditbackend.user").persistenceUnit("usersx").build();
}
#Bean(name = "tm2")
public PlatformTransactionManager tm2(#Qualifier ("entityuser") EntityManagerFactory entityuser){
return new JpaTransactionManager(entityuser);
}
}

Setters for session scoped bean not working in RestController

I'm trying to get the username from the session scoped bean once the user has logged in using /users/login
I've Autowired a session scoped bean into a RestController and in one of the endpoints in the rest controller, I'm invoking a setter on the session scoped bean. But the effect of setters is not visible for requests from the same session.
The following is my session scoped bean:
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
#Getter
#Setter
public class SessionSpecificUserDetails implements Serializable {
private String userName;
}
import lombok.Getter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.annotation.SessionScope;
#Getter
#Configuration
public class UserSessionDetailsConfiguration {
#Bean
#SessionScope
public SessionSpecificUserDetails sessionSpecificUserDetails() {
return new SessionSpecificUserDetails();
}
}
The following is the RestController
import com.course.backend.coursebackend.config.SessionSpecificUserDetails;
import com.course.backend.coursebackend.dao.User;
import com.course.backend.coursebackend.repository.UserRepository;
import com.course.backend.coursebackend.utils.ResponseUtils;
import com.course.backend.coursebackend.utils.UserUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
#RestController
#RequestMapping("/users")
public class UserController {
#Autowired
UserRepository userRepository;
#Autowired
SessionSpecificUserDetails sessionSpecificUserDetails;
#GetMapping("/getLoggedInUser")
public String getLoggedInUser() {
return sessionSpecificUserDetails.getUserName();
}
#PostMapping("/login")
public ResponseUtils.CustomResponse login(#RequestBody User user) {
List<User> users = getAllUsers();
Optional<User> optionalUser = users.stream()
.filter(currentUser -> currentUser.getUserName().equals(user.getUserName()))
.findAny();
if (optionalUser.isEmpty()) {
return ResponseUtils.getErrorResponse(List.of("Username not found!"));
}
if (optionalUser.get().getPassword().equals(user.getPassword())) {
sessionSpecificUserDetails.setUserName(user.getUserName());
return ResponseUtils.getSuccessResponse("Login Successful!");
}
return ResponseUtils.getErrorResponse(List.of("Login failed due to wrong password!"));
}
}
I see that spring is creating proxy for the session scoped bean. (And may be because of that my setters are not having any effect even for the same session?)
My question is what's the correct way to use the session scoped beans in the RestController? And what's the good way to get the username for the same session across requests?
I tried marking UserController also as #SessionScope but that's also not working.

Encountered error "Consider defining a bean of type 'java.util.concurrent.atomic.AtomicReference' in your configuration"

I am getting the below error while starting spring boot application.
The injection point has the following annotations:
#org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type
'java.util.concurrent.atomic.AtomicReference' in your configuration.
Below is the code .
package de.summer.sampleapplayerv1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#SpringBootApplication(scanBasePackages = {"de.summer.sampleapplayerv1"})
#EnableConfigurationProperties
#EnableJpaRepositories (basePackages ="de.summer.sampleapplayerv1.repository")
#EnableTransactionManagement
public class Sampleapplayerv1Application {
public static void main(String[] args) {
SpringApplication.run(Sampleapplayerv1Application.class, args);
}
}
package de.summer.sampleapplayerv1.service;
import de.summer.sampleapplayerv1.domain.QueueAndPublish;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
#Slf4j
#Service
public class QueueAndPublishServiceImpl implements QueueAndPublishService{
private final AtomicReference<List<QueueAndPublish>> currentJob;
public QueueAndPublishServiceImpl(
#Qualifier("currentJob") AtomicReference<List<QueueAndPublish>> currentJob
){
this.currentJob=currentJob;
}
#Override
public QueueAndPublish getJobStatus(UUID jobId) {
return (QueueAndPublish) currentJob.get().stream()
.filter(j -> j.getJobId()==jobId)
.collect(Collectors.toList());
}
#Override
public List<QueueAndPublish> getAllJobStatus() {
return currentJob.get();
}
#Override
public QueueAndPublish getCategoryDataProcess() {
List<QueueAndPublish> processList=new ArrayList<QueueAndPublish>();
QueueAndPublish process=QueueAndPublish.builder()
.jobId(UUID.randomUUID())
.jobName("Name for Job")
.jobStatus("Not Yet Started")
.build();
Thread t1=new Thread(process.getJobId().toString()){
#Override
public void run(){
log.info("How are you doing");
process.setJobStatus("Completed");
}
};
t1.start();
processList.add(process);
currentJob.set(processList);
return process;
}
#Override
public QueueAndPublish getCatgeoryDataProcessStatus() {
return null;
}
}
package de.summer.sampleapplayerv1.domain;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.io.Serializable;
import java.util.UUID;
#Getter
#Setter
#Builder
#Entity
public class QueueAndPublish implements Serializable {
#Id
private UUID jobId;
private String jobName;
private String jobStatus;
}
If I remove the constructor, spring boot application is starting up without any errors. If included , start up is failing with unsatisfied dependency errors.
Can someone please help on what is wrong with config?
You expect Spring to create an instance of class QueueAndPublishServiceImpl for the implementation of QueueAndPublishService. This instance needs a constructor parameter of type AtomicReference<List<QueueAndPublish>> injected.
But you obviously do not define any Spring bean (Bean, Component, Service, ...) of that type.
Edit:
public QueueAndPublishServiceImpl(
#Qualifier("currentJob") AtomicReference<List<QueueAndPublish>> currentJob
){
this.currentJob=currentJob;
}
Here you define a constructor parameter to have a AtomicReference<List<QueueAndPublish>>, and even specify it with a #Qualifier. So you need to provide a Spring bean of this class with this qualifier, otherwise Spring cannot inject it into the constructor call.
Consider defining a bean of type 'java.util.concurrent.atomic.AtomicReference' in your configuration.
Means "something like" adding this to your Sampleapplayerv1Application:
#Bean("currentJob") AtomicReference<List<QueueAndPublish>> currentJob() {
// or a list implementation of your choice.
return new AtomicReference<>(new java.util.ArrayList<>());
}

No instance(s) of type variable(s) T exist so that Flux<T> confirms to Mono<? extend R)

I am implementing Spring webflux demo application and have written my demo application as like that
package com.abcplusd.application;
import com.abcplusd.domain.Event;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import java.util.Collections;
import java.util.Date;
import java.util.stream.Stream;
#SpringBootApplication
public class ReactiveClientApplication {
#Bean WebClient webClient() {
return WebClient.create("http://localhost:8080");
}
#Bean CommandLineRunner demo(WebClient webClient) {
return args -> {
webClient.get()
.uri("/events")
.accept(MediaType.TEXT_EVENT_STREAM)
.exchange()
.flatMap(clientResponse -> clientResponse.bodyToFlux(Event.class))
.subscribe(System.out::println);
};
}
public static void main(String[] args) {
new SpringApplicationBuilder(ReactiveClientApplication.class)
.properties(Collections.singletonMap("server.port", "8081"))
.run(args);
}
}
It shows the following error
Error:(29, 41) java: incompatible types: no instance(s) of type variable(s) T exist so that reactor.core.publisher.Flux<T> conforms to reactor.core.publisher.Mono<? extends R>
The above error is at this line:
.flatMap(clientResponse -> clientResponse.bodyToFlux(Event.class)))
Event Class
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Date;
#Data
#AllArgsConstructor
public class Event {
private long id;
private Date when;
}
Can anybody help me to solve the error?
It works me after i have done these changes in my code
.flatMap(clientResponse -> clientResponse.bodyToFlux(Event.class)))
to
.flatMapMany(clientResponse -> clientResponse.bodyToFlux(Event.class))
and
#NoArgsConstructor annotation in Event.Class
as follows:
import java.util.Date;
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Event {
private long id;
private Date when;
}
flatMapMany instead of flatMap works.
However when you add property spring.main.web_environment=false to application.properties file, webClient simply doesn't work.

Resources