I'm using Quarkus Rest Client to perform a GET request to an external API service. This service, however, does not directly return the resource (XML) I need to receive, but it performs a redirect to another API service which returns the resource.
When I try to navigate to the path which asks the API service for the resource (i.e. localhost:8080/hello) I get redirected to the page with the resource instead of receiving and processing it.
Putting a breakpoint after the request, shows that the part of the code after the request is never reached.
Here is the code of the endpoint:
#Path("/hello")
public class GreetingResource {
#Inject
#RestClient
MyService myService;
#GET
#Produces(MediaType.TEXT_PLAIN)
public String hello() {
myService.performGet();
return "you are here"; // breakpoint here, it is never reached
}
}
And here is the code of MyService:
#Path("/..")
#RegisterRestClient(configKey="key")
public interface MyService {
#GET
#Path("/..")
#Produces(MediaType.TEXT_XML)
String performGet(#QueryParam("c") String c, #QueryParam("d") String d);
}
I have tried to add the configuration key/mp-rest/followRedirects=true, but I still get the same problem. Also, with a path without redirects, everything works fine.
Using the native HttpURLConnection also works fine, but, since I am using Quarkus, I would like to use its features instead.
Related
I have an endpoint in the com.project.users package that will fetch the information of the logged in user:
#RestController
#RequestMapping(path = "/api")
public class UserController {
#Autowired
private UserRepository repository;
#GetMapping("me")
public User me() {
Optional<User> ouser = repository.findById(1);
return ouser.get();
}
}
I have another controller within com.project.beneficiary and I am trying to access a method through a POST request but instead, I receive a 404 error message:
Request URL:http://localhost:8080/api/beneficiaries
Request method:POST
Remote address:127.0.0.1:8080
Status code:
404
Version:HTTP/1.1
Referrer Policy:no-referrer-when-downgrade
{"timestamp":"2019-04-16T01:46:37.395+0000","status":404,"error":"Not Found","message":"No message available","path":"/api/beneficiaries"}
#RestController
#RequestMapping(path = "/api/beneficiaries")
public class BeneficiaryController {
#Autowired
private BeneficiaryRepository repository;
#PostMapping("/")
public Beneficiary addBeneficiary(#Valid #RequestBody Beneficiary beneficiary) {
return repository.save(beneficiary);
}
}
I've dealt with CORS, and I think it worked because I see no message about it anywhere. All these packages are on the same level as the application's starting point, but it is weird why one is seen and the other is not. Something to do with the POST request?
I found something about setting up the context within application.properties, but whatever I put there will cause the 404 error even from Insomnia software. I tried adding the /beneficiaries, /api/beneficiares, and just /api, but I don't think it is anything to do with it. No error messages in the console are visible.
It's a typo :). I ran into a similar problem some time back. Took me hours to resolve. Just remove ("/") from your #PostMapping.
I have written a book catalog in Spring.
It collects books (pdf, epub, mobi, ebook) from a directory, collects some metadata from them, stores them in a DB and then puts them in a List that is made available to my views:
#Slf4j
#Controller
public class BookCatalogController {
// == Fields ==
private final BookService bookService;
#Autowired
public BookCatalogController(BookService bookService){this.bookService = bookService; }
// == Model attributes ==
#ModelAttribute
public List<Book> bookData(){ return bookService.getBooksFromMemory(); }
public static final File bookDirectory= new File("D:\\edu_repo\\ebooks_test\\");
.
.
.
// Catalog Simple View
#GetMapping(Mappings.CATALOG_SIMPLE)
public String catalogSimple(Model model){
log.info("catalogSimple method called");
// This is adding the entire BookManager book list into the model.
model.addAttribute(AttributeNames.BOOK_DATA, bookData());
return ViewNames.CATALOG_SIMPLE;
}
// Catalog Detail View
#GetMapping(Mappings.CATALOG_DETAIL)
public String catalogDetail(Model model){
log.info("catalogDetail method called");
// This is adding the entire BookManager book list into the model.
model.addAttribute(AttributeNames.BOOK_DATA, bookData());
return ViewNames.CATALOG_DETAIL;
}
.
.
.
#GetMapping(Mappings.LOAD_BOOKS)
public void loadBooks(Model model) {
bookService.loadBooksFromDirectory(bookDirectory);
}
}
Obviously I'm not using #GetMapping(Mappings.LOAD_BOOKS) properly as you can see in the error below:
The error:
There was an unexpected error (type=Internal Server Error, status=500).
Error resolving template [load-books], template might not exist or might not be accessible by any of the configured Template Resolvers
org.thymeleaf.exceptions.TemplateInputException: Error resolving template [load-books], template might not exist or might not be accessible by any of the configured Template Resolvers
How does one invoke a method like I am doing but without Spring trying to redirect the user to another view?
I'm not expecting the page to update at all since I'm not returning a View!
When you click a link in your browser with a load-books anchor, your browser sends it to the server and waits for result, which causes your page to be reloaded. Once the request to a load-books endpoint reached to the server, Spring MVC handles this and starting to looking up an appropriate controller with its method. It founds public void loadBooks(Model model) in your case. When Spring MVC invokes the method, it expects to obtain a view name to resolve and return back to your browser.
Since you haven't provided a View or String as a return type, Spring MVC used the endpoint's path as a view name (I'm not seeing your Mappings.LOAD_BOOKS constant, but it supposed to be load-books).
If you're not going to return any view back to the browser, you can annotate the method like that:
#GetMapping(Mappings.LOAD_BOOKS)
#ResponseBody
public void loadBooks(Model model) {
which tells Spring to treat void as a response body.
But it's not preventing a page refreshing, you'll just see an empty page after clicking the link. In order to fix this you can redirect a user to another page by returning the following string (without ResponseBody annotation on the method)
return "redirect:/path-to-redirect";
When Spring MVC sees this prefix it redirects you to another controller, but user going to notice that too.
If you really don't want to see a blank page for a moment, you'll have to use some JavaScript to perform AJAX request to the server when button is clicked.
Actually, it seems that you want to preload some files in a service by a given path. If it's all you want to do, you can use Spring's runners like that:
#Component
class Preloader implements ApplicationRunner {
private final BookCatalogService bookService;
#Autowired
public Preloader(BookCatalogService service) {
this.bookService = service;
}
#Override
public void run(ApplicationArguments args) throws Exception {
bookService.loadBooksFromDirectory(BookCatalogController.bookDirectory);
}
}
Spring automatically calls all registered runners when application is ready, so your code will be executed without having a user to visit load-books endpoint.
I have a Spring Boot app that has one controller that serves mostly RESTful endpoints, but it has 1 endpoint that actually needs to return HTML.
#RestController
#RequestMapping("v1/data/accounts")
public class AccountResource {
// Half a dozen endpoints that are all pure data, RESTful APIs
#GetMapping("/confirmRegistration")
public void confirmRegistration(#RequestParam(value = "vt") String token) {
// Some logic goes here
System.out.println("This should work!");
return ResponseEntity.ok('<HTML><body>Hey you did a good job!.</body></HTML>')
}
}
When this runs, no errors/exceptions get thrown at all, and in fact I see the "This should work!" log message in my app logs. However from both a browser and a curl command, the HTTP response is empty. Any idea what I need to change in the ResponEntity builder to get the server returning a hand-crafted HTML string?
Add this to your #RequestMapping or #GetMapping
produces = MediaType.TEXT_HTML_VALUE
Spring defaults to application\json. If you need any other type, you need to specify it.
I am trying to pass parameter required in rest method via URL in Jersey+Spring.
this is my service class.
#Path("/find")
public class DownLoadService {
#Autowired
TransactionWork transactionDownload;
#POST
#Path("/bring")
public Response GetFile(String uid) {
String result = transactionDownload.BringFile(uid);
return Response.status(200).entity(result).build();
}
}
I am trying to access via URL
http://localhost:8080/ProjectName/rest/find/bring'parameter for method getFile??'
I don't know is it possible or not.
(I am using this first time may be silly question)
NOTE:I am accessing this service easily in servlet and working fine.
After waiting for long I found this way
#GET
#Path("/bring/{withUID}")
public Response GetFile(#PathParam("withUID") String uid) {
String result = transactionDownload.BringFile(uid);
return Response.status(200).entity(result).build();
}
Now I am able to access the service in this way.
http://localhost:8080/RESTfulExample/rest/my/bring/AB
^
parameter I passed to method
Ready to learn other way to do the same thing.
I have a controller with a requestmapping..
#Controller
public class TestController {
private static final String template = "Hello there, %s!";
private final AtomicLong counter = new AtomicLong();
#RequestMapping("/hello")
public #ResponseBody String hello() {
return "Hello";
}
}
How can I make it such that everytime a user goes to a RequestMapping, or whichever url, some other method is called to println to the console the URL the user is at before it actually enters the method "hello"?
I would like to use this method to ensure users have proper credentials in the future. I see there are #PreAuthorize annotation, but there doesnt seem to be a method associated with it that I can write my own logic, i.e. do a simple println to the console with the current URL the user is at.
You have a number of options.
With Spring, you can implement and register a HandlerInterceptor and implement its preHandle method to log the request URL, which you can reconstruct with the various HttpServletRequest methods.
With pure servlet-api, you can implement and register your own Filter which logs the request URL and then continues the chain, with doFilter(..).
You can also use AOP, advise all your #RequestMapping annotated methods with a #Before advice that logs the URL.