Springboot springapplication gives 404 - spring-boot

Pom:
<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.mycomp.spring</groupId>
<artifactId>springboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot</name>
<url>http://maven.apache.org</url>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Resource class:
package com.mycomp.spring.springboot.resources;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.mycomp.spring.springboot.services.BankService;
#RestController
public class BankResource {
private final Environment env;
private final BankService bankService;
public BankResource(Environment env, BankService bankService) {
this.env = env;
this.bankService = bankService;
}
#RequestMapping("/bankname")
public String getBankName() {
System.out.println("REQUEST RECEIVED");
bankService.getUserAccounts("tets");
return env.getProperty("app.name");
}
}
App class:
package com.mycomp.spring.springboot;
import java.util.Arrays;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import com.mycomp.spring.springboot.config.Appconfiguration;
import com.mycomp.spring.springboot.initializers.Appintializer;
import com.mycomp.spring.springboot.listeners.AppListener;
/**
*
*
*/
public class App {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Appconfiguration.class);
app.addInitializers(new Appintializer());
app.addListeners(new AppListener());
app.setWebApplicationType(WebApplicationType.SERVLET);
System.out.println(Arrays.toString(args));
app.run(args);
// SpringApplication.run(App.class, args);
}
}
AppConfiguration class:
package com.mycomp.spring.springboot.config;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
#Configuration
#EnableAutoConfiguration
public class Appconfiguration {
}
When I run the app, it starts well but when I hit http://localhost:port/bankname it gives me 404.
However when I change my app class like this I am not getting 404 and the resource class returns the bankname as expected.
#SpringBootApplication
public class App {
public static void main(String[] args) {
// SpringApplication app = new SpringApplication(Appconfiguration.class);
// app.addInitializers(new Appintializer());
// app.addListeners(new AppListener());
// app.setWebApplicationType(WebApplicationType.SERVLET);
// System.out.println(Arrays.toString(args));
// app.run(args);
SpringApplication.run(App.class, args);
}
}
Any idea as to why I am getting 404 when I initialize the spring application by creating an instance instead of starting with the static run method?

Try this code for Resource file:
#Controller
public class BankResource {
// Some Codes ...
}
Change #RestController to #Controller.

Related

Getting null value while fetching properties from application.properties file in Springboot

Objective : reading property value from application.properties file in my Java class .
Current behaviour : getting null values
Expected behaviour :
value1
value3
application.properties
category1.subcategory2=value1
category1.subcategory3=value3
greeting.salutation=Hello
TryValueApplication.java
package com.example.tryvalue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class TryValueApplication {
#Value("${category1.subcategory2}")
private String category1;
#Value("basic value")
private String category3;
public static void main(String[] args) {
SpringApplication.run(TryValueApplication.class, args);
TryValueApplication tryValueApplication = new TryValueApplication();
System.out.println("Running main method");
tryValueApplication.printCategory();
}
public void printCategory(){
System.out.println("Print environment values");
System.out.println(category1);
System.out.println(category3);
}
}
Tried :
I tried accessing same value from within #RestController class and it was working .
GreetingController.java
package com.example.tryvalue.controller;
import com.example.tryvalue.EnvironmentValue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class GreetingController {
#Value("${greeting.salutation}")
private String greetingSalutation;
#Autowired
private EnvironmentValue environmentValue;
#GetMapping
public String greeting(){
return greetingSalutation + " world";
}
#GetMapping("/category1")
public String getCategory1(){
return environmentValue.getCategory1();
}
}
EnvironmentValue.java
package com.example.tryvalue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
#Component
public class EnvironmentValue {
#Value("${category1.subcategory2}")
private String category1;
#Value("${category1.subcategory3}")
private String category2;
#Value("basic value")
private String category3;
public EnvironmentValue(){
System.out.println("Creating instance of EnvironmentValue");
}
public String getCategory1(){
return category1;
}
public String getCategory2(){
return category2;
}
public String getCategory3(){
return category3;
}
}
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.7.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>tryValue</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>tryValue</name>
<description>tryValue</description>
<properties>
<java.version>11</java.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-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>
What can be the reason behind this difference in behaviour ?
Thanks .
You are creating a second unmanaged instance of TryValueApplication in your main method so the properties won't be injected into that.
The managed instance of TryValueApplication should have the values injected. Add this to TryValueApplication to print the values
#Value("${category1.subcategory2}")
private String category1;
#Value("${category1.subcategory3}")
private String category3;
public static void main(String[] args) {
SpringApplication.run(TryValueApplication.class, args);
}
#PostConstruct
public void printCategory(){
System.out.println("Print environment values");
System.out.println(category1);
System.out.println(category3);
}

