Spring boot properties with array - spring-boot

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;
}
}

Related

Take data from postgresql and write it to mongodb

I am new to using nosql databases, specifically mongodb.
My project is based on spring data jpa (postgresql). I would like to know if it is possible to use posgresql and mongodb together? I would like to take data from a postgresql database and write it to mongodb so as not to load postgre.
My Entity for mongodb
#Data
#Document(collection = "exposure")
public class Exposure {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne
#NotNull
private Facility facility;
#ManyToOne
#NotNull
private Investee investee;
#ManyToOne
#NotNull
private Investee investeeName;
#ManyToOne
#NotNull
private Tranche tranche;
}
Repository
#Repository
public interface ExposureRepository extends MongoRepository<Exposure, Long> {
}
DtoService
#Service
#RequiredArgsConstructor
public class DefaultExplosureDtoService implements ExplosureDtoService {
private final FacilityService facilityService;
private final InvesteeService investeeService;
private final ExplosureMapper explosureMapper;
private final ExplosureService explosureService;
#Override
#Transactional
public ExplosureDto create(CreateExplosureDto explosureDto) {
Explosure explosure = new Explosure();
if (explosureDto.getFacilityId() != null) {
explosure.setFacility(facilityService.getById(explosureDto.getFacilityId()));
}
if (explosureDto.getInvesteeId() != null) {
explosure.setInvestee(investeeService.getById(explosureDto.getInvesteeId()));
}
Explosure savedExplosure = explosureService.save(explosure);
return explosureMapper.toExplosureDto(savedExplosure);
}
}
Service
#Service
#RequiredArgsConstructor
public class DefaultExplosureService implements ExplosureService {
private final ExplosureRepository explosureRepository;
#Override
public Explosure save(Explosure explosure) {
return explosureRepository.save(explosure);
}
}
When I run the application, I get a 405 error. And I can’t figure out how to take data from the postgres database and write it to mongodb

Limiting the visibility of results from the database on one page- spring boot

