Rest api call fails in POST API call - java

Hi I have newly created a microservice post API call with STS4 which was build and deployed successfully. the localhost:8080/demo/ link is opening up. but the rest maping underneath it failing with 404 not found. I haved added requestmapping and post mapping and tried still not working. Can anyone fix the code?
PFB the code:-
POM:-
<?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.3</version>
<!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<maven.test.skip> true</maven.test.skip>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</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.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
here is the config for swagger :-
package com.example.demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
#Configuration
//Enable Swagger
#EnableSwagger2
public class SwaggerConfig {
#Bean
public Docket api() {
//creating constructor of Docket class that accepts parameter DocumentationType
return new Docket(DocumentationType.SWAGGER_2);
}
}
here is the rest controller:
package com.example.demo.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.model.MyResponse;
import com.example.demo.service.dao.DemoServiceDAO;
import com.example.demo.service.impl.DemoServiceImpl;
#RestController
#Validated
#RequestMapping(value ="/newcall", method = RequestMethod.POST)
public class DemoController {
Logger logger =LoggerFactory.getLogger(DemoController.class);
#PostMapping(value ="/newResp", headers ="Accept=Application/JSON", produces="Application/JSON")
public MyResponse newResp(#RequestBody String myInput) {
MyResponse myResponse = null;
try {
DemoServiceDAO demoServiceDAO = new DemoServiceImpl();
logger.debug("Started getValue() method...");
myResponse=demoServiceDAO.getValue(myInput);
logger.debug("Completed getValue() method...");
}
catch(Exception e){
logger.debug("Exception occurs",e);
e.printStackTrace();
System.out.println("Exception occurs");
}
return myResponse;
}
}
here is the application:-
package com.example.demo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
#SpringBootApplication
#ComponentScan(basePackages = "com.example.*")
#EnableSwagger2
public class DemoApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
Logger logger =LoggerFactory.getLogger(DemoApplication.class);
SpringApplication.run(DemoApplication.class, args);
}
}
here is the app.properties:-
logging.file.name=opt/var/logs/demoService.log
logging.file.path=opt/var/logs
logging.level.web=DEBUG
spring.jmx.default-domain=demo
server.servlet.context-path=/demo
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always
springfox.documentation.swagger-ui.base-url=true
management.endpoint.info.enabled: true
springfox.documentation.swagger-ui.enabled=true
springfox.documentation.open-api.enabled=true
spring.security.user.name = user
spring.security.user.password = password
Output from http://localhost:8080/demo/
"_links" : {
"profile" : {
"href" : "http://localhost:8080/demo/profile"
}
}
full code is in github with logs:-
https://github.com/Sourav654/tempProject/tree/master/demo

Without any logs we can only guess, but looking at your Controller I see some weird things. Can you please try the following?
#RestController
#Validated
#RequestMapping("newcall")
public class DemoController {
Logger logger =LoggerFactory.getLogger(DemoController.class);
#PostMapping("/newResp", consumes = "application/json", produces = application/json)
public MyResponse newResp(#RequestBody String myInput) {
MyResponse myResponse = null;
try {
DemoServiceDAO demoServiceDAO = new DemoServiceImpl();
logger.debug("Started getValue() method...");
myResponse=demoServiceDAO.getValue(myInput);
logger.debug("Completed getValue() method...");
}
catch(Exception e){
logger.debug("Exception occurs",e);
e.printStackTrace();
System.out.println("Exception occurs");
}
return myResponse;
}
}

Related

Spring MVC RestController 404 The requested resource is not available

