Controller Method not returning value - spring

I am building a spring boot application .This is my RestController
#RestController
#RequestMapping("api/v1/bikes")
public class BikeController {
#GetMapping
public String s(){
return " show this message";
}
When i paste the following URL in the POSTMAN i get the following message
http://localhost:8080/api/v1/bikes
{
"timestamp": "2018-06-16T21:19:17.791+0000",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/api/v1/bikes"
}
Why i am getting the error ?I expect to see the message returned by the method s().
My project name is bike and it's structure is below
**bike
-- src/main/java
--------- com.globomatics.bike (here is my main class)
--------- controllers**
And this is my main class
#SpringBootApplication
public class BikeApplication {
public static void main(String[] args) {
SpringApplication.run(BikeApplication.class, args);
}
}

The problem is that you #RestController is not being scanned by you #SpringBootApplication. You can do two things here. Either move the controller in the same package as your main class or specify that you want to scan other packages. Something like #SpringBootApplication(scanBasePackages = {"com.globomatics.*"}). Check out the documentation here and here where all of those things are very well explained.

#SpringBootApplication by defult will always scan the same package in which class with main method is present and all the packages inside it. In your case your package with class containing main method is "com.globomatics.bike" so your class BikeController should be either in same package or the the package containing class BikeController must be inside package "com.globomatics.bike". Or you can tell explcitly to scan in some other packages by use of annotation
#ComponentScan("package name you want spring to scan").
change you code to :
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
#ComponentScan("controllers")
public class BikeApplication {
public static void main(String[] args) {
SpringApplication.run(BikeApplication.class, args);
}
}

Related

Spring boot 2: Fail to reach controller method

I am having some spring boot rest tutorial.
I fail to reach the controller method when I call:
http://localhost:8090/customers/stam
Tomcat log:
o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s):
8090 (http) with context path ''
t.s.SpringbootRestDemoApplication : Started SpringbootRestDemoApplication in 2.696 seconds (JVM running for 4.042)
The response I get:
{
"timestamp": "2019-06-02T12:25:03.400+0000",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/customers/stam"
}
Can you assist?
package ttt.springboot_rest_demo;
import ...
#SpringBootApplication
#ComponentScan({"springboot_rest_demo.controller", "springboot_rest_demo.data"})
public class SpringbootRestDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootRestDemoApplication.class, args);
}
}
package ttt.springboot_rest_demo.controller;
import ...
#RestController
#RequestMapping("/customers")
public class CustomerController {
#RequestMapping(value = "/stam", method = RequestMethod.GET)
public ResponseEntity < Customer > getCustomer() {
return new ResponseEntity < >(new Customer(), HttpStatus.OK);
}
}
package ttt.springboot_rest_demo.data;
public class Customer {
private String name;
private int age;
private String email;
private Long id;
//getters and setters
}
This is only a part of the project. I use also a service class but because I have failed, I a added a simple controller method which doesn't need the service class for now, just to ease the example.
Your ComponentScan is incorrect, please check the packages (these package names do not exists):
#ComponentScan({"springboot_rest_demo.controller", "springboot_rest_demo.data"})
Your controller is in ttt.springboot_rest_demo.controller package. Change the package name in the ComponentScan to this package.
#ComponentScan({"ttt.springboot_rest_demo.controller", "springboot_rest_demo.data"})
Alternatively just leaving out the ComponentScan will also work for you, because then you will rely on the default behaviour of Spring Boot to scan all packages under the SpringBootApplication.
Note that if your controller is not a managed bean (for example not scanned by ComponentScan) any Spring annotation you add (like RequestMapping, RestController) is ignored.

how can I use #RequestMapping or #GetMapping annotation without whitelabel error?