Duplicate Key Error on saving Reactor Mongo result

I'm seeing the following error when attempting to query and update some records to MongoDB using reactive streams:
org.springframework.dao.DuplicateKeyException: E11000 duplicate key error collection: testtrans.submission index: _id_ dup key: { _id: ObjectId('600b10b2fbac4f4483af3e67') }; nested exception is com.mongodb.MongoWriteException
I'm not sure what I'm doing wrong; How do I go about querying and saving results to the database using reactive mongo in a single transaction?
My service class:
package com.example.reactivemongotransaction.service;
import com.example.reactivemongotransaction.dto.Submission;
import com.example.reactivemongotransaction.repository.SubmissionRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
#Slf4j
#Service
public class SubmissionService {
#Autowired
private SubmissionRepository submissionRepository;
public Mono<Submission> saveSubmission(Submission submission) {
log.debug("saving {}", submission);
return submissionRepository.save(submission);
}
#Transactional
public Flux<Submission> lockSubmissions() {
log.debug("setting all locked");
Flux<Submission> submissionFlux = submissionRepository.findAllByLockedFalse();
return submissionFlux
.map(submission -> submission.setLocked(true))
.flatMap(submission -> submissionRepository.save(submission));
}
}
My config:
#Configuration
#EnableMongoAuditing
#EnableTransactionManagement
public class MongoConfiguration {
#Bean
public ReactiveTransactionManager transactionManager(ReactiveMongoDatabaseFactory dbFactory) {
return new ReactiveMongoTransactionManager(dbFactory);
}
}
Controller:
#RestController
#RequestMapping("/submissions")
public class SubmissionController {
#Autowired
private SubmissionService submissionService;
#PostMapping
public Mono<Submission> saveSubmission(final #RequestBody Submission submission) {
return submissionService.saveSubmission(submission);
}
#GetMapping("/lockall")
public Flux<Submission> lockAll() {
return submissionService.lockSubmissions();
}
}
Model:
#ToString
#Getter
#Setter
#Accessors(chain = true)
#Document(collection = "submission")
#TypeAlias("payload")
public class Submission implements Persistable<String> {
#Id
private String id;
#Field("role_name")
#Indexed(unique = true)
private String role;
#CreatedDate
private ZonedDateTime created;
#LastModifiedDate
private ZonedDateTime updated;
private Boolean deleted;
private Boolean enabled;
private boolean locked;
#Override
#JsonIgnore
public boolean isNew() {
if(getCreated() == null)
return true;
else
return false;
}
}
Repository:
public interface SubmissionRepository extends ReactiveMongoRepository<Submission, String> {
Flux<Submission> findAllByLockedFalse();
}
Main class:
#EnableReactiveMongoRepositories
#SpringBootApplication
public class ReactivemongotransactionApplication {
public static void main(String[] args) {
SpringApplication.run(ReactivemongotransactionApplication.class, args);
}
}
application.yml:
spring:
data:
mongodb:
uri: 'mongodb://localhost:27017/testtrans'
server:
port: 8280
Maven 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.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>reactivemongotransaction</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>reactivemongotransaction</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<lombok.version>1.18.6</lombok.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
My request is GET http://localhost:8280/submissions/lockall which return 500. And the logs show errors e.g.:
com.mongodb.MongoWriteException: E11000 duplicate key error collection: testtrans.submission index: _id_ dup key: { _id: ObjectId('600b10b2fbac4f4483af3e67') }
at com.mongodb.internal.async.client.AsyncMongoCollectionImpl.lambda$executeSingleWriteRequest$9(AsyncMongoCollectionImpl.java:1075) ~[mongodb-driver-core-4.1.1.jar:na]
The issue was related to the #CreatedDate not being set (see #EnableMongoAuditing and #CreatedDate Auditing not working in Spring Boot 2.4.3).
Resolved by reverting spring-boot-starter-parent to 2.3.5.RELEASE.

Unable to read configurationProperties