I create web application in spring boot using the postgress database.
I want to limit the number of records per page(now it's 30,000 records - it's loading a long time), so what should i do to limit it? I use thymeleaf.
Model:
#Entity(name="articles")
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Articles {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long article_id;
private String title;
private String issn;
private String eissn;
private String title2;
private String issn2;
private String eissn2;
private Integer points;
#ManyToMany
#JoinTable(
name = "articles_categories",
joinColumns = #JoinColumn(name = "article_id"),
inverseJoinColumns = #JoinColumn(name = "category_id"))
private List<Category> categories;
....
getters and setters
Repository:
public interface ArticlesRepository extends JpaRepository<Articles,Long> {
}
Controller:
#Controller
#RequestMapping("/articles")
public class ArticlesController {
private ArticleService articleService;
#Autowired
public void setArticleService(ArticleService articleService) {
this.articleService = articleService;
}
#GetMapping
public String getAll(Model model)
{
model.addAttribute("articles", articleService.list());
return "articles";
}
Service:
#Service
public class ArticleService {
#Autowired
private ArticlesRepository articlesRepository;
public ArticleService() {
}
public List<Articles> list(){
return articlesRepository.findAll();
}}
Use Pageable to limit the size of your articles.
public List<Articles> list(int page, int limit){
Page<Articles> pageableArticales = articlesRepository.findAll(PageRequest.of(page, limit);
return pageableArticales.getContent();
}
Note that repository.findAll(pageable) wraps the list of data on Page, which provides getNumber(), getSize(), getNumberOfElements(), getTotalPages(), getTotalElements, etc.
And consider exploring PageRequest and PagedResources as well.

Spring property Inject full property object to bean

Ihave property class:
#Getter
#Setter
#Component
#ConfigurationProperties(prefix = "my-api")
public class MyApiProperties {
...
private MyClient myClient;
#Getter
#Setter
public static class MyClient {
private String host;
private long connectionTimeout;
private long receiveTimeout;
}
}
I can config it:
my-api:
my-client:
host: http://1...
connection-timeout: 30000
receive-timeout: 60000
And I can Inject it:
#Value("${my-api.my-client.host}")
private String host;
But can I inject full object like this?
#Value("${my-api.my-client}")
private MyClient myClient;

Spring Data JPA Redis : Cannot write custom method based query

I have configured Spring Data JPA with Redis and using RedisRepositories with provides methods like find(), findAll() etc. All these methods seem to be working just fine, but I am not able to write my custom method like.
RedisEntity findByGenderAndGrade(String gender, String grade);
RedisEntity is a simple POJO Entity class. If you want any more info, please let me know in messages.
Following is my entity:
#Data
#RedisHash("test1")
public class RedisEntity implements Serializable {
#Id
#GeneratedValue
private String id;
private String name;
private String gender;
private Integer grade;
}
Repository:
#Repository
public interface TestRepository extends JpaRepository<RedisEntity, String> {
List<RedisEntity> findAllByGender(String gender);
List<RedisEntity> findAllByGrade(Integer grade);
}
Service/Controller:
#Override
public List<RedisEntity> getById(String id) {
return testRepository.findById(id); //returns data perfectly.
}
#Override
public List<RedisEntity> getAllByGender(String gender) {
return testRepository.findAllByGender(gender); //returns []
}
#Override
public void saveEntity(RedisEntity redisEntity) {
testRepository.save(redisEntity); // saves it in redis perfectly.
}
Also,
findByGender and findAllByGender both give [], although I can see data in my redis database and save it as well.
As requested by FrançoisDupire,
#Configuration
public class RedisConfig {
#Autowired
private DeploymentProperties deploymentProperties;
private static Logger logger = LoggerFactory.getLogger(RedisConfig.class);
#Bean
JedisConnectionFactory jedisConnectionFactory() {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration("localhost", 6379);
redisStandaloneConfiguration.setPassword(RedisPassword.of("root"));
return new JedisConnectionFactory(redisStandaloneConfiguration);
}
#Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(jedisConnectionFactory());
return template;
}
}
Also, I had referred this article: Baeldung article on Spring data redis
As mentioned by #JoshJ and verified by myself and others,
The solution to the problem is:
Adding #Indexed annotation
to all those columns/fields which need to be used with all finds.
#Data
#RedisHash("EmployeeDetails")
public class RedisEntity {
#Id
private String employeeId;
private String firstName;
private String lastName;
#Indexed
private String gender;
#Indexed
private String grade;
}
We have the Spring Data Redis Library which provides the scope to write the custom method.Attaching Sample code.
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>2.0.8.RELEASE</version>
</dependency>
Entity Definition
#Data
#RedisHash("EmployeeDetails")
public class RedisEntity {
#Id
private String employeeId;
private String firstName;
private String lastName;
private String gender;
private String grade;
}
Repository Definition
#Repository
public interface RedisEntityRepository extends CrudRepository<RedisEntity, String>{
List<RedisEntity> findAllByGenderAndGrade(String gender, String grade);
}
Implementation
#Component
public class RedisEntityImpl implements RedisEntityService {
#Autowired
private RedisEntityRepository redisEntityRepository;
#Override
public List<RedisEntity> getAllByGenderAndGrade(String gender, String grade) {
return redisEntityRepository.findAllByGenderAndGrade(gender,grade);
}
}
Properties
spring.cache.type = redis
spring.redis.host = localhost
spring.redis.port = 6379

findByName isn't work [Spring boot]

I have a problem with Spring boot.
I created Entity and Repository, but method findByName in Repository isn't work.
My url:
http://localhost:8080/student/search/findByName?name=Artem
In Google chrome: localhost not found, but search is mapped.
Entity:
#Getter #Setter
#Entity #Table(name = "Student")
public class Student extends BaseEntity{
private String name;
private String dateOfBirthDay;
private String sex;
private String phoneNumber;
}
BaseEntity:
#Getter
#Setter
#MappedSuperclass
public class BaseEntity {
#Id #GeneratedValue(strategy = GenerationType.SEQUENCE) #Column protected Long id;
My Repository:
#RepositoryRestResource(collectionResourceRel = "student", path = "student")
public interface StudentRepository extends PagingAndSortingRepository<Student, Long> {
Student findByName(#Param("name") String name);
}
Application:
#SpringBootApplication
#EnableTransactionManagement
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Application.yaml:
spring:
application:
name: students
datasource:
driverClassName: org.postgresql.Driver
url: jdbc:postgresql://localhost:5432/students
username: postgres
password: postgres
jpa:
hibernate:
ddl-auto: update
server:
port: 8080
I recommend you to create a resource class, works like controller. Here a simple example:
#RestController
#RequestMapping("/yourPath") //students, whatever
public class StudentsResource {
#Autowired
private StudentRepository studentRepository;
//type media that you want to show (json, xml...in this case is JSON)
#RequestMapping(method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
// <Student> is the entity, object
#RequestMapping(value = "/yourPath/{studentName}")
public ResponseEntity<Student> findByName(#pathVariable("studentName") String name) {
Student student = studentRepository.findByName(name);
if(student == null){
//handler your own exception here
}
//show the student as json object
return ResponseEntity.status(HttpStatus.OK).body(student);
}
Note: that's the resource class. But your problem is about localhost, so if you are using Spring Boot, see if your "application.properties" is correct. Here my example:
spring.datasource.url=jdbc:mysql://localhost:3306/yourDataBase
spring.datasource.username=yourUser
spring.datasource.password=yourPassword
spring.jpa.hibernate.ddl-auto=update //makes the spring create the database automatic!

Resources