I am trying to write a simple 'hello world' application using Spring MVC.
My goal is to send a GET response and receive a text message, however it keeps returning 404 "The requested resource [/api/hello] is not available". What can potentially be wrong? Below is my code:
package org.example.rest.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping("/api")
public class MyRestController {
#GetMapping("/hello")
public String hello() {
return "Hello";
}
}
Config
package org.example.rest.configuration;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
import java.util.Properties;
#EnableWebMvc
#Configuration
#EnableTransactionManagement
#ComponentScan(basePackages = "org.example.rest")
public class MyConfig {
#Bean
public DataSource dataSource() {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
try {
dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/my_db?useSSL=false&serverTimezone=UTC");
dataSource.setUser("bestuser");
dataSource.setPassword("bestuser");
} catch (PropertyVetoException e) {
throw new RuntimeException(e);
}
return dataSource;
}
#Bean
public LocalSessionFactoryBean sessionFactoryBean() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource());
sessionFactoryBean.setPackagesToScan("org.example.rest.entity");
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.dialect",
"org.hibernate.dialect.MySQLDialect");
hibernateProperties.setProperty("hibernate.show_sql",
"true");
sessionFactoryBean.setHibernateProperties(hibernateProperties);
return sessionFactoryBean;
}
#Bean
public HibernateTransactionManager hibernateTransactionManager() {
HibernateTransactionManager manager = new HibernateTransactionManager();
manager.setSessionFactory(sessionFactoryBean().getObject());
return manager;
}
}
package org.example.rest.configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class MyWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{MyConfig.class};
}
#Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
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>org.example</groupId>
<artifactId>spring-rest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.24.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.3.9</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
I am using IntelliJ IDEA 2022.2.2 (Ultimate Edition).
Server is Tomcat 9.0.71

APPLICATION FAILED TO START - Consider defining a bean of type in your configuration [SpringBoot]

