Why do I get 404 for rest with spring-boot - java

I am implementing rest services with Spring Boot. The entity classes are defined in a separate package. So I added that with Component annotation in Application.java.
#Configuration
#EnableAutoConfiguration
#ComponentScan("org.mdacc.rists.cghub.model")
#EnableJpaRepositories(basePackages = "org.mdacc.rists.cghub.model")
public class Application
{
public static void main( String[] args )
{
SpringApplication.run(Application.class, args);
}
}
Here is my controller class:
// SeqController.java
#RestController
public class SeqController {
#Autowired
private SeqService seqService;
#RequestMapping(
value = "/api/seqs",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<SeqTb>> getSeqs() {
List<SeqTb> seqs = seqService.findAll();
return new ResponseEntity<List<SeqTb>>(seqs, HttpStatus.OK);
}
}
I also created a JPA data repository that extends JPARepository in which I added custom query code.
// SeqRepository.java
#Repository
public interface SeqRepository extends JpaRepository<SeqTb, Integer> {
#Override
public List<SeqTb> findAll();
#Query("SELECT s FROM SeqTb s where s.analysisId = :analysisId")
public SeqTb findByAnalysisId(String analysisId);
}
Below is the servicebean class that implements a service interface
// SeqServiceBean.java
#Service
public class SeqServiceBean implements SeqService {
#Autowired
private SeqRepository seqRepository;
#Override
public List<SeqTb> findAll() {
List<SeqTb> seqs = seqRepository.findAll();
return seqs;
}
public SeqTb findByAnalysisId(String analysisId) {
SeqTb seq = seqRepository.findByAnalysisId(analysisId);
return seq;
}
}
When I started the application and type the following url in the browser "http://localhost:8080/api/seqs" , I got 404 error. What did I miss?
Edit #1:
I decided to take out the JPA repository stuff and change the controller class to the following:
#RestController
//#RequestMapping("/")
public class SeqController {
private static BigInteger nextId;
private static Map<BigInteger, Greeting> greetingMap;
private static Greeting save(Greeting greeting) {
if(greetingMap == null) {
greetingMap = new HashMap<BigInteger, Greeting>();
nextId = BigInteger.ONE;
}
greeting.setId(nextId);
nextId = nextId.add(BigInteger.ONE);
greetingMap.put(greeting.getId(), greeting);
return greeting;
}
static {
Greeting g1 = new Greeting();
g1.setText("Hello World!");
save(g1);
Greeting g2 = new Greeting();
g1.setText("Hola Mundo!");
save(g2);
}
#RequestMapping(
value = "/api/greetings",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Collection<Greeting>> getGreetings() {
Collection<Greeting> greetings = greetingMap.values();
return new ResponseEntity<Collection<Greeting>>(greetings, HttpStatus.OK);
}
}
When I started the application and put "localhost:8080/api/greetings" in my browser I still got 404.

==>Did you make sure that your Spring Boot application class and your Rest Controller are in the same base package? For Example if your package for Spring Boot application class is com.example.demo, then your Rest Controller should be in same base package as com.example.demo.controller.
==>I think that is the reason boot is unable to map to the uri of your rest controller. Because #SpringBootApplication has #ComponentScan and #Configuration embedded in it already. Try doing this. I hope it works.

If spring boot starter web is not there in your pom.xml then add the same as the reason could be the code not being able to map the endpoints.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

The first thing I would try is to put #RequestMapping("/") on the class definition of the controller. Keep the same value on the method.
Another thing, unrelated to your problem, is that you do not need to define that custom query. JPA is actually smart enough to do the query you defined just by using that method name. Check out the findByLastName example here: https://spring.io/guides/gs/accessing-data-jpa/.

Related

Request to Spring Controller returns 404 not found