I used #RequestMapping or #GetMapping for routing.
But, it doesn't work. It makes whitelabel error page.
(spring boot)
my Application.java
#RestController
#SpringBootApplication
public class SmDemoApplication {
#RequestMapping("/")
String home() {
return "Hello World! smDemo 111";
}
public static void main(String[] args) {
SpringApplication.run(SmDemoApplication.class, args);
}
}
And controller is
#RestController
public class WebRestController {
//#GetMapping("/hello")
#RequestMapping(value="/hello", method=RequestMethod.GET)
public String hello() {
return "Hello World! 222";
}
}
http://localhost:8080 is good.
but, http://localhost:8080/hello makes white label error !!
what's the problem in my code?? (I made my project, using spring starter project)
Springboot reads its stereotype beans ,controllers and configurations from package and subpackages of main class,(until you define #ComponentScan to read other packages) I feel your project main class is in another package than the controller i.e. Controller is not in same or in a sub package where Main class is.
For example , If your main package is in
com.xyz.abc
|_ SmDemoApplication
Keep controller,other beans and configuration in com.xyz.abc package like
com.xyz.abc
|_WebRestController
or sub-packages like
com.xyz.abc.controllers
|_WebRestController

Identifying Start-Class during runtime in spring boot

I am trying to identify a way to know the name of the Main-Class that started SpringBoot.
e.g.
#SpringBootApplication
public class SampleApplication {
public static void main(String[] args) {
SpringApplication.run(SampleApplication.class, args);
}
#RestController
public class SampleController
{
#GetMapping("/hello")
pubic String sayHello()
{
System.out.println("Need start class name: "+System.getProperty("sun.java.command"));
return "hello";
}
}
}
When I run the springboot using java -jar myappname.jar ,the System.getProperty("sun.java.command") returns org.springframework.boot.loader.JarLauncher
Can anyone advise, how can I get the name of actual run class. I have tried specifying the start-class attribute in the manifest.mf. It still gave me org.springframework.boot.loader.JarLauncher as the start-class.
You should be able to #Autowire in the ApplicationContext and then do context.getBeansWithAnnotation(SpringBootApplication.class).values().toArray()[0].getClass().getName(), which will give you the first (and presumably only) bean in the context annotated with #SpringBootApplication

Spring Boot #Value Properties

I have a Spring Boot application and in one of the classes, I try to reference a property from the application.properties file using #Value. But, the property does not get resolved. I have looked at similar posts and tried following the suggestions, but that didn't help. The class is:
#Configuration
#ComponentScan
#EnableAutoConfiguration
public class PrintProperty {
#Value("${file.directory}")
private String fileDirectory;
public void print() {
System.out.println(fileDirectory);
}
}
I have the property file.directory in application.properties. I have other fields as well.
I had the same problem like you. Here's my error code.
#Component
public class GetExprsAndEnvId {
#Value("hello")
private String Mysecret;
public GetExprsAndEnvId() {
System.out.println("construct");
}
public void print(){
System.out.println(this.Mysecret);
}
public String getMysecret() {
return Mysecret;
}
public void setMysecret(String mysecret) {
Mysecret = mysecret;
}
}
This is no problem like this, but
we need to use it like this:
#Autowired
private GetExprsAndEnvId getExprsAndEnvId;
not like this:
getExprsAndEnvId = new GetExprsAndEnvId();
Here, the field annotated with #Value is null because Spring doesn't know about the copy of GetExprsAndEnvId that is created with new and didn't know to how to inject values in it.
Make sure your application.properties file is under src/main/resources/application.properties. Is one way to go. Then add #PostConstruct as follows
Sample Application.properties
file.directory = somePlaceOverHere
Sample Java Class
#ComponentScan
public class PrintProperty {
#Value("${file.directory}")
private String fileDirectory;
#PostConstruct
public void print() {
System.out.println(fileDirectory);
}
}
Code above will print out "somePlaceOverhere"
I´d like to mention, that I used spring boot version 1.4.0 and since this version you can only write:
#Component
public class MongoConnection {
#Value("${spring.data.mongodb.host}")
private String mongoHost;
#Value("${spring.data.mongodb.port}")
private int mongoPort;
#Value("${spring.data.mongodb.database}")
private String mongoDB;
}
Then inject class whenever you want.
EDIT:
From nowadays I would use #ConfigurationProperties because you are able to inject property values in your POJOs. Keep hierarchical sort above your properties. Moreover, you can put validations above POJOs attributes and so on. Take a look at the link
To read the values from application.properties we need to just annotate our main class with #SpringBootApplication and the class where you are reading with #Component or variety of it. Below is the sample where I have read the values from application.properties and it is working fine when web service is invoked. If you deploy the same code as is and try to access from http://localhost:8080/hello you will get the value you have stored in application.properties for the key message.
package com.example;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#SpringBootApplication
#RestController
public class DemoApplication {
#Value("${message}")
private String message;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#RequestMapping("/hello")
String home() {
return message;
}
}
Try and let me know
You haven't included package declarations in the OP but it is possible that neither #SpringBootApplication nor #ComponentScan are scanning for your #Component.
The #ComponentScan Javadoc states:
Either basePackageClasses or basePackages (or its alias value) may be
specified to define specific packages to scan. If specific packages
are not defined, scanning will occur from the package of the class
that declares this annotation.
ISTR wasting a lot of time on this before and found it easiest to simply move my application class to the highest package in my app's package tree.
More recently I encountered a gotcha were the property was being read before the value insertion had been done. Jesse's answer helped as #PostConstruct seems to be the earliest you can read the inserted values, and of course you should let Spring call this.
I had the similar issue and the above examples doesn't help me to read properties. I have posted the complete class which will help you to read properties values from application.properties file in SpringBoot application in the below link.
Spring Boot - Environment #Autowired throws NullPointerException
Your problem is that you need a static PropertySourcesPlaceholderConfigurer Bean definition in your configuration. I say static with emphasis, because I had a non-static one and it didn't work.
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
I had the same issue get value for my property in my service class. I resolved it by using #ConfigurationProperties instead of #Value.
create a class like this:
import org.springframework.boot.context.properties.ConfigurationProperties;
#ConfigurationProperties(prefix = "file")
public class FileProperties {
private String directory;
public String getDirectory() {
return directory;
}
public void setDirectory(String dir) {
this.directory = dir;
}
}
add the following to your BootApplication class:
#EnableConfigurationProperties({
FileProperties.class
})
Inject FileProperties to your PrintProperty class, then you can get hold of the property through the getter method.

