I am working on a project based on Wildfly Swarm. The problem I currently have is that RESTeasy hides my index.html (and other html files) which are placed below /webapp since RESTeasy is listening on root level.
My Main Application:
#ApplicationPath("/")
public class XYZnlineApplication extends Application {
}
One of my resources:
#Path("protected/api/admin")
public class AdminResource {
#GET
#Path("public/api/offer/reduced")
#Produces("application/json")
public List<XYZ> getXYZ() {
...
}
#GET
#Path("protected/api/offer/full")
#Produces("application/json")
public List<XYZ> getAllXYZ() {
...
}
}
The thing is. If I start my wildfly swarm app and access one of the restendpoint above, everything works fine (e.g. http://localhost:8080/app/public/api/offer/reduced)
But if I d'like to access one of my html (e.g. login.html) files which are directly below /webapp, I get a 404 although the file is bundled correctly (e.g. on trying to access http://localhost:8080/app/login.html). So in my opinion what happens is that RESTeasy hides this html file cause it listens on root (/).
Since the first part of my url is the context (which is injected by a proxy) I can't set anything else than root (/) as ApplicationPath in my XYZApplication.
Do you have any idea on how I could solve this issue?
Thanks a lot in advance for your help.
You'll need to change the ApplicationPath to be something like "/services" or "/svc" or whatever works for you. Ultimately you need to partition the URL namespace between static resources and services. You don't need to worry about the context when specifying the ApplicationPath.
Major Edit:
Your comment really explains what's going on. I'm not sure what type of security you're using exactly but ultimately you likely need to have a filter of some sort in front of your services. I would have something like:
#Provider
#Priority(Priorities.AUTHENTICATION)
#PreMatching
public class AuthFilter implements ContainerRequestFilter {
#Context
private HttpServletRequest httpServletRequest;
#Context
private HttpServletResponse httpServletResponse;
#Override
public void filter(ContainerRequestContext containerRequestContext) throws IOException {
if( containerRequestContext.getUriInfo().getPath().contains("/public/") )
return; // user is in public area - doesn't matter if they are authenticated
// guess at how to check if user is authenticated
if( httpServletRequest.getSession().get("user_is_ok") )
return;
httpServletResponse.sendRedirect("/login");
// or maybe
httpServletResponse.sendError(SC_UNAUTHORIZED);
}
}
Again, this is a bit of a guess but this is a pretty common way of handling your challenge.
Related
Building Spring Boot application, deploying(by copying to webapps folder while Tomcat is down) to local Tomcat8. Always get an error:
No thread-bound request found:
Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread?
If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet:
In this case, use RequestContextListener or RequestContextFilter to expose the current request.
As I understand, problems are while instantiating bean with WebAuthenticationDetails extending:
#Component
public class AuthDetails extends WebAuthenticationDetails{
private final AuthTarget authTarget;
public AuthDetails(HttpServletRequest request) {
super(request);
this.authTarget = AuthTarget.valueOf(request.getParameter("target"));
}
public AuthTarget getAuthTarget(){
return this.authTarget;
}
}
It cannot provide HttpServletRequest for bean constructing, but I don't know how to evade it.
Tried to add RequestContextListener, in xml or as implementation(and marking as #WebListener), no effect.
Out of ideas, how to fix it. Tried example from here: https://github.com/Baeldung/spring-security-registration , no changes - same error at the similar place.
Any help is greatly welcome.
The key was simple: I should define filter bean explicitly in security configuration extends WebSecurityConfigurerAdapter:
#Bean
AuthFilter authFilter() throws Exception{
AuthFilter authFilter = new AuthFilter();
return authFilter;
}
instead of autowiring it.
I am using Jhipster(Angular + Springboot) Application for my existing project.
I managed to create a controller(app.resource) manually apart from the ones already generated by jhiptser(using .jh file) for achieving a file download functionality.
So, when we start the server we usually initiate two servers i.e gradlew and npm start. The second runs on port 9000 which eventually supports hot reload functionality.(front-end development)
So the problem is, I am able to access those endpoints from the server running on standard 8000 port. However, from the port which is a proxy(9000), the method is returning 404.
I tried to clean build the application several times.
NOTE: The #RequestMapping value on the new controller is different then those present already.
Does this have to do something with spring security?
Thanks in advance.
Here is the previous controller:
#RestController
#RequestMapping("/api")
public class FGAppDiagramResource {
#GetMapping(value = "/fg-app-diagram-downloadFile")
public void getImage(String fileName,String folderName, HttpServletResponse
response){
// Some Code
}
}
Here is my New controller:
#RestController
#RequestMapping("/fileDownload")
public class DownloadFileController {
private final Logger log =
LoggerFactory.getLogger(DownloadFileController.class);
public DownloadFileController() {
super();
}
#Autowired
private ApplicationProperties applicationProperties;
#GetMapping(value = "/fg-app-diagram-downloadFile/{fileName}/{folderName}")
public void getImage(#PathVariable String fileName,#PathVariable String folderName, HttpServletResponse response) {
// Some Code
}
}
Your new controller does not use /api so you must add your endpoint URL /fileDownload to proxy configuration of webpack dev server in webpack/webpack.dev.js
proxy: [{
context: [
/* jhipster-needle-add-entity-to-webpack - JHipster will add entity api paths here */
'/api',
'/fileDownload',
You may want to use /api/fileDownload to avoid changing proxy configuration and also because /api is useful for many other aspects like security and also using HTML5 URL routing strategy in Angular to get rid of # in client routes (see https://github.com/jhipster/generator-jhipster/pull/9098).
/api and /management are namespaces to avoid route conflicts, so it is usually wise to use them for your new endpoints.
I know this is usually an issue that happens the other way around, so I am caught a little of guard here :D
I have built a user-management backend that provides a UI with data. When this architecture is deployed on our dev-server, everything works beautifully. However, as soon as I try to run the integration tests (which we do using a maven cargo tomcat) or if I use the war file in a local tomcat, the exception handlers aren't used at all. Spring simply displays a standard 500 response with the exception transformed into the body.
Perusing SO for similar issues has only resulted in the advice that I should use #EnableWebMVC, but that is neither applicable to what my backend is trying to accomplish, nor does it change anything.
How should I go about looking for the solution to this issue? Specifically, can I somehow observe if my controlleradvice is even scanned, and is there a reason why it might not be?
EDIT: These are the relevant files:
SpringConfiguration:
#Configuration
#ComponentScan(basePackageClasses = {UserManagementSpringConfiguration.class})
#EnableWebSecurity
public class UserManagementSpringConfiguration {
#Configuration
public static class ResourceMappingConfig implements WebMvcConfigurer {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/ui/*/usermanagement").setViewName("forward:/usermanagement-ui/index.html");
// registry.addViewController("/ui/*/*/generator/").setViewName("forward:/generator-ui/index.html");
registry.addViewController("/ui/*/usermanagement/*").setViewName("forward:/usermanagement-ui/index.html");
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// cache setting, otherwise fonts are not loaded in IE over https
CacheControl cacheControl = CacheControl.noCache().mustRevalidate();
registry.addResourceHandler("/ui/**/*").addResourceLocations("/usermanagement-ui/")
.setCacheControl(cacheControl);
}
}
}
ControllerAdvice:
#ControllerAdvice
public class CustomResponseEntityExceptionHandler {
public static final Logger LOG = EISLoggerFactory.getLogger(CustomResponseEntityExceptionHandler.class);
#PostConstruct
public void postConstruct() {
LOG.debug("CustomExceptionHandler loaded and ready for use");
}
#ExceptionHandler(PasswordMismatchException.class)
public final ResponseEntity<ErrorDetails> handlePasswordChangeMismatch(
PasswordMismatchException ex,
WebRequest request) {
ErrorDetails errorDetails = new ErrorDetails(
new Date(),
ex.getMessage(),
request.getDescription(false),
MessageKeys.mismatchedPassword);
return new ResponseEntity<>(errorDetails, HttpStatus.BAD_REQUEST);
}
}
It turns out that one of the modules that we wrote and that my project contains defines an ExceptionHandler for Throwable.class. On my machine, this ControllerAdvice is registered before my own ControllerAdvice, which causes Spring to look there first. Since Throwable fits the bill, Spring asks no further questions and just uses that handler.
The solution to my immediate problem was to add #Order(Ordered.HIGHEST_PRECEDENCE) to my ControllerAdvice. Since the exceptions I define within are quite specific, this will not cause any issues.
I have yet to find an explanation for why the order in which the two ControllerAdvice classes are registered is so consistently different between my machine and our dev server. Will update if I find anything. For now, I consider this issue to be answered.
This SO question was essential to solving this particular problem. Perhaps it helps someone in the future to link it here: Setting Precedence of Multiple #ControllerAdvice #ExceptionHandlers
Thanks to ValentinCarnu for pointing me to it!
The last couple of days, I have been struggling with an issue. I've created a rest service hosted by a Grizzly server inside an OSGi container. Everything is working perfectly at this point.
Now, I want to add a header in every response.Not so complex or illogical right? Yet, I can't find a way to do it.
I have tried to:
1) Get the response object inside the rest functions as this question suggests (pretty textbook when you are not under OSGi).
2) Add a handler using the code above (in this case the service method is never called)
server.getServerConfiguration().addHttpHandler(
new HttpHandler() {
#Override
public void service(Request arg0, Response arg1)
throws Exception {
arg1.setHeader("Access-Control-Allow-Origin", "*");
}
});
I am using jersey-server/client/core 1.18.1 and grizzly2-server 1.18.1, hence i prefer a solution that can be applied in this version, but I am willing to update jar versions if it cannot be done in 1.18.x.
You could give a try to Jersey filters.
In a nutshell, you should create class implementing ContainerResponseFilter:
public class MyFilter implements ContainerResponseFilter {
#Override
public void filter(
ContainerRequest request,
ContainerResponse response
) throws IOException {
request.getHttpHeaders().add(<header name>, <header value>);
}
}
Then, you should register this filter in your Jersey server configuration.
Please, note, that this filter would be invoked on every response. To bind it only to specific resources, you could use annotation-binding, that is described here.
All other information you could find here.
I am using Spring 4.1.5 with Boot 1.2 on a webservice that does not serve up any JSPs. I don't want to add a JSP servlet but I want it to serve up a single canary page that shows in a prettier html type format the information that would be provided at the /manage/health endpoint.
I have a file in webapp/canary/canary.html I want to serve this up from the url: www.mywebservice.com:9343/canary, exactly like that, NOT canary.html
I tried doing this:
#Configuration
public class CanaryConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/canary")
.addResourceLocations("/canary/canary.html");
}
}
That doesn't work however.
It is expecting the handler to provide a file name. So in otherwords the location should be something like: /canary/
and the handler would something like: /canary/**
With that, the URL www.mywebservice.com:9343/canary/canary.html would work like a charm.
HOWEVER, I want the URL to resolve www.mywebservice.com:9343/canary to webapp/canary/canary.html without me having to type the html.
This is really easy in a jsp servlet because you can set the suffix ect...
I looked at ResourceResolver but it didn't make sense to me how I would link that into my current configuration.
It looks like what I want:
Provides mechanisms for resolving an incoming request to an actual Resource and for obtaining the public URL path that clients should use when requesting the resource.
See: ResourceResolver Documentation
Any help would be very beneficial.
Also I am very aware that I can put html in the resources/static and several other places that are automatically configured. That always requires the .html to be typed, which is not what I want in this case so that won't work. Thanks!
You can use view controllers to do it. Here is a sample of it. Hope this helps.
public class AppConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/canary").setViewName("/canary/canary.html");
}
}
Note: if you are using tomcat, you might have to configure jsp servlet to server html files.
Related post here.
For information sake, the selected answer is the same as the following:
#Controller
public class CanaryController {
#RequestMapping(value="/canary", method=RequestMethod.GET)
public String getCanary() {
return "/canary/canary.html";
}
}
The above code will work as long as canary(or whatever file/folder) is in your webapp folder.
When I tried this I was trying to set the suffix to .html in my YAML (.yml) file and it wasn't working to I thought that it needed to return to a servlet if it is not a RestController. I was mistaken.