How can i ignore some path of vaadin ? /HEARTBEAT /UIDL /VAADIN - spring

I am using a vaadin application with the dashboardemo example
My class does not use a VaadinSevlet but, a VaadinCDIServlet
My webServlet 3.0 I have it so
#WebServlet (asyncSupported = false, urlPatterns = {"/*"},
I will not serve any static content otherwise I would write another
urlpattern as well /VAADIN/*
The problem is that when I visit the path as
/HEARTBEAT/?v-uid=0
/HEARTBEAT
/UIDL/?v-uiId=2
/VAADIN/
/VAADIN/themes/valo/fonts
I get different errors, as I can show some errorView or redirect users to a main view,
The demo dashboard actually redirects some incorrect url or fragments !#blalbla, redirect to
https://domain/myapp/#!dashboard
but with these path does not it, I have reviewed many applications and it happens just the same, whether we are demos or not.please some help?
Update
The solution I recommend for this in case of handling errors 4xx 5xx etc, is to use spring framework, example:. redirect to an external url
#RestController
public class MyController implements ErrorController {
private static final String URL = "http://www.blablaba.com";
#RequestMapping(method = RequestMethod.GET)
#ExceptionHandler(RuntimeException.class)
public void handle(final RuntimeException rex, final HttpServletResponse
hsp) throws IOException {
hsp.sendRedirect(getErrorPath());
}
#Override
public String getErrorPath() {
return URL;
}
}

Im not sure the approach they took in the demo but this is what comes to my mind. In your ErrorView you can call UI.getCurrent().getNavigator() and then redirect to the desired URL by getting the URL from the Page.getCurrent() object then running Navigator.navigateTo().

Related

How to access url of this endpoint #GetMapping("/catalog/**") inside its method?

I have following endpoint:
#GetMapping("/catalog/**")
public String getCatalog(final Model model){
// code
}
This endpoint handles such urls: catalog/clothes, catalog/clothes/men,catalog/clothes/women and so on.
When I enter such url:
http://localhost:8080/catalog/clothes/women
this endpoint gets fired.
I need to get this url inside the method. How can I do this?
Thanks in advance.
The 2nd snippet looks Ok and the problem it is not getting called seems to be in other code, or share the class/configuration code.
#Controller
public class CatalogController {
private static final Logger logger = LoggerFactory.getLogger(CatalogController.class);
#GetMapping("/catalog/**")
public String getCatalog(final Model model, HttpServletRequest request, HttpServletResponse response){
logger.debug(request.getRequestURL().toString());
logger.debug(request.getQueryString());
logger.debug("Inside catalog");
return null;
}
}
If URL your enter is like - http://localhost:8080/catalog/a/b/c/d?key=value
The above code will log:
http://localhost:8080/catalog/a/b/c/d (URL)
key=value (query string)
http://localhost:8080/catalog/a/b/c/d

Spring Boot Tries to Access A Post Request URL but shows GET not supported

I just started to learn Spring Boot today, and I wanted to create a GET/POST request for my Spring Boot Project. When I tried to access the URL that has the post request it shows 405 error saying that "Request method 'GET' not supported".
I think it is something wrong about my code for the POST request, but I don't know where I did wrong. I tried to search for the a tutorial that teaches how to write a proper GET/POST request, so I couldn't find anything good.
If you guys have any good website that teaches basic HTTP requests in Spring Boot, that will be great. I tried to find answers at StackOverflow, but I didn't find anything answers.
The Spring Boot project I have been using is the one from the official Spring.io website: https://spring.io/guides/gs/rest-service/
I wanted to call the POST request for my project so I have a better understanding of the HTTP.
Here is the source code for the controller:
package hello;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.web.bind.annotation.*;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
#RestController
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
// GET Request
#RequestMapping(value="/greeting", method = GET)
public Greeting greeting(#RequestParam(value="name", defaultValue="World") String name) {
return new Greeting(counter.incrementAndGet(), name);
}
#RequestMapping(value = "/testpost", method = RequestMethod.POST)
public String testpost() {
return "ok";
}
}
Here is the source code for the Application:
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
And here is the source code for the Greeting Object
package hello;
public class Greeting {
private final long id;
private final String content;
public Greeting(long id, String content) {
this.id = id;
this.content = content;
}
public long getId() {
return id;
}
public String getContent() {
return content;
}
}
I can get the GET request working by using the "/greeting" URL.
I tried to access the "/testpost" url but it shows 405 error that the GET method is not supported.
There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'GET' not supported
If you try to open the http://localhost:8080/testpost by directly opening in browser, it won't work because opening in browser makes a GET request.
I am not sure how you are trying to do a post request, I tried to do the same post request from postman and able to get the response. Below is the screenshot.
It looks like you are trying to make post request directly from web browser which will not work.
When you hit a URL directly from web browser address bar, it is considered as GET request. Since in your case, there is no GET API as /testpost , it is giving error.
Try to use rest client such as Postman or curl command to make post request.
I tried your post end-point with postman and it is working properly. PFA snapshot for your reference.
Hope this helps.
From where you are trying POST request. If from browser windows you calling POST call, then it will not work, browser will send only GET request. Have you tried from postman or from UI side. It will work.

Cannot properly test ErrorController Spring Boot

due to this tutorial - https://www.baeldung.com/spring-boot-custom-error-page I wanted to customize my error page ie. when someone go to www.myweb.com/blablablalb3 I want to return page with text "wrong url request".
All works fine:
#Controller
public class ApiServerErrorController implements ErrorController {
#Override
public String getErrorPath() {
return "error";
}
#RequestMapping("/error")
public String handleError() {
return "forward:/error-page.html";
}
}
But I dont know how to test it:
#Test
public void makeRandomRequest__shouldReturnErrorPage() throws Exception {
this.mockMvc.perform(get(RANDOM_URL))
.andDo(print());
}
print() returns:
MockHttpServletResponse:
Status = 404
Error message = null
Headers = {X-Application-Context=[application:integration:-1]}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
So I cant created something like this:
.andExpect(forwardedUrl("error-page"));
because it fails, but on manual tests error-page is returned.
Testing of a custom ErrorController with MockMvc is unfortunately not supported.
For a detailed explanation, see the official recommendation from the Spring Boot team (source).
To be sure that any error handling is working fully, it's necessary to
involve the servlet container in that testing as it's responsible for
error page registration etc. Even if MockMvc itself or a Boot
enhancement to MockMvc allowed forwarding to an error page, you'd be
testing the testing infrastructure not the real-world scenario that
you're actually interested in.
Our recommendation for tests that want to be sure that error handling
is working correctly, is to use an embedded container and test with
WebTestClient, RestAssured, or TestRestTemplate.
My suggestion is to use #ControllerAdvice
In this way you can work around the problem and you can continue to use MockMvc with the big advantage that you are not required to have a running server.
Of course to test explicitly the error page management you need a running server. My suggestion is mainly for those who implemented ErrorController but still want to use MockMvc for unit testing.
#ControllerAdvice
public class MyControllerAdvice {
#ExceptionHandler(FileSizeLimitExceededException.class)
public ResponseEntity<Throwable> handleFileException(HttpServletRequest request, FileSizeLimitExceededException ex) {
return new ResponseEntity<>(ex, HttpStatus.PAYLOAD_TOO_LARGE);
}
#ExceptionHandler(Throwable.class)
public ResponseEntity<Throwable> handleUnexpected(HttpServletRequest request, Throwable throwable) {
return new ResponseEntity<>(throwable, HttpStatus.INTERNAL_SERVER_ERROR);
}
}

Error 404 on PUT request while having a GET

Got a small problem on my rest server. It's based on spring web framework.
Here's the code that poses me problems :
#RestController
#RequestMapping("users")
public class usersWS {
//some other functions
//works
#RequestMapping(
value="/{iduser}/functions/",
method=RequestMethod.GET,
produces={"application/json"})
public ResponseEntity<String> getUserFunctions(#PathVariable("iduser") String iduser){
//do stuff
return stuff;
}
//Don't works
#RequestMapping(
value="/{iduser}/functions/"
method=RequestMethod.PUT,
consumes={"application/json"})
public ResponseEntity<String> addUserFunctions(#RequestBody String json, #PathVariable("iduser") String iduser){
//do stuff
return stuff;
}
}
Server is launched by :
#SpringBootApplication()
#ImportResource("classpath*:**/jdbc-context.xml")
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
To call this server, I use the HTML handler found here : Spring HTTP Client
When I call the get verb, everything is working fine. I get the iduser, get the data I want, no problem.
When I call the put verb... I have an error 404. I checked, the url (http://localhost:8080/users/xxx/functions/) are exactly the same, I do send the body.
I would understand to get a 405 error, but I really don't understand how I can have a 404. If the mapping was wrong, the server should at least see that there is a function on the get verb and throw me a 405.
I have other functions using the PUT/POST that are working but they don't have a #PathVariable. Is it possible to mix #RequestBody and #PathVariable ?
Any help is gladly welcome.

Spring 3.0 RESTful Controller Fails on Redirect

I am setting up a simple RESTful controller for a Todo resource with an XML representation. It all works great - until I try to redirect. For example, when I POST a new Todo and attempt to redirect to its new URL (for example /todos/5, I get the following error:
Error 500 Unable to locate object to be marshalled in model: {}
I do know the POST worked because I can manually go to the new URL (/todos/5) and see the newly created resource. Its only when trying to redirect that I get the failure. I know in my example I could just return the newly created Todo object, but I have other cases where a redirect makes sense. The error looks like a marshaling problem, but like I said, it only rears itself when I add redirects to my RESTful methods, and does not occur if manually hitting the URL I am redirecting to.
A snippet of the code:
#Controller
#RequestMapping("/todos")
public class TodoController {
#RequestMapping(value="/{id}", method=GET)
public Todo getTodo(#PathVariable long id) {
return todoRepository.findById(id);
}
#RequestMapping(method=POST)
public String newTodo(#RequestBody Todo todo) {
todoRepository.save(todo); // generates and sets the ID on the todo object
return "redirect:/todos/" + todo.getId();
}
... more methods ...
public void setTodoRepository(TodoRepository todoRepository) {
this.todoRepository = todoRepository;
}
private TodoRepository todoRepository;
}
Can you spot what I am missing? I am suspecting it may have something to do with returning a redirect string - perhaps instead of it triggering a redirect it is actually being passed to the XML marshaling view used by my view resolver (not shown - but typical of all the online examples), and JAXB (the configured OXM tool) doesn't know what to do with it. Just a guess...
Thanks in advance.
This happend because redirect: prefix is handled by InternalResourceViewResolver (actually, by UrlBasedViewResolver). So, if you don't have InternalResourceViewResolver or your request doesn't get into it during view resolution process, redirect is not handled.
To solve it, you can either return a RedirectView from your controller method, or add a custom view resolver for handling redirects:
public class RedirectViewResolver implements ViewResolver, Ordered {
private int order = Integer.MIN_VALUE;
public View resolveViewName(String viewName, Locale arg1) throws Exception {
if (viewName.startsWith(UrlBasedViewResolver.REDIRECT_URL_PREFIX)) {
String redirectUrl = viewName.substring(UrlBasedViewResolver.REDIRECT_URL_PREFIX.length());
return new RedirectView(redirectUrl, true);
}
return null;
}
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
}

Resources