How to save single document to Elasticsearch index? - elasticsearch

I am trying to put into my ES index mapping an exemplary two fielded book class entity like below. As a result I ONLY get the index and mapping created but the JSON is not put in the place.
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class ElasticSearchTransactionsApplicationTests {
#Autowired
private BookRepository bookRepository;
#Autowired
private ElasticsearchTemplate elasticsearchTemplate;
#Test
public void shouldCreateSingleBookEntityWitRepository(){
elasticsearchTemplate.deleteIndex(Book.class);
elasticsearchTemplate.createIndex(Book.class);
elasticsearchTemplate.putMapping(Book.class);
elasticsearchTemplate.refresh(Book.class);
//given
IndexQuery queryCreatingBookEntity = new BookBuilder("1").setTitle("BBB").buildBookIndex();
//when
elasticsearchTemplate.index(queryCreatingBookEntity);
elasticsearchTemplate.refresh(Book.class);
//then
assertThat(bookRepository.findOne("1"), is(notNullValue()));
}
While it creates the index and mapping BUT it does not put the Book inside it - why?
EDIT
Test fils like this:
java.lang.AssertionError:
Expected: is not null
but: was null
Expected :is not null
Actual :null
<Click to see difference>
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
When I GET _all/_mapping
{
"bookshop": {
"mappings": {
"book": {
"properties": {
"bid": {
"type": "string"
},
"title": {
"type": "string"
}
}
}
}
}
}
Also I check my index and mapping created but when I try to get the content:
GET /bookshop/book/1
{
"_index": "bookshop",
"_type": "book",
"_id": "1",
"found": false
}
So I get found false. So no book added.
EDIT 2
I have ES 2.3.5 form their official repo. below are the version packages.
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RC1</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-elasticsearch</artifactId>
</dependency>
<dependency> <!--version 2.0.2 to getClient form ElasticTemplate-->
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.14.8</version>
</dependency>
</dependencies>
<!-- For executable JAR packaging-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository><!--version 2.0.2 to getClient form ElasticTemplate-->
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots><enabled>false</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
Book.java
#Data
#Document(indexName = "bookshop", type = "book", shards = 1, replicas = 0, refreshInterval = "-1")
public class Book {
#Id
private String bID;
#Field(type = FieldType.String, store = true)
private String title;
}
I have also put my book.java with lombok generated #Data and extended #Document content

My code is almost similar to yours. I've used this when I was playing with Spring Data Elasticsearch ages ago. I've just updated the version to 1.4.0.RELEASE The test is passing.
The 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.demo</groupId>
<artifactId>data-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>data-demo</name>
<description>Demo project for Spring Data ES and JPA</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.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-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
</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>
The Book.class
package com.demo.model;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.annotation.Id;
/**
* Holds the details of book.
*/
#Document(indexName = "book")
public class Book {
#Id
private String bookId;
private String title;
public String getBookId() {
return bookId;
}
public void setBookId(String bookId) {
this.bookId = bookId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
The Repository
package com.demo.search.repository;
import com.demo.model.Book;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
/**
* Holds the Elasticsearch CRUD operations for {#link Book} entity.
*/
public interface BookSearchRepository extends ElasticsearchRepository<Book, String> {
}
And finally, the test.
package com.demo.search.repository;
import com.demo.model.Book;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
/**
* Test things on {#link BookSearchRepository}
*/
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class BookSearchRepositoryTest {
#Autowired
private BookSearchRepository bookRepository;
#Autowired
private ElasticsearchTemplate elasticsearchTemplate;
#Before
public void before() {
elasticsearchTemplate.deleteIndex(Book.class);
elasticsearchTemplate.createIndex(Book.class);
elasticsearchTemplate.putMapping(Book.class);
elasticsearchTemplate.refresh(Book.class);
}
#Test
public void shouldSaveBook(){
Book book = new Book();
book.setBookId("1");
book.setTitle("Learning Scala");
Book indexedBook = bookRepository.save(book);
assertThat(indexedBook, is(notNullValue()));
assertThat(indexedBook.getBookId(), is(book.getBookId()));
assertThat(bookRepository.findOne("1"), is(notNullValue()));
}
}

Related

Spring Social LinkedIn : 'org.springframework.social.linkedin.api.LinkedIn' that could not be found

I'm trying to create a Spring Social application with Spring Boot and Im facing issues starting it . I have gone through Spring social documentation and Spring Social sample projects searching around the web. Whatever Ive tried did not work and I was wandering if someone can help me with this here .
LinkedInController
package com.example.demo;
import org.springframework.social.connect.ConnectionRepository;
import org.springframework.social.linkedin.api.LinkedIn;
import org.springframework.social.linkedin.api.ProfileOperations;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
#RequestMapping("/linkedin")
public class LinkedInController {
private static final String LINKEDIN_DISPLAY = "linkedin";
private static final String LINKEDIN_REDIRECT = "redirect:/connect/linkedin";
private LinkedIn linkedIn;
private ConnectionRepository connectionRepository;
public LinkedInController(LinkedIn linkedIn, ConnectionRepository connectionRepository) {
this.linkedIn = linkedIn;
this.connectionRepository = connectionRepository;
}
#GetMapping
public String helloLinkedIn(Model model) {
if (connectionRepository.findPrimaryConnection(LinkedIn.class) == null) {
return LINKEDIN_REDIRECT;
}
ProfileOperations user = linkedIn.profileOperations();
System.out.println(user);
model.addAttribute("linkedInProfile",linkedIn.profileOperations().getUserProfileFull());
return LINKEDIN_DISPLAY;
}
}
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>HCLinkedIn</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>HCLinkedIn</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.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>
<start-class>com.example.demo.HcLinkedInApplication</start-class>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-linkedin</artifactId>
<version>1.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-core</artifactId>
<version>1.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-config</artifactId>
<version>1.1.6.RELEASE</version>
</dependency>
<!-- <dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-security</artifactId>
<version>1.1.6.RELEASE</version>
</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>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
application.properties
spring.social.linkedin.app-id=<<client-key>>
spring.social.linkedin.app-secret=<<client-secret>>
I had the same issue, turns out I forgot to add the OAuth2.0 redirect url.
Log in to your developer's account on linkedin and under the heading OAuth 2.0
There will be an input field for the redirect url called Authorized Redirect URLs:
Add the redirect url..say you are testing using your localhost, put http://localhost:8080/connect/linkedin
replace 8080 by your port and /connect/linkedin by whatever you are using to access the authorization.
Also, incase you haven't specified..add linkedinConnect.html and linkedinConnected.html to your templates/connect

Spring boot Rest Api controller getting 404 error

I'm exposing my services by using Rest in Spring boot. I'm exposing my service with 2 different approach first by using cxf jaxrs dependency and other by spring rest dependency. In first approach i'm getting 404 error when i run my services in postman. But in second approach i'm getting my output. Please help me out.
First approach with cxf jaxrs
#Path("/locations")
public interface LocationRestController {
#GET
public List<Location> getLocations();
}
******************************************
#RestController
public class LocationRestControllerImpl implements LocationRestController {
#Autowired
LocationRepos repos;
#Override
public List<Location> getLocations() {
return repos.findAll();
}}
{
"timestamp": "2018-09-17T03:36:05.283+0000",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/locationweb/locations"
}
Second approach using spring inbuilt dependency
#RestController
#RequestMapping("/locations")
public class LocationRestControllerImpl {
#Autowired
LocationRepos repos;
#GetMapping
public List<Location> getLocations() {
return repos.findAll();
}}
Pom file
<?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.project.abhishek</groupId>
<artifactId>student</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>student</name>
<description>Student DAL</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
"pom.xml" <version>2.1.0.M2</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>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>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>9.0.12</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<version>2.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.0.13</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-spring-boot-starter-jaxrs</artifactId>
<version>3.2.6</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
please refer below code for correct implementation
public interface LocationRestController {
public List<Location> getLocations();
}
******************************************
#RestController(value="/locationweb/locations")
public class LocationRestControllerImpl implements LocationRestController {
#Autowired
LocationRepos repos;
#Override
#GetMapping
public List<Location> getLocations() {
return repos.findAll();
}}
{
This line might be the issue
#RestController
public class LocationRestControllerImpl implements LocationRestController {
remove #RestController from the class in 1st approach
Try this example,
https://dzone.com/articles/spring-boot-building-restful-web-services-with-jersey
Most probably you are missing Spring/Jersey integration or Jersey Configuration.
Do add Jersey Configuration for Spring boot to understand Jersey.
Below is the code for Jersey Configuration for convenience.
#Configuration
#ApplicationPath("rest")
public class Config extends ResourceConfig {
public Config() {
}
#PostConstruct
public void setUp() {
register(Controller.class);
}
}
Make sure you have CXF configuration and set as a service bean as if you use #RestController you are actually not implementing CXF so to order to handle requests by CXF, you need to configure CXF server.
#Configuration
public class CXFConfig {
#Autowired
private Bus bus;
#Bean
public Server rsServer() {
final JAXRSServerFactoryBean endpoint = new JAXRSServerFactoryBean();
endpoint.setBus(bus);
endpoint.setAddress("/");
endpoint.setServiceBeans(Arrays.asList(LocationRestController ()));
return endpoint.create();
}
#Bean
public LocationRestController locationController() {
return new LocationRestControllerImpl();
}
}
Note: No need to implement a controller, you can have directly controller.

Spring Boot WebFlux test not finding MockMvc

Problem
I'm trying to run a simple spring boot test and I'm getting errors that suggest it can't MockMvc at runtime. Documentation suggests I'm using the correct annotations and I created my pom.xml using start.spring.io. Not sure why its having issues.
Error:
No qualifying bean of type 'org.springframework.test.web.servlet.MockMvc'
TestCode
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class MyWebApplicationTests {
#Autowired
MockMvc mockMvc;
#Test
public void Can_Do_Something() throws Exception {
mockMvc.perform(get("/hello-world")).andDo(print()).andExpect(status().isOk())
.andExpect(content().string(containsString("Hello World")));
}
}
Documentation:
I was using this doc as a reference ->
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-testing-with-mock-environment
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.mywebapp</groupId>
<artifactId>webapp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>my-webapp</name>
<description>Backend application</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.M1</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>10</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.6</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
As this Question seems to appear at the top of search lists when people are trying to test their endpoints after they've switched to Spring WebFlux, I'll add what I was able to determine here. (It should be noted that in the past I was having an incredibly hard time getting the WebTestClient to function with RestController annotated endpoints. But this code works. I think I was missing a dependency and it wasn't clear.)
MyService.java
#Service
public class MyService {
public String doSomething(String input) {
return input + " implementation";
}
}
MyController.java
#RestController
#RequestMapping(value = "/api/v1/my")
public class MyController {
#Autowired
private MyService myService;
#RequestMapping(value = "", method = RequestMethod.POST, consumes = {APPLICATION_JSON_VALUE})
public ResponseEntity<Mono<String>> processPost(#RequestBody String input)
{
String response = myService.doSomething(input);
return ResponseEntity.ok(Mono.just(response));
}
TestMyController.java
#ExtendWith(SpringExtension.class)
#WebFluxTest(MyController.class)
public class TestMyController {
#Autowired
private WebTestClient webTestClient;
#MockBean
private MyService myService;
#Test
public void testPost() throws Exception {
// Setup the Mock MyService. Note the 'mocked' vs 'implementation'
when(myService.doSomething(anyString())).thenAnswer((Answer<String>) invocation -> {
String input = invocation.getArgument(0);
return input + " mocked";
});
String response = webTestClient.post()
.uri("/api/v1/my")
.body(BodyInserters.fromObject("is"))
.accept(MediaType.APPLICATION_JSON)
.exchange()
.expectStatus().isOk()
.returnResult(String.class)
.getResponseBody()
.blockFirst();
assertThat(response).matches("is mocked");
}
}
The dependencies that can cause issues that are hard to diagnose appear to be from reactor-test. So if the WebTestClient is not working, make sure that dependency exists.
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.1.5.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<version>3.2.9.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>jackson-module-kotlin</artifactId>
<groupId>com.fasterxml.jackson.module</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.4.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.truth</groupId>
<artifactId>truth</artifactId>
<version>0.45</version>
<scope>test</scope>
</dependency>
As pointed out by M. Deinum MockMvc isn't loaded for the WebFlux configuration in Spring Boot. You need to use WebTestClient instead. So replace AutoConfigureMockMvc with AutoConfigureWebTestClient and utilize the the webTestClient methods in its place.
One thing to note is that this is making actual web calls behind the scenes and will start the server. MockMVC does not start the server. What is the difference between MockMvc and WebTestClient?

spring boot - web mvc test does not find controller mapping

In this spring-boot project the following WebMvcTest fails because the GET /items mapping from the ItemController is not found
#RunWith(SpringRunner.class)
#WebMvcTest(ItemController.class)
#AutoConfigureMockMvc
public class Test_ItemController {
#Autowired
private MockMvc mvc;
#MockBean
private ItemDao dao;
#MockBean
private CartDao cartDao;
#Test
public void test() throws Exception {
// setting up mock response
Cart cart = new Cart();
cart.setId(1);
Item item = new Item();
item.setCart(cart);
item.setItemName("toothbrush");
item.setId(1);
//---------------------
List<Item> items = new ArrayList<>();
items.add(item);
given(this.dao.findAll()).willReturn(items);
this.mvc.perform(get("items").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk());
}
}
The error is:
2018-02-26 12:10:45.816 WARN 12252 --- [ main] o.s.web.servlet.PageNotFound :
No mapping found for HTTP request with URI [items] in DispatcherServlet with name ''
MockHttpServletRequest:
HTTP Method = GET
Request URI = items
Parameters = {}
Headers = {Accept=[application/json]}
Body = <no character encoding set>
Session Attrs = {}
Handler:
Type = null
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 404
Error message = null
Headers = {}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
Here is the controller (just a little experiment, so don't focus on missing ResponseEntity and missing service layer)
#RestController
public class ItemController
{
private static final Logger LOG = LoggerFactory.getLogger(ItemController.class);
#Autowired ItemDao dao;
#GetMapping("items")
public List<Item> getAll()
{
List<Item> res = new ArrayList<>();
dao.findAll().forEach(res::add);
return res;
}
#PostMapping("items")
public Item addItem(#RequestBody Item item)
{
return dao.save(item);
}
#GetMapping("items/{item_id}")
public Item getItemById(#PathVariable("item_id") long item_id)
{
Item item = dao.findById(item_id).get();
LOG.info(" ---------------- Retrieved item: {}", item.toString());
return item;
}
}
This is the 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RC1</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-actuator</artifactId>
</dependency>
<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.springframework.boot</groupId>
<artifactId>spring-boot-devtools</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>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
Thanks for the help
Yes, ok I forgot the slash in the endpoint
this.mvc.perform(get("/items").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk());
simple comment instead of downvote would suffice imho

Not able to run the starter guide code of Building Spring Boot Rest Service

I am trying to build rest service using Spring Boot. I am learning to implement it using the this Spring's guide. I have built the application using STS as a Maven application and the code is exact replica of the guide and when I try to run the application I get the below connection error
I also tried to run the github code for the same guide provided by Spring and that code also gives same the error as above. I am new to Spring Boot and any help would be appreciated.
Below is my code
App.java
package Greetings.Web_Services;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class App
{
public static void main( String[] args )
{
System.out.println("App Started");
SpringApplication.run(App.class, args);
}
}
Greetings.java
package Greetings.Web_Services;
public class Greetings {
private final long id;
private final String content;
public Greetings(long id, String content){
this.id = id;
this.content = content;
}
public long getId(){
return id;
}
public String getContent(){
return content;
}
}
GreetingsController.java
package Greetings.Web_Services;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class GreetingsController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
#RequestMapping("/greeting")
public Greetings greeting(#RequestParam(value="name", defaultValue="World") String name) {
return new Greetings(counter.incrementAndGet(),
String.format(template, name));
}
}
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.springframework</groupId>
<artifactId>gs-rest-service</artifactId>
<version>0.1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency> -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-releases</id>
<url>https://repo.spring.io/libs-release</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-releases</id>
<url>https://repo.spring.io/libs-release</url>
</pluginRepository>
</pluginRepositories>
</project>
GitHub link for the project of above code
Thanks!!
The code in the guide is correct and it was not working earlier for which I had also raised an issue in the GitHub community of the guide. Later when I updated the STS and restarted, it seems to work now. One of the modifier in the community also recommended the same after I explained the scenario. Hope this saves someone's time.

Resources