I am trying to set up a Spring MVC app but every time I call the http://localhost:9001/tasks API from postman I get the following error:
Here is my code:
#SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
public class TaskManagerApplication {
public static void main(String[] args) {
SpringApplication.run(TaskManagerApplication.class, args);
}
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("http://localhost:4200");
}
};
}
}
TaskRepository:
#Path("tasks")
#ApiIgnore
#Component
#AllArgsConstructor
public class TaskResource {
private final TaskService taskService;
#GET
#Produces(APPLICATION_JSON)
public List<Task> getAllTasks() {
return taskService.getTasks();
}
TaskService:
#Service
#RequiredArgsConstructor
public class TaskService {
private final TaskRepository taskRepository;
public List<Task> getTasks() {
return taskRepository.findAll();
}
Project Structure:
You are using JAX-RS in spring boot. Spring handles rest in its own way, if you want to use JAX-RS instead of Springs Rest Annotations, you need to do some extra configurations.
First, you need to add a JAX-RS dependency in your build.gradle or pom.xml file. I guess you have already done that. Jersey is one of the JAX-RS implementation, if you want to add this, you need to do the following.
build.gradle
implementation "org.springframework.boot:spring-boot-starter-jersey"
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
</dependency>
After that, you need to register the JAX-RS endpoints with Spring. I guess you missed this step.
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.context.annotation.Configuration;
#Configuration
public class JaxrsConfig extends ResourceConfig {
public JaxrsConfig() {
register(TaskResource.class);
}
}
After this, your JAX-RS endpoints will be registered with spring.
But I will suggest you to follow spring annotations if you are using spring. If you use spring annotations your code will look like this.
#RestController
#RequestMapping(path = "tasks")
public class TaskResource {
#GetMapping(path = "", produces = MediaType.APPLICATION_JSON_VALUE)
public List<String> getAllTasks() {
return Arrays.asList("a","b");
}
}
Also you will need to remove JAX-RS from spring to use this Spring MVC annoatations to work.

Java Spring Test Autowired Controller is null error

I would like to test a Java Web Controller using Spring (Not Spring Boot).
My Controller is
#Controller
#RequestMapping("/orders")
public class OrderHdrController {
#RequestMapping(value = "/getOrderList", method = RequestMethod.POST)
#ResponseBody
public Map<String, Object> getOrderTables(OrderSearchDto orderSearchDto) { ... }
}
And my test class is:
public class FilterActivityTest2 {
#Autowired
private OrderHdrController orderHdrController;
#Test
public void testActivity() {
OrderSearchDto orderSearchDto = new OrderSearchDto();
OrderSearchPanelDto orderSearchPanelDto = new OrderSearchPanelDto();
orderSearchPanelDto.setActivityTypes(Arrays.asList("TAKEOVER","DELIVERY"));
orderSearchDto.setOrderSearchPanelDto(orderSearchPanelDto);
Map<String, Object> result = orderHdrController.getOrderTables(orderSearchDto);
assertNotNull(result);
}
}
I do not want to mock any objects. I just want to run the test on the controller all the way to the db. But when I debug into the test, the orderHdrController is null in testActivity method.
What have I done wrong? Please help or ask me for more information. Thanks.
#RunWith(SpringRunner.class)
#WebMvcTest(OrderHdrController.class)
public class FilterActivityTest2 {
#Autowired
private OrderHdrController orderHdrController;
#Test
public void testActivity() {
OrderSearchDto orderSearchDto = new OrderSearchDto();
OrderSearchPanelDto orderSearchPanelDto = new OrderSearchPanelDto();
orderSearchPanelDto.setActivityTypes(Arrays.asList("TAKEOVER","DELIVERY"));
orderSearchDto.setOrderSearchPanelDto(orderSearchPanelDto);
Map<String, Object> result = orderHdrController.getOrderTables(orderSearchDto);
assertNotNull(result);
}
}
or If dont using any spring or junit then why using #test
simply make a main class
public class FilterActivityTest2{
public static void main(String args[]){
....... put your tast case code here
}
}
Your FilterActivityTest2 needs to be managed by the Spring context, to be able to autowire dependencies.
To do that, either annotate your test class with:
#RunWith(SpringRunner.class)
#SpringBootTest
Or extend the main test class that already has these annotations. If you created your project using spring initializer, you'll find that class in the tests created for you.
public class FilterActivityTest2 extends MyApplicationTests {
EDIT
For Spring, you can use #ContextConfiguration. Here is a good tutorial.
Also see the official documentation here.
If you do not use spring boot then you can create the application context manually
#Before
public void init() {
ApplicationContext context = desired implementation;
controller = context.getBean("bean name");
}
But better do this
#RunWith(MockitoJUnitRunner.class)
public class FilterActivityTest2 {
private OrderHdrController orderHdrController;
#MockBean
private Service service;
#MockBean
private Dao dao;
#Before
public void init() {
orderHdrController = new OrderHdrController(service, dao ....);
}
#Test
....
}

AnjularJs integration with Spring boot

I need to call index() method in java class. But I tried this way it is not working.
It is going up to console.log('coming here....'); in controller.js, after that http path is not recognizing.
#RestController
public class DatumBoxShedule {
#Autowired
private DatumService datumService;
#RequestMapping(value = "/loadIndex", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
public String index() throws IOException {
}
}
controller.js
app.controller('datumBoxShedule', function($scope, $http) {
$scope.newTodo = {};
$scope.loadIndex = function(){
console.log('coming here....');
$http.get('loadIndex')
.success(function(data, status, headers, config) {
$scope.todos = data;
})
.error(function(data, status, headers, config) {
alert('Error loading DatumBoxShedule');
});
};
$scope.loadIndex();
});
Is the Angular project part of the Spring project?
Are other mappings working (in other words: is the REST-Service running)?
If not: do you have an embedded container like Tomcat in your depenedencies?
For example, you could add the dependency for Tomcat to your project:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
I figureout ,issue is not in the anujularjs.Issue is in the spring.
my componantscan is not working
package main.java.datumbox;
#Configuration
#SpringBootApplication
#EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class})
#ComponentScan({"main.java.datumbox.service.impl","main.java.datumbox.controller","main.java.datumbox.service"})
public class Application{
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class,args);
}
}
package main.java.datumbox.service.impl;
public class DatumServiceImpl{
#Autowired(required = true)
DatumDataRepository datumDataRepository;
}
package main.java.datumbox.controller;
#RestController
public class DatumBoxController {
#Autowired
private DatumService datumService;
#Autowired
private DatumServiceImpl datumServiceImpl;
#RequestMapping( value = "/loadIndex" , produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
public String index() throws IOException {
}
}
package main.java.datumbox.service;
#Service
public class DatumService{
#Autowired
HitApiService hitApiService;
}
error is coming..
APPLICATION FAILED TO START
Description:
Field datumServiceImpl in main.java.datumbox.controller.DatumBoxController required a bean of type 'main.java.datumbox.service.impl.DatumServiceImpl' that could not be found.
Action:
Consider defining a bean of type 'main.java.datumbox.service.impl.DatumServiceImpl' in your configuration.

Project starting in embedded Tomcat, but doesn't work in full Tomcat

I have small SpringBoot project with few RESTful-services which I made for studying Spring and REST technology. If I run it through spring-boot:run it working properly on localhost:8080/ + what I wrote in #RequestMapping in Controller. In example, on localhost:8080/restapp/test/{id} :
#RequestMapping(value = "http ://localhost:8080/restapps-0.0.1-SNAPSHOT/restapp/test/{id}",
method = RequestMethod.GET)
public String getWelcome(#PathVariable(value = "id") String id) {
return "Welcome to jax-rs " + id;
}
While deploying in full Tomcat, it started on localhost:8080/project_version it opened index.html (whitch I added for testing while created project) and i haven't access to my services. I trying:
localhost:8080/project_version/restapp/test/{id}
localhost:8080/project_version/test/{id}
localhost:8080/project_version/project_name/restapp/test/{id}
but have only 404 error.
Application.java
#Configuration
#EnableAutoConfiguration
#ComponentScan
public class Application {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
}
}
Controller.java
#RestController
public class Controller extends ApplicationConfig {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> s = new HashSet<Class<?>>();
s.add(Controller.class);
return s;
}
#RequestMapping(value = "http ://localhost:8080/restapps-0.0.1-SNAPSHOT/restapp/test/{id}",
method = RequestMethod.GET)
public String getWelcome(#PathVariable(value = "id") String id) {
return "Welcome to jax-rs " + id;
}
}
ApplicationConfig - empty class, which extends Application.
Thanx for all advises/answers.
Your controller mapping is NOT correct because Controller #RequestMapping value should be only the relative path, not the absolute path, so it needs to be changed as shown below:
#RestController
#RequestMapping(value="/test")
public class Controller extends ApplicationConfig {
#RequestMapping(value = "{id}", method = RequestMethod.GET)
public String getWelcome(#PathVariable(value = "id") String id) {
return "Welcome to jax-rs " + id;
}
}
You should be able to access your Controller method using the below url (for resource id 1):
http ://localhost:8080/restapps-0.0.1-SNAPSHOT/test/1
Try to add #SpringBootApplication or #EnableWebMvc in Application class.
Then see javaguy's answer.
Problem was solved by extending Application from SpringBootServletInitializer.

