Spring boot provided it's own database connection according to configuration in application.properties. But here I have a service which provided me an object of javax.sql.Connection type.
src/main/resources/application.properties
server.port=9090
spring.jpa.database=POSTGRESQL
spring.datasource.platform=postgres
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=postgres
spring.datasource.password=root
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
Here is code for repository
package com.example.springbootdemo.repositories;
import org.springframework.data.repository.CrudRepository;
import com.example.springbootdemo.model.Box;
public interface BoxRepository extends CrudRepository<Box, Long> {
}
Code for controller
package com.example.springbootdemo.controllers;
import com.example.springbootdemo.model.Box;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.springbootdemo.repositories.BoxRepository;
#RestController
public class BoxController {
#Autowired
BoxRepository boxrepository;
#PostMapping("/box")
public Box addBox(Box box){
return this.boxrepository.save(box);
}
}
Here when I am calling save function of JPA repository it saves the object using db object which it is calculating by using some of its own wrapper.
But I have to use a jar which gives me Database connection. Instead of configuration in src/main/resources/application.properties, I have to use connection object returned from this jar. Now I'll need to override the connection object that spring boot is using internally. I am not able to figure out how I can do this.
you have this path : src//main//resoruces//application.properties
and here you need to configure
Related
I have searched for so many posts but I couldn't find a proper way to use Elastic Search with spring boot application because I am totally new to elastic search.
My only dependency is:
org.springframework.boot
spring-boot-starter-data-elasticsearch
2.7.3
My config class is:
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.RestClients;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
#Configuration
#EnableElasticsearchRepositories(basePackages = "com.backend.repository.elasticsearchrepository")
#ComponentScan(basePackages = {"com.backend.model.elasticsearchmodel"})
public class ElasticSearchConfig extends AbstractElasticsearchConfiguration {
#Value("${spring.elasticsearch.url}")
public String elasticsearchUrl;
#Value("${spring.elasticsearch.username}")
public String username;
#Value("${spring.elasticsearch.password}")
public String password;
#Bean
#Override
public RestHighLevelClient elasticsearchClient() {
final ClientConfiguration config = ClientConfiguration.builder()
.connectedTo(elasticsearchUrl)
.withBasicAuth(username, password)
.build();
return RestClients.create(config).rest();
}
}
Here RestHighLevelClient is shown as deprecated. And my repository class is:
package com.backend.repository.elasticsearchrepository;
import com.backend.model.elasticsearchmodel.EsOffice;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.UUID;
public interface ESOfficeRepository extends ElasticsearchRepository<EsOffice, UUID> {
}
When I call the methods of this repository then it works fine but while storing the data it is returning error message even if it adds the data successfully.
2022-10-15 00:00:15.608 ERROR 51607 --- [nio-8080-exec-2] c.a.a.exception.GlobalExceptionHandler : Unable to parse response body for Response{requestLine=POST /office/_doc?timeout=1m HTTP/1.1, host=http://localhost:9200, response=HTTP/1.1 201 Created}; nested exception is java.lang.RuntimeException: Unable to parse response body for Response{requestLine=POST /office/_doc?timeout=1m HTTP/1.1, host=http://localhost:9200, response=HTTP/1.1 201 Created}
Which POM dependency + what kind of repository should I use and How can I configure it in my config file ? I need these 3 that compatible with each other ?
Spring Data Elasticsearch 4.4 (which is pulled in by Spring Boot 2.7.3) is build with the Elasticsearch libraries in version 7.17, this is problematic when running against an Elasticsearch cluster in version 8. Youhave basically two options:
Downgrade your cluster to version 7.17.6 (the latest 7.17 currently available) i f this is possible.
You can try and see if setting the compatibility headers (see the Spring Data Elasticsearch documentation section 5.3.1 for more info). This should work, but I encountered cases where the response from the cluster still wasn't readable with a 7.17 client. - I had issues opened with Elasticsearch and they were resolved, but there still might be hidden traps.
I am trying to load a MySQL database into a spring boot application but when I start the application I am getting those error messages:
2018-07-17 13:46:31.426 WARN 2120 --- [ restartedMain] o.s.b.a.orm.jpa.DatabaseLookup : Unable to determine jdbc url from datasource
org.springframework.jdbc.support.MetaDataAccessException: Could not get Connection for extracting meta-data; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection: 'url' not set
Although I have set the url property in application.properties : spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase
Can anyone help me figure this one out?
Edit: Here is my Main class:
package com.randomsoft.checkoff;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
#SpringBootApplication
#EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class CheckoffApplication {
public static void main(String[] args) {
SpringApplication.run(CheckoffApplication.class, args);
}
}
can you try by removing
#EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
also try to add all below jdbc properties,
spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase?verifyServerCertificate=false&useSSL=false&requireSSL=false
spring.datasource.username=<username>
spring.datasource.password=<password>
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.ddl-auto=update
just try to append this line in your config class
#SpringBootApplication
#EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
Most of the answers recommend excluding DataSourceAutoConfiguration, and I agree with the approach, but what they don't tell is that besides the programmatic way via annotation #EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}), we also have the option of setting it via properties in the following manner which is useful when annotating an application class is not an option.
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
You should name property file: application.properties or application.yml
I am using Spring Data LDAP to get user data from an LDAP server.
My file structure looks like this:
main
java
com.test.ldap
Application.java
Person.java
PersonRepository.java
resources
application.yml
schema.ldif
test
java
Tests.java
resources
test.yml
test_schema.ldif
And here is my test class:
import com.test.ldap.Person;
import com.test.ldap.PersonRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {PersonRepository.class})
#TestPropertySource(locations = "classpath:test.yml")
#EnableAutoConfiguration
public class Tests {
#Autowired
private PersonRepository personRepository;
#Test
public void testGetPersonByLastName() {
List<Person> names = personRepository.getPersonNamesByLastName("Bachman");
assert(names.size() > 0);
}
}
The problem is, Spring Boot is loading the application.yml and schema.ldif files instead of my test YAML and LDIF files, despite the fact that my #TestPropertySource annotation is explicitly listing test.yml. This seems to be due to the auto configuration, which I would prefer to use for convenience.
I would expect #TestPropertySource to take higher precedence than the auto configuration, but that does not seem to be the case. Is this a bug in Spring, or am I misunderstanding something?
For the record, here is my test.yml file (it does specify test_schema.ldif):
spring:
ldap:
# Embedded Spring LDAP
embedded:
base-dn: dc=test,dc=com
credential:
username: uid=admin
password: secret
ldif: classpath:test_schema.ldif
port: 12345
validation:
enabled: false
So I was able to work around this by manually specifying the properties needed to make use of the LDIF file. This is because, according to the #TestPropertySource documentation, inlined properties have higher preferences than property files.
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {PersonRepository.class})
#TestPropertySource(properties =
{"spring.ldap.embedded.ldif=test_schema.ldif", "spring.ldap.embedded.base-dn=dc=test,dc=com"})
#EnableAutoConfiguration
public class Tests {
//...
}
This is not the best workaround, however: what if I had more than just two properties I needed to define? It would be impractical to list them all there.
Edit:
Renaming my test.yml file to application.yml so it overrides the production file that way did the trick. As it turns out, the TestPropertySource annotation only works for .properties files.
I discovered that YML files DO NOT work with #TestPropertySource annotation.
A clean way around this is to use #ActiveProfile. Assuming that your YML file with test properties is called
application-integration-test.yml
then you should use the annotation like this
#ActiveProfile("integration-test")
I currently have one database connected and it is working. I would like to connect another (and eventually 2 more) databases. How do I do so? There should be a solution using only annotations and properties files.
I read this
Profile Specific Properties
and it sort of helps but I still don't know how switch from one profile to the other in the code during runtime. I'm assuming I need to be connected to one profile at a time before I try to retrieve/persist things from different databases.
I also read this question, How to use 2 or more databases with spring?, but I dont know how it works too well/ if it will apply. I'm not using a controller class and I dont know what that does. I'm also not sure how the config class they mention in the answer actually connects to the specific DO.
This is my application.properties file: (marked out username and password but its there in my file)
hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.default_schema=dbo
hibernate.packagesToScan=src.repositories.LMClientRepository.java
spring.jpa.generate-ddl=true
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.DefaultNamingStrategy
spring.datasource.username=***
spring.datasource.password=***
spring.datasource.url=jdbc:sqlserver://schqvsqlaod:1433;database=dbMOBClientTemp;integratedSecurity=false;
spring.datasource.testOnBorrow=true
spring.datasource.validationQuery=SELECT 1
spring.jpa.database=dbMOBClientTemp
spring.jpa.show-sql=true
spring.jpa.hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect
spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
This is my application file:
package testApplication;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.orm.jpa.EntityScan;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import fileRetrieval.InputFileParse;
import lmDataObjects.LMClientDO;
import lmDataObjects.LoadMethodDO;
import repositories.LMClientRepository;
import repositories.LoadMethodRepository;
#SpringBootApplication
#EnableJpaRepositories(basePackageClasses = LoadMethodRepository.class)
#EntityScan(basePackageClasses = LoadMethodDO.class)
#EnableCaching
public class Application {
private static final Logger log = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public CommandLineRunner demo(LoadMethodRepository lm_repo, LMClientRepository lmc_repo) {
return (args) -> {
List<LMClientDO> lmlist = InputFileParse.getMultiGroupfile();
List<String> uniqueMediaIds = new ArrayList(InputFileParse.getUniqueMediaIds());
for (int i = 0; i < InputFileParse.getUniqueMediaIds().size(); i ++){
lm_repo.save(new LoadMethodDO(uniqueMediaIds.get(i)));
}
for (int i = 0; i < lmlist.size(); i++){
lmc_repo.save(new LMClientDO(lmlist.get(i).getClientId(), lmlist.get(i).getMediaId()));
}
//Here is where I would like to do stuff with data from the other database that I have not connected yet
};
}
}
I also made a new properties file called application-MTS.properties and I put data for the new database in there. Still unsure of what to do with it.
spring.datasource.username=***
spring.datasource.password=***
spring.datasource.url=jdbc:sqlserver://SCHQVSQLCON2\VSPD:1433;database=dbMTS;integratedSecurity=false;
You will need to define multiple DataSource beans that each represent the various database connection resources you plan to use.
You will then need to add a TransactionManager and EntityManagerFactory bean definition for each of those DataSource beans.
If you intend to have each DataSource participate in a JTA transaction, you'll need to also consider configuring a JTA transaction manager rather than individual resource local transaction managers.
I am studying for the Spring Core certification and I have the followind doubt with an exercice related to the beans configuration using the Java configuration way.
So I have the following RewardsConfig class that configure my beans (this class is into the application folder src/main/java):
package config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import rewards.RewardNetwork;
import rewards.internal.RewardNetworkImpl;
import rewards.internal.account.AccountRepository;
import rewards.internal.account.JdbcAccountRepository;
import rewards.internal.restaurant.JdbcRestaurantRepository;
import rewards.internal.restaurant.RestaurantRepository;
import rewards.internal.reward.JdbcRewardRepository;
import rewards.internal.reward.RewardRepository;
#Configuration
public class RewardsConfig {
#Autowired
DataSource dataSource;
#Bean
public RewardNetwork rewardNetwork(){
return new RewardNetworkImpl(accountRepository(), restaurantRepository(), rewardRepository());
}
#Bean
public AccountRepository accountRepository(){
JdbcAccountRepository repository = new JdbcAccountRepository();
repository.setDataSource(dataSource);
return repository;
}
#Bean
public RestaurantRepository restaurantRepository(){
JdbcRestaurantRepository repository = new JdbcRestaurantRepository();
repository.setDataSource(dataSource);
return repository;
}
#Bean
public RewardRepository rewardRepository(){
JdbcRewardRepository repository = new JdbcRewardRepository();
repository.setDataSource(dataSource);
return repository;
}
}
As you can see I declare 4 methods that are used to create 4 beans and that specify the dependency that occurs among these beans.
So I have a RewardNetwork bean that is implemented by RewardNetworkImpl class that depends from the following 3 beans: AccountRepository, RestaurantRepository and RewardRepository.
Is it the correct interpretation of the Java configuration is Spring?
Can I say for example that RewardNetwork is the declared bean and that RewardNetworkImpl its the current implementation of this bean?
All the 3beans (AccountRepository, RestaurantRepository and RewardRepository) depends by another bean dataSource that, as you can see in the previous code snippet, is declared as #Autowired:
#Autowired
DataSource dataSource;
This bean is not declared in this configuration class because it changes according to the environment (test, developt, production).
So, in my case it is declared into the unit test folder src/test/java:
package rewards;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
#Configuration
public class TestInfrastructureConfig {
/**
* Creates an in-memory "rewards" database populated
* with test data for fast testing
*/
#Bean
public DataSource dataSource(){
return
(new EmbeddedDatabaseBuilder())
.addScript("classpath:rewards/testdb/schema.sql")
.addScript("classpath:rewards/testdb/test-data.sql")
.build();
}
}
So the dataSource bean define a datasource that is valid only for the test environment (used when I perform a unit test).
Now my doubt is: I have 2 different configuration classes and the dataSource bean is not definied into the RewardsConfig configuration class that contains the 3 beans that use it. Why I can't not use the #Import annotation to use it into RewardsConfig?
Something like it:
#Import(TestInfrastructureConfig.class)
How it work exactly?
Tnx
You don't have to import beans to make them available for autowiring. #Import is used to add extra configuration classes.
You really don't want to hard-import a test configuration class, because then your production code is referring to test-only code (and, in this case, always activating it). Instead, think of your configuration class more like an abstract class: declare autowired beans, but don't worry about how they get there. The downstream (runtime) configuration will supply them, and you don't need to know how. Maybe you're supplying an in-memory H2 for testing and using Spring Cloud Connectors for actual runs, doesn't matter.