I am trying to use ConfiguartionProperties to read properties from application.prop files. But I am getting NullPointerException because at the time of initiating the bean the properties are not read properly from application.prop file.
#Configuration
#ConfigurationProperties(prefix = "httpool")
public class ClientHttpPoolConfig {
private Integer maxPerRoute;
private Integer maxTotal;
private Integer connectionRequestTimeout;
private Integer connectTimeout;
private Integer socketTimeout;
#Bean
public PoolingHttpClientConnectionManager poolingHttpClntConnMger() {
PoolingHttpClientConnectionManager result = new PoolingHttpClientConnectionManager();
result.setDefaultMaxPerRoute(maxPerRoute); // maxPerRoute is null.
result.setMaxTotal(maxTotal);
return result;
}
}
I simplified as much as I could, so I'm using very simple bean:
StringWrapper
package betlista.springTests.beanInConfiguration;
/** Represents a very simple Bean */
public class StringWrapper {
private String name;
public StringWrapper(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
There is nothing special in configuration class too...
Config
package betlista.springTests.beanInConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
#Component
#ConfigurationProperties
public class Config {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Bean
public StringWrapper getStringWrapper() {
return new StringWrapper(name);
}
}
and finally application
package betlista.springTests.beanInConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class SpringBootConsoleApplication implements CommandLineRunner {
private static Logger LOG = LoggerFactory.getLogger(SpringBootConsoleApplication.class);
#Autowired
StringWrapper stringWrapper;
public static void main(String[] args) {
SpringApplication.run(SpringBootConsoleApplication.class, args);
}
#Override
public void run(String... args) {
LOG.info("stringWrapper.name: {}", stringWrapper.getName());
}
}
Just for completeness
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>betlista</groupId>
<artifactId>springTests-beanInConfiguration</artifactId>
<version>1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.2.5.RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Prefix
Pretty much same works with #ConfigurationProperties("my") and my.name=Betlista in property file.
All available in GitHub: https://github.com/Betlista/SpringTests/tree/master/BeanInConfiguration
in your application.properties files, parameters should be as follow:
httpool.max-per-route=//here your Integer value
httpool.max-total=//here your Integer value
httpool.connection-requestTimeout=//here your Integer value
httpool.connect-timeout=//here your Integer value
httpool.socket-timeout=//here your Integer value
EDITED:
and you must write this annotation to your Main class
#EnableConfigurationProperties({
ClientHttpPoolConfig.class
})

spring boot configuration properties not working

This is driving me up the wall trying to get spring boot #configurationproperties annotation working. So hoping someone can shed some light on this for me as to what I am doing wrong.
I have a spring boot application and it contains a application.properties on the classpath. It has a value in there of
server.contextPath=/test/v1
server.port=8080
spring.profiles.active=dev
vendors=me
I have a application.class which has the spring boot annotation and sits at the top of my package hierarchy
package com.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
#EnableConfigurationProperties
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I am trying to map the property vendors into a configurationproperties bean as below
package com.test.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
#Component
#PropertySource("classpath:application.properties")
#ConfigurationProperties
public class GlobalProperties {
private String vendors;
public String getVendors() {
return vendors;
}
public void setVendors(String vendors) {
this.vendors = vendors;
}
}
and then call this bean from my rest controller. I know it resolves the property as when i rename it the server fails to start. In the code below the props bean is not getting autowired and is null. //code ommitted for brevity
package com.test.controller;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.test.config.GlobalProperties;
#RestController
#Component
public class MController {
//TODO should be wired in from properties file
#Autowired
GlobalProperties props;
private boolean vendorUnknown(String vendor) {
if(props.getAllowedVendor().equalsIgnoreCase(vendor)) {
return true;
}
return false;
}
#RequestMapping(value = "/test/{id}", method = RequestMethod.GET, produces = { "application/json" })
public ResponseEntity<?> getStatus(
#PathVariable String id) {
//#RequestBody Bookmark input
if(vendorUnknown("me")) {
System.out.println("found");
};
return ResponseEntity.noContent().build();
}
}
Anybody point me to what i have done wrong please?
UPDATE:
changed the code above to be a more simplistic version with a test class to recreate the issue. See below for my pom.xml and test class
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.me.test</groupId>
<artifactId>test-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- tag::actuator[] -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- end::actuator[] -->
<!-- tag::tests[] -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- end::tests[] -->
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Test class:
package com.test.controller;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.BeanFactory;
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.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class MControllerTest {
#Autowired
private MockMvc mockMvc;
#InjectMocks
MController testController;
#Before
public void setup() {
// this must be called for the #Mock annotations above to be processed
// and for the mock service to be injected into the controller under
// test.
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.standaloneSetup(testController).build();
}
#Test
public void testPropertiesMsg() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/test/1").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
}
}
Remove #PropertySource. You can keep #Component, or if you don't, specify #EnableConfigurationProperties(GlobalProperties.class).
Don't need #Component on testController. But I think your issue is where you're calling vendorUnknown method from. It's not shown in your code. If calling from the constructor, then the bean initialization has not completed yet, and GlobalProperties props is indeed null.
Edit:
Based on OP's edit, here's a fully working solution.
DemoApplication.java:
#SpringBootApplication
#EnableConfigurationProperties
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
DemoController.java:
#RestController
public class DemoController {
#Autowired
private DemoProperties props;
#GetMapping(value = "/", produces = APPLICATION_JSON_VALUE)
public ResponseEntity<?> getVendor() {
return ResponseEntity.ok(props.getVendors());
}
}
DemoProperties.java:
#ConfigurationProperties
#Component
public class DemoProperties {
private String vendors;
public String getVendors() {
return vendors;
}
public void setVendors(String vendors) {
this.vendors = vendors;
}
}
application.properties:
vendors=me
DemoControllerTest.java:
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class DemoControllerTest {
#Autowired
TestRestTemplate restTemplate;
#Test
public void testGenVendor() throws Exception {
String vendor = restTemplate.getForObject("/", String.class);
assertThat(vendor).isEqualTo("me");
}
}
Problems with OP's code:
MockMvc doesn't use the main class, so EnableConfigurationPropertiesis not processed. MockMvc or WebMvcTest is designed to test the web layer (duh!), not the whole app. Using either of those. the properties bean should be set by the test.
InjectMocks fails silently. See Why You Should Not Use InjectMocks Annotation to Autowire Fields.
Add #EnableConfigurationProperties to your Application class to enable scanning ConfigurationProperties beans.