I'm new to Spring and I'm getting the error below when I try to run my application. Am I missing any Spring annotation?
Should I create a JpaUpdateRepositoryImpl class instead?
APPLICATION FAILED TO START
Description:
Parameter 1 of constructor in com.myapp.domain.service.StoreAsyncService required a bean of type 'com.myapp.domain.repository.JpaUpdateRepository' that could not be found.
Action:
Consider defining a bean of type 'com.myapp.domain.repository.JpaUpdateRepository' in your configuration.
Service Class
package com.myapp.domain.service;
import com.myapp.domain.model.Store;
import com.myapp.domain.repository.JpaUpdateRepository;
import com.myapp.facade.ElasticSearchFacade;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ForkJoinPool;
#Async
#Service
public class StoreAsyncService {
static Logger logger = LoggerFactory.getLogger(StoreAsyncService.class);
private Integer partitionSize = 1000;
private Integer parallelism = 4;
private final ElasticSearchFacade elasticSearch;
private final JpaUpdateRepository repository;
public StoreAsyncService(ElasticSearchFacade elasticSearch, JpaUpdateRepository repository) {
this.elasticSearch = elasticSearch;
this.repository = repository;
}
public void exportStores(List<Store> stores) {
List<List<Store>> storesSubset = Lists.partition(stores, partitionSize);
ForkJoinPool pool = new ForkJoinPool(parallelism);
for (List<Store> storesItem : storesSubset) {
CompletableFuture.runAsync(() -> sendToElastic(storesItem), pool);
}
pool.shutdown();
LocalDateTime localDateTime = LocalDateTime.now();
repository.updateCadConfiguracaoWithLastExecutionDate(localDateTime.format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss")));
}
public void sendToElastic(List<Store> stores) {
elasticSearch.post(stores);
logger.info("sentToElastic - {} Stores sent to Elastic", stores.size());
}
}
Repository
package bcom.myapp.domain.repository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
#Repository
public interface JpaUpdateRepository extends CrudRepository<Object, Integer> {
#Modifying
#Query("UPDATE CONFIG c SET c.VALOR = :lastExecutionDate WHERE c.CODE = 'EXPORTACAO_WORKER_STORE' ")
void updateCadConfiguracaoWithLastExecutionDate(#Param("lastExecutionDate") String lastExecutionDate);
}
POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
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.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>br.com.getnet</groupId>
<artifactId>cstores-worker</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>tores-worker</name>
<properties>
<java.version>11</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</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>
<version>2.3.1.RELEASE</version><!--$NO-MVN-MAN-VER$-->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.7.RELEASE</version><!--$NO-MVN-MAN-VER$-->
</dependency>
<dependency>
<groupId>com.oracle.ojdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>19.3.0.0</version><!--$NO-MVN-MAN-VER$-->
<exclusions>
<exclusion>
<groupId>com.oracle.ojdbc</groupId>
<artifactId>simplefan</artifactId>
</exclusion>
<exclusion>
<groupId>com.oracle.ojdbc</groupId>
<artifactId>ons</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.4.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version><!--$NO-MVN-MAN-VER$-->
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.google.collections</groupId>
<artifactId>google-collections</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.10.1</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.10.1</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>4.1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Configuration
package com.myapp.infrastructure.config;
import org.apache.http.HttpHost;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
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.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
import static org.apache.http.auth.AuthScope.ANY;
#Configuration
#EnableElasticsearchRepositories(basePackages = "com.myapp.infrastructure")
#ComponentScan(basePackages = {"com.myapp.domain"})
public class ElasticSearchConfig {
#Value("${app.url}")
String elasticPostUrl;
#Value("${app.port}")
Integer elasticPostPort;
#Value("${app.username}")
String userName;
#Value("${app.password}")
String userPassword;
BasicCredentialsProvider credentialsProvider;
#Bean
public RestHighLevelClient client() {
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(userName, userPassword);
this.credentialsProvider = new BasicCredentialsProvider();
this.credentialsProvider.setCredentials(ANY, credentials);
HttpHost httpHost = new HttpHost(elasticPostUrl, elasticPostPort, "http");
RestClientBuilder builder = RestClient.builder(httpHost)
.setHttpClientConfigCallback(httpClientBuilder ->
httpClientBuilder.setDefaultCredentialsProvider(
this.credentialsProvider));
return new RestHighLevelClient(builder);
}
#Bean
public ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchRestTemplate(client());
}
}
You need to use #EnableAsync on the class level instead of #Async and use #Async on the Methods that shall run asynchronously, As the #EnableAsync annotation applied on application classes for asynchronous behavior and look for methods marked with #Async annotation and run in background thread pools.
It would be nice to check your imports, package declaration and config java files. Please add them and I will be happy to help.
You can try to set up a scan for your repository in your SpringBoot Main application like:
#EnableJpaRepositories("...your.repository.package.name")

Spring Boot Can't See My Mapstruct Mapper

I defined the mapper but Spring Boot can't detect it. I couldn't find the problem for days. Please help. Tried on IDEA and Netbeans. Tried to add some annotations on main class from this thread.
Description:
Parameter 1 of constructor in
com.example.springmysqlelastic.service.impl.UserService required a
bean of type 'com.example.springmysqlelastic.mapper.UserMapper' that
could not be found.
Action:
Consider defining a bean of type
'com.example.springmysqlelastic.mapper.UserMapper' in your
configuration.
UserMapper.java
package com.example.springmysqlelastic.mapper;
import com.example.springmysqlelastic.model.Food;
import com.example.springmysqlelastic.model.FoodModel;
import com.example.springmysqlelastic.model.User;
import com.example.springmysqlelastic.model.UserModel;
import com.example.springmysqlelastic.model.dto.FoodDTO;
import com.example.springmysqlelastic.model.dto.UserDTO;
import org.mapstruct.Mapper;
import org.springframework.stereotype.Component;
import java.util.List;
//#Component
#Mapper(componentModel = "spring")
public interface UserMapper {
UserDTO toUserDTO(User user);
List<UserDTO> toUserDtos(List<User> users);
User toUser(UserDTO userDTO);
List<User> toUsers(List<UserDTO> userDTOS);
UserModel toUserModel(User user);
/*
FoodDTO toFoodDTO(Food food);
List<FoodDTO> toFoodDtos(List<Food> foods);
Food toFood(FoodDTO foodDTO);
List<Food> toFoods(List<FoodDTO> foodDTOS);
FoodModel toFoodModel(Food food);*/
}
UserService
package com.example.springmysqlelastic.service.impl;
import com.example.springmysqlelastic.mapper.UserMapper;
import com.example.springmysqlelastic.model.User;
import com.example.springmysqlelastic.model.dto.UserDTO;
import com.example.springmysqlelastic.repo.IUserDAO;
import com.example.springmysqlelastic.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.util.List;
#Service
public class UserService implements IUserService {
private IUserDAO userDAO;
private UserMapper userMapper;
#Autowired
public UserService(IUserDAO userDAO, UserMapper userMapper) {
this.userDAO = userDAO;
this.userMapper = userMapper;
}
#Override
public UserDTO save(UserDTO userDTO) {
User user = this.userDAO.save(this.userMapper.toUser(userDTO));
return this.userMapper.toUserDTO(user);
}
#Override
public UserDTO findById(Long id) {
return this.userMapper.toUserDTO(this.userDAO.findById(id).orElse(null));
}
#Override
public List<UserDTO> findAll() {
return this.userMapper.toUserDtos(this.userDAO.findAll());
}
}
UserController.java
package com.example.springmysqlelastic.rest;
import com.example.springmysqlelastic.model.dto.UserDTO;
import com.example.springmysqlelastic.service.IUserService;
import com.example.springmysqlelastic.utils.PathResources;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
#RestController
#RequestMapping("/user") //PathResources.USER
public class UserController {
private final IUserService userService;
#Autowired
public UserController(IUserService userService) {
this.userService = userService;
}
#PostMapping("/save") //PathResources.SAVE
public ResponseEntity<UserDTO> saveUser(#RequestBody UserDTO userDTO) {
return new ResponseEntity<>(this.userService.save(userDTO), HttpStatus.OK);
}
#GetMapping("/find-one/{id}") //PathResources.FIND_ONE + "/{" + PathResources.ID + "}"
public ResponseEntity<UserDTO> findById(#PathVariable Long id) {
return new ResponseEntity<>(this.userService.findById(id), HttpStatus.OK);
}
#GetMapping("/find-all") //PathResources.FIND_ALL
public ResponseEntity<List<UserDTO>> findById() {
return new ResponseEntity<>(this.userService.findAll(), HttpStatus.OK);
}
}
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.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>spring-mysql-elastic</artifactId>
<packaging>jar</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>spring-mysql-elastic</name>
<description>Demo project for Mysql and ElasticSearch Synchronization in Spring</description>
<properties>
<java.version>1.8</java.version>
<mapstruct.version>1.4.0.Beta3</mapstruct.version>
<org.json.version>20190722</org.json.version>
<swagger.version>2.9.2</swagger.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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>${org.json.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<!--<version>1.18.12</version>-->
<type>jar</type>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>2.0.2</version>
<type>jar</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<mainClass>com.example.springmysqlelastic.SpringMysqlElasticApplication</mainClass>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
Main class
package com.example.springmysqlelastic;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.scheduling.annotation.EnableScheduling;
#SpringBootApplication
//#SpringBootApplication(scanBasePackages={"com.example.springmysqlelastic"})
#EnableElasticsearchRepositories("com.example.springmysqlelastic.repo.elastic")
#EnableScheduling
//#ComponentScan(scanBasePackages = {"com.example.springmysqlelastic"})
//#EntityScan("com.example.springmysqlelastic.model")
//#EnableJpaRepositories("com.example.springmysqlelastic")
//#ComponentScan(basePackages = {"com.example.springmysqlelastic"})
//#EnableAutoConfiguration
public class SpringMysqlElasticApplication {
public static void main(String[] args) {
SpringApplication.run(SpringMysqlElasticApplication.class, args);
}
}
In the documentation says that in addition to the main dependency, you need to add annotationProcessor
Example for Gradle:
dependencies {
implementation 'org.mapstruct:mapstruct:1.4.2.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.2.Final'
}
I think its an issue with swagger conflicting with the mapstruct library..
I modified your POM like below and it started working for me. They have some documentation here that talks about it. https://www.programmersought.com/article/6208308983/
<?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.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>spring-mysql-elastic</artifactId>
<packaging>jar</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>spring-mysql-elastic</name>
<description>Demo project for Mysql and ElasticSearch Synchronization in Spring</description>
<properties>
<java.version>1.8</java.version>
<mapstruct.version>1.4.0.Beta3</mapstruct.version>
<org.json.version>20190722</org.json.version>
<swagger.version>2.9.2</swagger.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>${org.json.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
<exclusions>
<exclusion>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
<exclusions>
<exclusion>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<!--<version>1.18.12</version>-->
<type>jar</type>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>2.0.2</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.0.Beta3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<mainClass>com.example.springmysqlelastic.SpringMysqlElasticApplication</mainClass>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4.0.Beta3</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
PS: I have removed JPA dependency to make it work without spring. Forget it.
You can find that I have changed swagger dependencies to look like below -
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
<exclusions>
<exclusion>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
<exclusions>
<exclusion>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</exclusion>
</exclusions>
</dependency>
Can you check if it works for you?
Update
After codegen step, this is what it generates -
package com.example.springmysqlelastic.mapper;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Generated;
import org.springframework.stereotype.Component;
#Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2020-08-11T16:40:57+0530",
comments = "version: 1.4.0.Beta3, compiler: javac, environment: Java 1.8.0_265 (Private Build)"
)
#Component
public class UserMapperImpl implements UserMapper {
#Override
public UserDTO toUserDTO(User user) {
if ( user == null ) {
return null;
}
UserDTO userDTO = new UserDTO();
return userDTO;
}
#Override
public List<UserDTO> toUserDtos(List<User> users) {
if ( users == null ) {
return null;
}
List<UserDTO> list = new ArrayList<UserDTO>( users.size() );
for ( User user : users ) {
list.add( toUserDTO( user ) );
}
return list;
}
#Override
public User toUser(UserDTO userDTO) {
if ( userDTO == null ) {
return null;
}
User user = new User();
return user;
}
#Override
public List<User> toUsers(List<UserDTO> userDTOS) {
if ( userDTOS == null ) {
return null;
}
List<User> list = new ArrayList<User>( userDTOS.size() );
for ( UserDTO userDTO : userDTOS ) {
list.add( toUser( userDTO ) );
}
return list;
}
}

Basic Spring based WSSecurity client gets a null response

I've been following this tutorial to learn how to develop a basic spring client and server application using wssecurity (certificates).
The demo works beautifully, but i need to deploy my application on a wildfly server, so i had to change the example a bit in order to avoid the embedded tomcat, the changes are as follows:
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.memorynotfound.spring.ws</groupId>
<artifactId>ws-security-certificate-wss4j-security-interceptor</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>SPRING-WS - ${project.artifactId}</name>
<url>http://memorynotfound.com</url>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-security</artifactId>
</dependency>
<dependency>
<groupId>org.apache.ws.security</groupId>
<artifactId>wss4j</artifactId>
<version>1.6.19</version>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
<version>1.6.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>2.5.0</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<sources>
<source>src/main/resources/xsd</source>
</sources>
<generatePackage>com.memorynotfound.beer</generatePackage>
</configuration>
</plugin>
</plugins>
</build>
RunServer.java
package com.memorynotfound.server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
#SpringBootApplication
public class RunServer extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(RunServer.class);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(applicationClass);
}
private static Class<RunServer> applicationClass = RunServer.class;
}
BeerEndpoint.java
package it.corvallis.soap.endpoint;
import com.memorynotfound.beer.Beer;
import com.memorynotfound.beer.GetBeerRequest;
import com.memorynotfound.beer.GetBeerResponse;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;
import org.springframework.ws.soap.server.endpoint.annotation.SoapAction;
#Endpoint
public class BeerEndpoint {
public static final String NAMESPACE_URI = "http://memorynotfound.com/beer";
#PayloadRoot(namespace = NAMESPACE_URI, localPart = "getBeerRequest")
#SoapAction("http://localhost:8080/ws/beers")
#ResponsePayload
public GetBeerResponse getBeer(#RequestPayload GetBeerRequest request) {
GetBeerResponse beerResponse = new GetBeerResponse();
Beer beer = new Beer();
beer.setId(request.getId());
beer.setName("Beer name");
beerResponse.setBeer(beer);
return beerResponse;
}
}
I deployed the server application on my wildfly and i tried to call it using the same client application used in the tutorial. The service seems to answer correctly, the beerResponse object is correctly istantiated, but, as soon as the object is being sent back to the the client, i see it's NULL.
What am i missing?
Thanks in advance
Oh well, next time i'll read better. At the same link of my first post, a guy asked the same question in the comments, here is the solution: add a callBackHandler to the client configuration, and modify the securityInterceptor to use this handler.
SoapClientConfig.java
package com.memorynotfound.client;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.stereotype.Component;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
import org.springframework.ws.soap.security.wss4j2.Wss4jSecurityInterceptor;
import org.springframework.ws.soap.security.wss4j2.callback.KeyStoreCallbackHandler;
import org.springframework.ws.soap.security.wss4j2.support.CryptoFactoryBean;
import java.io.IOException;
#Configuration
public class SoapClientConfig {
#Bean
public Wss4jSecurityInterceptor securityInterceptor() throws Exception {
Wss4jSecurityInterceptor securityInterceptor = new Wss4jSecurityInterceptor();
// set security actions
securityInterceptor.setSecurementActions("Timestamp Signature Encrypt");
// sign the request
securityInterceptor.setSecurementUsername("client");
securityInterceptor.setSecurementPassword("changeit");
securityInterceptor.setSecurementSignatureCrypto(getCryptoFactoryBean().getObject());
// encrypt the request
securityInterceptor.setSecurementEncryptionUser("server-public");
securityInterceptor.setSecurementEncryptionCrypto(getCryptoFactoryBean().getObject());
securityInterceptor.setSecurementEncryptionParts("{Content}{http://memorynotfound.com/beer}getBeerRequest");
// sign the response
securityInterceptor.setValidationActions("Signature Encrypt");
securityInterceptor.setValidationSignatureCrypto(getCryptoFactoryBean().getObject());
securityInterceptor.setValidationDecryptionCrypto(getCryptoFactoryBean().getObject());
securityInterceptor.setValidationCallbackHandler(securityCallbackHandler());
return securityInterceptor;
}
#Bean
public CryptoFactoryBean getCryptoFactoryBean() throws IOException {
CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();
cryptoFactoryBean.setKeyStorePassword("changeit");
cryptoFactoryBean.setKeyStoreLocation(new ClassPathResource("client.jks"));
return cryptoFactoryBean;
}
#Bean
public Jaxb2Marshaller getMarshaller(){
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("com.memorynotfound.beer");
return marshaller;
}
#Bean
public BeerClient getBeerClient() throws Exception {
BeerClient beerClient = new BeerClient();
beerClient.setMarshaller(getMarshaller());
beerClient.setUnmarshaller(getMarshaller());
beerClient.setDefaultUri("http://localhost:8080/ws/beers");
ClientInterceptor[] interceptors = new ClientInterceptor[]{securityInterceptor()};
beerClient.setInterceptors(interceptors);
return beerClient;
}
#Bean
public KeyStoreCallbackHandler securityCallbackHandler(){
KeyStoreCallbackHandler callbackHandler = new KeyStoreCallbackHandler();
callbackHandler.setPrivateKeyPassword("changeit");
return callbackHandler;
}
}