How to configure #RestController?

Can somebody tell me how to configure #RestController?
I do this :
#RestController
#EnableAutoConfiguration
public class Application {
#RequestMapping("/test.htm")
#ResponseBody
String home() {
return "Hello Worlds!";
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
#Controller
public class MusicControler {
class Test{
String name;
int age;
}
#RequestMapping(value = "/MyController")
public Test MyController() {
Test test = new Test();
test.name = "zl.shi";
test.age = 16;
return test;
}
}
When I request /test.htm, it is ok but I get response 404 for /testController.htm. Can someone help me about it?
use following code to create rest controller
#RestController
#RequestMapping("/service/")
public class Application {
#RequestMapping(value = "/getmemberdetail/{id}/{info}", method = RequestMethod.GET, produces = { "application/json" })
public ResponseEntity<String> getuserdetail(#PathVariable int portalType,#PathVariable("id") int id,#PathVariable("info") String info) throws JsonProcessingException, ParseException{}
}
if you want to know how to use it you should read about it
Difference between spring #Controller and #RestController annotation
when you make starter-project spring you should make another class where you are going to put you controller don't forget RestController annotation or the controller annotation ( as best practice you shouldn't use the starter class of spring boot ) i hope this helps you
ps don't tag spring-mvc and spring-boot it's not the same thing

Categories