Spring Boot #RestController and #Controller - java

I have a #Controller:
#Controller("/")
public class GreetingController {
#GetMapping("/greeting")
public String get() {
return "greeting";
}
}
Also a #RestController:
#RestController("/test")
public class TestRest {
#RequestMapping()
public List<TestDTO> get() {
List<TestDTO> dtos = new ArrayList<>();
dtos.add(new TestDTO("value1","value2"));
dtos.add(new TestDTO("value1","value2"));
return dtos;
}
}
The #Controller works correctly, and serves a static HTML page at src/main/resources/templates/greeting.html
But the #RestController does not work, all I get are 404s.
If I move the method from the #RestController into the #Controller and add a #ResponseBody annotation, it then starts working.
How can I have the controllers as different classes?

#RestController and #Controller do not take the path to the resource as a parameter. Perhaps try something along the lines of...
#RestController
#RequestMapping("/test")
public class TestRest {
#RequestMapping(method = RequestMethod.GET)
public List<TestDTO> get() {
List<TestDTO> dtos = new ArrayList<>();
dtos.add(new TestDTO("value1","value2"));
dtos.add(new TestDTO("value1","value2"));
return dtos;
}
}

You question itself has the answers, for the RESTController to work, you would need to have a #ResponseBody because, for all REST calls, there needs to be response body to return the data.
I hope adding #ResponseBody alone will solve the problem.

Related

Spring Security Principal transformation

Is there a way to transform a Spring Security Principal before it is injected in a RestController method?
Let's say I have defined the following class:
#RestController
public class MyController {
#GetMapping("/test")
public void getWithPrincipalA(#AuthenticationPrincipal PrincipalTypeA a) {
...
}
#GetMapping("/test")
public void getWithPrincipalB(#AuthenticationPrincipal PrincipalTypeB b) {
...
}
}
I know that these controller methods are ambiguous and I could do several things to solve that, but what I would rather do is transform the #AuthenticationPrincipal to some type I can define myself. The result would become something like:
#RestController
public class MyController {
#GetMapping("/test")
public void getWithTransformedPrincipal(#AuthenticationPrincipal MyTransformedPrincipal principal) {
...
}
}
Now I basically could define a single controller for several different authentication principals, without having to change the API.
Any help would be appreciated :)
Too keep things simple and transparant you could simply transform the principal in your controller method and dispatch the generic principal from there.
#RestController
public class MyController {
#GetMapping("/test")
public void getWithTransformedPrincipal(#AuthenticationPrincipal Principal principal) {
GenericPrincipal generic = PrincipalTransformer.transform(principal);
doSomethingWithPrincipal(generic);
}
}

Add a Page to a Spring Boot App (Extremely Basic)

I have a spring boot api. My problem is how do I actually create a page in my app?
I created a page in /resources/static/templates/index.html
and when I get to /api/lol I just see a string saying index and not the page.
How do I do this?
#RequestMapping("/api")
#RestController
public class Controller {
#Autowired
JdbcTemplate jdbcTemplate;
#GetMapping("/lol")
String lol() {
return "index";
}
}
You annotated your class with #RestController.
What you want is a MVC Controller, so replace it with #Controller.
Here is an example of the documentation :
#Controller
public class HelloController {
#GetMapping("/hello")
public String handle(Model model) {
model.addAttribute("message", "Hello World!");
return "index";
}
}
Put your index.html in src/main/resources/static
and then in your controller
#RequestMapping("/api")
#RestController
public class Controller {
#Autowired
JdbcTemplate jdbcTemplate;
#GetMapping("/lol")
String lol() {
return "index.html";
}
}

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

Why do I get 404 for rest with spring-boot

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/.

Spring #Controller annotation and Java based configuration

I have a Spring Java configuration and I'd like to build 2 instances of the same controller
#Bean(name = CONTROLLER_A)
public MyController getMyAController() {
return new MyController(new A());
}
#Bean(name = CONTROLLER_B)
public MyController getMyBController() {
return new MyController(new B());
}
public class MyController {
...
#RequestMapping(method = RequestMethod.GET)
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response){
...
}
}
There is no way to annotate the methods as #Controller and without it, Spring doesn't consider that instance as Controller instances (the exception handling doesn't work properly).
Is there a way to get the controller work properly w/o using xml configuration?
EDIT: the only way I can make it works is by extending AbstractController, but I don't really want to use inheritance.

Categories