Spring boot - configure context-path

I have configured application.properties‬ as explained here with :
server.servlet.context-path=/test
And in my #RestController I have a simple a simple #RequestMapping:
#RequestMapping(value = "/products", method = RequestMethod.GET)
But still when sending a request to http://localhost:8080/test/products I get tomcat - 404 response.
Full code:
package com.siemens;
import java.util.HashMap;
import java.util.Map;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class ProductServiceController {
private static Map<String, Product> productRepo = new HashMap<>();
static {
Product honey = new Product();
honey.setId("1");
honey.setName("Honey");
productRepo.put(honey.getId(), honey);
Product almond = new Product();
almond.setId("2");
almond.setName("Almond");
productRepo.put(almond.getId(), almond);
}
#RequestMapping(value = "/products", method = RequestMethod.GET)
public ResponseEntity<Object> getProduct() {
return new ResponseEntity<>(productRepo.values(), HttpStatus.OK);
}
}
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.example</groupId>
<artifactId>siemens</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>siemens</name>
<description>Demo project for siemens</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
#SpringBootApplication:
#SpringBootApplication
public class SiemensApplication {
public static void main(String[] args) {
SpringApplication.run(SiemensApplication.class, args);
}
}
Running on tomcat 9, if there is more code or config needed please comment below, thank you.
Any request should 'know' how to get to this controller. I would suggest trying this:
#RestController
#RequestMapping("psc")
public class ProductServiceController {
#RequestMapping(value = "products", method = RequestMethod.GET)
public ResponseEntity<Object> getProduct() {
return new ResponseEntity<>(productRepo.values(), HttpStatus.OK);
}
this way you can send a GET request, to the following url:
http://localhost:8080/test/psc/products
add the #RequestMapping annotation to specify the path to this class(controller)
get rid of the "/" on every #RequestMapping path value (just a cosmetic suggestion)

Categories