This is my first WebApp builded using Spring and i'm going mad because when i call my RestController everytime gives me 404. I tried to use the Class/Annotaion configuration instead of the XML configuration and i think that is here that the problem lives.
Here are my config classes, pom and controller.
Sorry for the huge amount of code.
For the api call i use localhost:8080/Polito/metric
Initailizer
package com.poli.config;
import org.springframework.core.annotation.Order;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
#Order(1)
public class Initializer extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return new Class[] { RootConfig.class, SecurityConfig.class };
}
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebAppConfig.class };
}
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
RootConfig
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories("com.poli")
#ComponentScan("com.poli")
#PropertySource("classpath:application.properties")
public class RootConfig {
private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";
private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password";
private static final String PROPERTY_NAME_DATABASE_URL = "db.url";
private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username";
private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = "entitymanager.packages.to.scan";
private static final String PROPERTY_NAME_HIBERNATE_DDL_AUTO = "hibernate.hbm2ddl.auto";
private static final String PROPERTY_NAME_HIBERNATE_EJB_NAMING_STRATEGY = "hibernate.ejb.naming_strategy";
private static final String PROPERTY_NAME_HIBERNATE_FORMAT_SQL = "hibernate.format_sql";
#Resource
private Environment env;
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
dataSource.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
dataSource.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));
return dataSource;
}
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource());
sessionFactoryBean.setPackagesToScan(env.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));
sessionFactoryBean.setHibernateProperties(hibProperties());
return sessionFactoryBean;
}
private Properties hibProperties() {
Properties properties = new Properties();
properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
return properties;
}
#Bean
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource());
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
entityManagerFactoryBean.setPackagesToScan(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN);
Properties jpaProperties = new Properties();
jpaProperties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
jpaProperties.put(PROPERTY_NAME_HIBERNATE_DDL_AUTO,
env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DDL_AUTO));
jpaProperties.put(PROPERTY_NAME_HIBERNATE_EJB_NAMING_STRATEGY,
env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_EJB_NAMING_STRATEGY));
jpaProperties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL,
env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
jpaProperties.put(PROPERTY_NAME_HIBERNATE_FORMAT_SQL,
env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_FORMAT_SQL));
entityManagerFactoryBean.setJpaProperties(jpaProperties);
return entityManagerFactoryBean;
}
}
SecurityConfig
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private DataSource dataSource;
#Autowired
private UserDetailsService customUserDetailsService;
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.userDetailsService(customUserDetailsService)
.authorizeRequests()
.antMatchers("/personal/**").hasRole("USER")
.and()
.formLogin()
.loginPage("/login.html")
.defaultSuccessUrl("/index.html")
.failureUrl("/error-login.html")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/index.html");
}
}
WebAppConfig
#Configuration
#EnableWebMvc
#ComponentScan("com.poli")
public class WebAppConfig {
#Bean
public UrlBasedViewResolver setupViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("/WEB-INF/pages/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
}
SecurityInitializer
#Order(2)
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {
}
MetricRESTController
#RestController()
#RequestMapping("/metric")
public class MetricRESTController {
#Autowired
private MetricService metricService;
#RequestMapping(method = RequestMethod.POST, value="/")
#ResponseStatus(value=HttpStatus.CREATED)
public void post(#RequestBody Metric metric){
metricService.addMetric(metric);
}
#RequestMapping(method = RequestMethod.GET, value = "/{uuid}")
public List<Metric> get(#PathVariable("uuid") String uuid){
return metricService.findByUuid(uuid);
}
#RequestMapping(method = RequestMethod.GET, value = "/")
public List<Metric> get(){
return metricService.findAllMetrics();
}
}
And finally pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>Polito</groupId>
<artifactId>Polito</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<build>
<finalName>Polito</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
</plugin>
</plugins>
</build>
<properties>
<spring.version>4.2.1.RELEASE</spring.version>
<spring.security.version>4.0.2.RELEASE</spring.security.version>
<jstl.version>1.2</jstl.version>
<mysql.connector.version>5.1.30</mysql.connector.version>
<logback.version>1.1.2</logback.version>
<slf4j.version>1.7.6</slf4j.version>
<hibernate.version>4.2.11.Final</hibernate.version>
<dbcp.version>1.4</dbcp.version>
<servletapi.version>2.5</servletapi.version>
</properties>
<dependencies>
<!-- database pool -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>${dbcp.version}</version>
</dependency>
<!-- Hibernate ORM -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<!-- Spring 3 dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Spring MVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring + aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- ORM integration, e.g Hibernate -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.9.0.RELEASE</version>
</dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>
<!-- Spring Security JSP Taglib -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${spring.security.version}</version>
</dependency>
<!-- jstl for jsp page -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<!-- MySql Driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>${servletapi.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
Related
I have a problem, I'm trying to use two Oracle databases in spring boot using DataSource, The DataSource wiht the #Primay annotation works fine but the oher one only gives me:
SQL Error: 942, SQLState: 42000
ORA-00942: table or view does not exist
I don't have idea what I should do now. Any help will be welcomed. Thanks!
application.properties
spring.datasource.url=jdbc\:oracle\:thin\:[connection] #Not showing for security
spring.datasource.password=[password]
spring.datasource.configuration.maximum-pool-size=30
spring.sgc-datasource.url=jdbc\:oracle\:[connection] #Not showing for security
spring.sgc-datasource.username=[user]
spring.sgc-datasource.password=[password]
spring.sgc-datasource.max-total=30
spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect
spring.jpa.database=default
spring.jpa.hibernate.ddl-auto=none
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.indra.vmo.edenorte</groupId>
<artifactId>InMpData</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>InMpData</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-dbcp/commons-dbcp -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
DatabaseConfiguration.java
package com.indra.vmo.edenorte.config;
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import com.zaxxer.hikari.HikariDataSource;
#Configuration(proxyBeanMethods = false)
public class DatabaseConfiguration {
#Bean
#Primary
#ConfigurationProperties("spring.datasource")
public DataSourceProperties inMpDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#Primary
#ConfigurationProperties("spring.datasource.configuration")
public HikariDataSource inMpDataSource(DataSourceProperties inMpDataSourceProperties) {
return inMpDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
#Bean
#ConfigurationProperties("spring.sgc-datasource")
public DataSourceProperties sgcDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#ConfigurationProperties("spring.sgc-datasource.configuration")
public HikariDataSource sgcDataSource(DataSourceProperties sgcDataSourceProperties) {
return sgcDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
}
Repository from 1st DB
package com.indra.vmo.edenorte.repository.inmp;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.indra.vmo.edenorte.entity.inmp.MpLocalidadesCoordenadas;
#Repository
public interface IMpLocalidadesCoordenadasRepository extends JpaRepository<MpLocalidadesCoordenadas, String> {
}
Repository from 2nd DB
package com.indra.vmo.edenorte.repository.sgc;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import com.indra.vmo.edenorte.entity.sgc.Clientes;
#Repository
public interface IClientesRepository extends JpaRepository<Clientes, Integer> {
#Query("select c from Clientes c where c.docId=?1")
public Clientes findBydocId(String docId);
#Query("select c from Clientes c where c.docId=?1 and c.tipDoc=?2")
public Clientes findBydocIdU(String docId, String tipDoc);
}
SpringBoot auto-config works perfectly for a single datasource. For multiple datasources, you will need to manually configure the EntityManagerFactory beans for each of the datasources. See this article
I could resolve the problem with the following changes in my code:
application.properties
I changed the spring.jpa.hibernate.ddl-auto from none to validate and made some other chages
#Credenciales Datasource (InMpData)
spring.datasource.url=jdbc\:oracle\:thin\:[connection] #Not showing for security
spring.datasource.username=[user]
spring.datasource.password=[password]
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
#Credenciales Datasource (SGC)
spring.sgcdatasource.url=jdbc\:oracle\:thin\:[connection] #Not showing for security
spring.sgcdatasource.username=[user]
spring.sgcdatasource.password=[password]
spring.sgcdatasource.driver-class-name=oracle.jdbc.driver.OracleDriver
#Hibernate config
spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect
spring.jpa.hibernate.ddl-auto=validate
# HikariCP settings
# spring.datasource.hikari.*
spring.datasource.hikari.connection-timeout=60000
spring.datasource.hikari.maximum-pool-size=5
pom.xml
Added a new dependency
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
Divided the DatabaseConfiguration.java in two separeated files InMpConfig.java and SgcConfig.java
InMpConfig.java
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = "com.indra.vmo.edenorte.repository.inmp", entityManagerFactoryRef = "inMpEntityManagerFactory", transactionManagerRef = "inMpTransactionManager")
public class InMpConfig {
#Bean
#Primary
#ConfigurationProperties("spring.datasource")
public DataSourceProperties inMpDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#Primary
#ConfigurationProperties("spring.datasource.configuration")
public DataSource inMpDataSource() {
return inMpDataSourceProperties().initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
/*Primary Entity manager*/
#Primary
#Bean(name = "inMpEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean inMpEntityManagerFactory(EntityManagerFactoryBuilder builder) {
return builder.dataSource(inMpDataSource()).packages("com.indra.vmo.edenorte.entity.inmp").build();
}
#Primary
#Bean
public PlatformTransactionManager inMpTransactionManager(
final #Qualifier("inMpEntityManagerFactory") LocalContainerEntityManagerFactoryBean inMpEntityManagerFactory) {
return new JpaTransactionManager(inMpEntityManagerFactory.getObject());
}
}
SgcConfig.java
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = "com.indra.vmo.edenorte.repository.sgc", entityManagerFactoryRef = "sgcEntityManagerFactory", transactionManagerRef = "sgcTransactionManager")
public class SgcConfig {
#Bean
#ConfigurationProperties("spring.sgcdatasource")
public DataSourceProperties sgcDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#ConfigurationProperties("spring.sgcdatasource.configuration")
public DataSource sgcDataSource() {
return sgcDataSourceProperties().initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
#Bean(name = "sgcEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean sgcEntityManagerFactory(EntityManagerFactoryBuilder builder) {
return builder.dataSource(sgcDataSource()).packages("com.indra.vmo.edenorte.entity.sgc").build();
}
#Bean(name = "sgcTransactionManager")
public PlatformTransactionManager sgcTransactionManager(
final #Qualifier("sgcEntityManagerFactory") LocalContainerEntityManagerFactoryBean sgcEntityManagerFactory) {
return new JpaTransactionManager(sgcEntityManagerFactory.getObject());
}
}
And made some changes to the models, such as add the #Table and #Column annotation
#Entity
#Data
#Table(name = "CLIENTES")
public class Clientes implements Serializable {
#Id
#NotNull
#Column(name = "COD_CLI")
private Integer codCli;
#Column(name = "USUARIO")
private String usuario;
#Column(name = "F_ACTUAL")
private Date fActual;
I hope this is helpful for someone else.
I'm trying to make documentation on the code I'm working with using Spring-boot , swagger2 and H2-database.
Here is the swaggerconfig
#Configuration
#EnableSwagger2
public class SwaggerConfig extends WebMvcConfigurationSupport {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).select()
.apis(RequestHandlerSelectors
.basePackage("se.dala.restserviceswagger.controller"))
.paths(PathSelectors.any())
.build();
}
}
And here is the Controller
#RestController
public class EmployeeController {
private final EmployeeRepository repository;
private final EmployeeResourceAssembler assembler;
public EmployeeController(EmployeeRepository repository, EmployeeResourceAssembler assembler) {
this.repository = repository;
this.assembler = assembler;
}
#GetMapping("/employees/{id}")
public Resource<Employee> get(#PathVariable Long id) {
Employee employee = repository.findById(id).orElseThrow(() -> new EmployeeNotFoundException(id));
return assembler.toResource(employee);
}
#GetMapping("/employees")
public Resources<Resource<Employee>> getAll() {
List<Resource<Employee>> employees = repository.findAll().stream()
.map(assembler::toResource)
.collect(Collectors.toList());
return new Resources<>(employees,
linkTo(methodOn(EmployeeController.class).getAll()).withSelfRel());
}
//Blanda inte ihop resource.getId() med employee.getId(). resource.getId() ger dig en URI.
#PostMapping("/employees")
public ResponseEntity<?> newEmployee(#RequestBody Employee newEmployee) throws URISyntaxException {
Resource<Employee> resource = assembler.toResource(repository.save(newEmployee));
return ResponseEntity.created(new URI(resource.getId().expand().getHref())).body(resource);
}
#PutMapping("/employees/{id}")
public ResponseEntity<?> replace(#RequestBody Employee newEmployee, #PathVariable Long id) throws URISyntaxException {
Employee updatedEmployee = repository.findById(id).map(employee -> {
employee.setName(newEmployee.getName());
employee.setRole(newEmployee.getRole());
return repository.save(employee);
}).orElseGet(() -> {
newEmployee.setId(id);
return repository.save(newEmployee);
});
Resource<Employee> resource = assembler.toResource(updatedEmployee);
return ResponseEntity.created(new URI(resource.getId().expand().getHref())).body(resource);
}
#DeleteMapping("/employees/{id}")
public ResponseEntity<?> delete(#PathVariable Long id) {
repository.deleteById(id);
return ResponseEntity.noContent().build();
}
}
And here is my pom.
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
When I go to http://localhost:8080/v2/api-docs I get it to work but not when I go to http://localhost:8080/swagger-ui.html. There I get:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Thu Feb 14 15:22:38 CET 2019
There was an unexpected error (type=Not Found, status=404).
No message available
I don't have any Spring security or anything.
Use SwaggerConfig without extending WebMvcConfigurationSupport should work then.
Error is not related to security its telling that there is no mapped path with that url.
#Configuration
#EnableSwagger2
public class SwaggerConfig {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).select()
.apis(RequestHandlerSelectors
.basePackage("se.dala.restserviceswagger.controller"))
.paths(PathSelectors.any())
.build();
}
}
Same for me becareful with Spring boot it will work until version 2.8.0
it does'nt work with version 3.0.0
tested with this
#Configuration
#EnableSwagger2
public class SwaggerConfig{
#Value("${application.version}")
private String version;
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.basePackage("com.langton"))
.paths(PathSelectors.any()).build();
}
/**
* will add some importants information to the swagger docs
* #return
*/
private ApiInfo apiInfo() {
return new ApiInfo("Langton ant app", "rest api for langton ant app", version, null,
new Contact("name", "N/A", "email"), null, null, Collections.EMPTY_LIST);
}
}
and in main class
#SpringBootApplication
public class LangtonAntLauncher{
public static void main(String[] args) {
SpringApplication.run(LangtonAntLauncher.class, args);
}
}
I am using Spring Configuration and Jersey Configuration.
This is my spring configuration:
#Component
#Configuration
#EnableScheduling
#EnableAspectJAutoProxy
#EnableTransactionManagement
#ComponentScan(basePackages = { "my.packages" })
public class SpringConfig {
private static final String MESSAGE_SOURCE_BASE_NAME = "i18n/messages";
#Profile(Profiles.APPLICATION)
#Configuration
#PropertySource("classpath:application.properties")
static class ApplicationProperties {
}
#Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder(11);
}
#Bean
public TaskScheduler taskScheduler() {
return new ConcurrentTaskScheduler();
}
#Bean
MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename(MESSAGE_SOURCE_BASE_NAME);
messageSource.setUseCodeAsDefaultMessage(true);
return messageSource;
}
}
This is my Service class and interface:
public interface DAOService {
User register(User user)
}
#Service
public class DAOServiceImpl implements DAOService {
#Override
User register(User user){
return null;
}
}
This is my jersey resource:
Inside ResourceSecurityService class I want to use #Autowire for DAOService
class, but I get null pointer exception, daoService is always null.
#Component
#Path("/security")
#Produces({ MediaType.APPLICATION_JSON })
public class ResourceDAOService {
#Autowired
private DAOService daoService ; //<--- here daoService is null;
#POST
#Path("/register")
#Consumes({ MediaType.APPLICATION_JSON })
#Transactional
public Response register(User user, #Context HttpServletRequest request,
#Context HttpServletResponse response) throws AppException {
return Response.status(Response.Status.CREATED).entity(securityService.register(user)).build();
}
I am using spring version 4.3.8.RELEASE with the next dependencies:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
It could be better if you'd provide a link to your project.
Based on information I see:
make sure you have jersey-spring4 dependency
make sure your Jersey version compatible with integration dependency
check out your project configuration
I advice you to use Spring Boot with auto configurations.
I'm using Spring Boot 1.5.9 with spring-boot-starter-data-jpa and Camel 2.20.1.
As input I get an XML file with a sequence of elements, which I unmarshal with JAXB and after that I aggregate them to a list of elements.
For that I defined a Element class where I associate a root element for JAXB and annotated it as a JPA entity.
#Entity
#Table (name="tblElement", schema="comp")
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Element implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
#Column (name="name")
#XmlElement(required = true)
private String name;
public void Element(){}
//getter and setter methods
...
}
So my camel route processes a list of entries which I want to store to a MySQL database (version: 5.1.73).
#Component
public class CompRoute extends RouteBuilder {
#Autowired
private ElementDao elementDao;
#Override
public void configure() throws Exception {
DataFormat jaxbDataFormat = new JaxbDataFormat("com.comp.beans");
from(file:src/test/resources/input)
.convertBodyTo(byte[].class, "UTF-8")
.split().tokenizeXML("element")
.unmarshal(jaxbDataFormat)
.setProperty("SplitSize", simple("${header.CamelSplitSize}"))
.aggregate(constant(true), new ArrayListAggregationStrategy())
.completionSize(simple("${property.SplitSize}"))
.bean(elementDao, "insertElementList");
}
}
I'm not so familiar with JPA and the transaction manager, so I configured it according these documentations:
https://spring.io/guides/gs/accessing-data-jpa/
https://docs.spring.io/spring-data/jpa/docs/1.5.0.RELEASE/reference/html/jpa.repositories.html
application.properties
spring.datasource.url=jdbc:mysql://compserver:3306/comp
spring.datasource.username=user
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
JpaConfig.java
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(basePackageClasses = CompApplication.class)
class JpaConfig {
#Autowired
DataSource dataSource;
#Bean
public EntityManagerFactory entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(false);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
String entities = ClassUtils.getPackageName(CompApplication.class);
factory.setPackagesToScan(entities);
factory.setDataSource(dataSource);
factory.afterPropertiesSet();
return factory.getObject();
}
#Bean
#Qualifier (value = "jpaTransactionManager")
public PlatformTransactionManager transactionManager() {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory());
return txManager;
}
}
CompApplication.java
#SpringBootApplication
public class CompApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(CompApplication.class);
app.setBannerMode(Banner.Mode.OFF);
app.run(args);
}
}
ElementDao.java
#Service
public class ElementDao {
#Autowired
ElementRepository elementRepository;
#Transactional (transactionManager = "jpaTransactionManager", readOnly = false, propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public void insertElementList(Exchange exchange) {
if(exchange.getIn().getBody() instanceof List) {
List<Element> elements= convertListToElementList(exchange.getIn().getBody(List.class));
if (elements != null) {
elementRepository.save(elements);
}
}
}
}
ElementRepository.java
#Repository
public interface ElementRepository extends CrudRepository<Element, Long> {
}
But my transaction configuration is not working correct. Because if an error occured e.g. while storing the 5th element, the whole transaction is not rolled back. It should not insert any elements. But still the first 4 elements are stored and commited.
I don't understand this behavor? How can I set my service #insertElementList transactional that the whole operation is rolled back when an exception occured during database storage?
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.company</groupId>
<artifactId>company</artifactId>
<version>0.0.1</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<camel.version>2.20.1</camel.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jdbc</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jaxb</artifactId>
<version>2.20.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-artemis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jms</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>com.ibm</groupId>
<artifactId>com.ibm.mq.allclient</artifactId>
<version>9.0.0.1</version>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>4.8</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
</dependencies>
</project>
I found the solution. The problem was the database and not my configuration. The MySql table was of type MyISAM, which does not support transactions and roll back. So I converted the table to InnoDB and now it works - when the transaction fails, all is rolled back.
According to Spring documentation.
#Transactional on beans in the same application context it is defined in. This means that, if you put annotation in a WebApplicationContext for a DispatcherServlet, it only checks for #Transactional beans in your controllers, and not your services.
So, your save method is not transactional , include that package also in which
save method is defined.
Hi i am trying to build up a junit test case #before setup but after processing the junit class, i found no data changed in my database and no exception throws as well. Funny thing is i can call up from the controller and it can save and delete by calling the service from a http client. Below is my code, please help. Thanks a lot.
#SpringApplicationConfiguration(classes = MockServletContext.class)
#WebAppConfiguration
public class UserRepositoryTest extends AbstractBestFirstTest {
private MockMvc mvc;
#Autowired
private UserRepositoryI userRepo;
private void userRepositoryTestPreparer() {
User user = new User();
user.setEmail("markII#gmail.com");
user.setName("Tony Stark");
userRepo.deleteAll();
userRepo.save(user);
}
#BeforeTransaction
public void setUpData() {
userRepositoryTestPreparer();
}
#Before
public void setUp() {
mvc = MockMvcBuilders.standaloneSetup(new SampleController()).build();
}
#After
public void tearDown() {
// implement me
}
#Transactional
#Commit
#Test
public void testSave() {
Assert.assertEquals("save failed", 1, userRepo.findUserByName("Tony Stark").size());
Assert.assertEquals("save failed", 1, userRepo.findUserByEmail("markII#gmail.com").size());
}
#Test
public void testRestfulBasic() throws Exception {
ResultActions actions = mvc.perform(MockMvcRequestBuilders.get("/sample").accept(MediaType.APPLICATION_JSON));
actions.andExpect(status().isOk());
actions.andExpect(content().string(equalTo("Hello World! Greetings from spring boot")));
}
}
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = BestfirstApplication.class)
public abstract class AbstractBestFirstTest {
protected Logger logger = LoggerFactory.getLogger(this.getClass());
}
#Transactional
public interface UserRepositoryI extends CrudRepository<User, Long>,UserRepositoryCustomerizedI {
}
here goes my pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bestfirst</groupId>
<artifactId>bestfirst</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>bestfirst</name>
<description>Spring Boot project for Best First</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<retrofit.version>2.0.0-beta3</retrofit.version>
<org.springframework.version>4.0.2.RELEASE</org.springframework.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.1.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- junit test requires -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- junit test requires -->
<!-- JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- JPA -->
<!-- http client retrofit -->
<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>retrofit</artifactId>
<version>${retrofit.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>converter-gson</artifactId>
<version>2.0.0-beta3</version>
</dependency>
<!-- http client retrofit -->
<!-- mysql connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- mysql connector -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
i eventually get this problem solved. in Spring test senario, we must use PlatformTransactionManager to process transactions. Indeed i missed this part in DB config. after i added into my configuration, the problem is gone!
#Configuration
#EnableTransactionManagement
public class DatabaseConfig {
#Value("${db.driver}")
private String DB_DRIVER;
#Value("${db.password}")
private String DB_PASSWORD;
#Value("${db.url}")
private String DB_URL;
#Value("${db.username}")
private String DB_USERNAME;
#Value("${hibernate.dialect}")
private String HIBERNATE_DIALECT;
#Value("${hibernate.show_sql}")
private String HIBERNATE_SHOW_SQL;
#Value("${hibernate.hbm2ddl.auto}")
private String HIBERNATE_HBM2DDL_AUTO;
#Value("${entitymanager.packagesToScan}")
private String ENTITYMANAGER_PACKAGES_TO_SCAN;
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(DB_DRIVER);
dataSource.setUrl(DB_URL);
dataSource.setUsername(DB_USERNAME);
dataSource.setPassword(DB_PASSWORD);
return dataSource;
}
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource());
sessionFactoryBean.setPackagesToScan(ENTITYMANAGER_PACKAGES_TO_SCAN);
Properties hibernateProperties = new Properties();
hibernateProperties.put("hibernate.dialect", HIBERNATE_DIALECT);
hibernateProperties.put("hibernate.show_sql", HIBERNATE_SHOW_SQL);
hibernateProperties.put("hibernate.hbm2ddl.auto", HIBERNATE_HBM2DDL_AUTO);
sessionFactoryBean.setHibernateProperties(hibernateProperties);
return sessionFactoryBean;
}
#Bean
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
}
You can also annotate the test with Rollback(false) see Persist/commit not working in test environment with Spring JPA JUnit