#RequestMapping not redirecting to the specified URL : Spring Boot application

I am trying to create a sample spring boot application which can connect to postgres. But I am not able to redirect to the path specified in the rest controller. The code for my project is given below:
pom.xml
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.vmware.springboot</groupId>
<artifactId>SpringBootSample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>SpringBootDemo1</name>
<description>Sample project for Spring Eureka</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.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.postgresql</groupId>
<artifactId>postgresql</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>
application.properties
server.port=3000
spring.datasource.url= jdbc:postgresql://localhost:5432/local_db
spring.datasource.data-username=postgres
spring.datasource.data-password=postgres
spring.jpa.hibernate.ddl-auto=create-drop
SpringBootExampleApplication.java
package org.kumar.springboot;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.kumar.spring.enitiy.Employee;
#SpringBootApplication
#ComponentScan
public class SpringBootExampleApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootExampleApplication.class, args);
}
}
EmployeeController.java
package org.kumar.spring.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.kumar.spring.enitiy.Employee;
import org.kumar.spring.repository.EmployeeRepository;
#RestController
#RequestMapping("/data")
public class EmployeeController {
#Autowired
private EmployeeRepository employeeRepository;
#RequestMapping("/employees")
public List<Employee> getEmployees(){
return (List<Employee>)employeeRepository.findAll();
}
}
Employee.java
package org.kumar.spring.enitiy;
public class Employee {
private String employeeId;
private String employeeName;
public String getEmployeeId() {
return employeeId;
}
public void setEmployeeId(String employeeId) {
this.employeeId = employeeId;
}
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
#Override
public String toString() {
return "Employee [employeeId=" + employeeId + ", employeeName=" + employeeName + "]";
}
public Employee(String employeeId, String employeeName) {
super();
this.employeeId = employeeId;
this.employeeName = employeeName;
}
}
EmployeeRepository.java
package org.kumar.spring.repository;
import org.springframework.data.repository.CrudRepository;
import org.kumar.spring.enitiy.Employee;
public interface EmployeeRepository extends CrudRepository<Employee, String>
{
}
I am trying to run the following:
Request : GET http://localhost:3000/data/employees
Response :
{
"timestamp": 1492152367659,
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/data/employees"
}
What mistake am I committing.
Basically, your EmployeeController class has not been detected/scanned by the Spring container because of the classes are in different package hierarchy and the container has not been instructed to scan in which package to look for.
So there are two options to solve the issue:
(1) Change your SpringBootExampleApplication class package to org.kumar.spring
(2) Add #ComponentScan(basePackages = {"org.kumar.spring"})
I suggest you prefer the option(1) above otherwise, for option(2), you need to add #EnableJpaRepositories to make the program to work from end to end (i.e., connecting to the database using your EmployeeRepository class).

Resources