how to use the ApplicationArguments in spring-boot

I am learning the Spring-Boot(I am new to it), reading the Spring Boot Document. In the 23.6 Accessing application arguments, It talk about the ApplicationArguments, and the code is:
package com.example.project;
import org.springframework.boot.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;
import java.util.*;
#Component
public class MyBean {
#Autowired
public MyBean(ApplicationArguments args) {
boolean debug = args.containsOption("debug");
List<String> files = args.getNonOptionArgs();
System.out.println(debug);
System.out.println(files);
}
}
It says if run with "--debug logfile.txt" debug=true, files=["logfile.txt"].
But in my project, I don't know how to run it. I create the spring-boot using Maven: The Project Structure
In Spring Boot doc ApplicationArguments is autowired in a bean. Here is a more hands on example where it's used in a Main method.
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application implements ApplicationRunner {
public static void main(String[] args) {
SpringApplication.run(Application.class, args).stop();
}
#Override
public void run(ApplicationArguments args) throws Exception {
boolean debug = args.containsOption("debug");
List<String> files = args.getNonOptionArgs();
System.out.println(debug);
System.out.println(files);
}
}
Assuming that you have an Application class with annotation #SpringBootApplication like in the answer provided by a.b.d.
To be able to provide the arguments within IntelliJ IDEA environment you will need to first Run the main method and then Edit 'Run/Debug Configurations' and under Main Class fill Program arguments field with "--debug logfile.txt":
In one word like a thousand :
the 'Program arguments' in your IDE field prefixed by -- is simply the same name as the 'Option' expected in the 'ApplicationArguments'.
Hence you can match --debug and "args.containsOption("debug")".

Resources