Spring Restful service URL encoding issue with "." - java

#RequestMapping(value = "/newLoadtest/{loadtest}", method = RequestMethod.POST)
public #ResponseBody void addNewLoadTest(#PathVariable("loadtest") String loadtest) {
System.out.println(loadtest);
}
This is the code that I have written and if lets say the loadtest string is "test.version" . The period doesn't work for some reason. It prints out "test" only
I think the issue here might be encoding the url but i am not sure how to go about it. Please help

Its spring's smart way to avoid any suffix in URI. You have two ways to disable it.
add ":.+" after your path variable definition.
#RequestMapping(value = "/newLoadtest/{loadtest:.+}", method = RequestMethod.POST)
Another way is to
Use your own "DefaultAnnotationHandlerMapping" and disable "useDefaultSuffixPattern" to false.

Check below quote from Spring reference:
By default Spring MVC automatically performs "." suffix pattern matching so that a controller mapped to /person is also implicitly mapped to /person.. This allows indicating content types via file extensions, e.g. /person.pdf, /person.xml, etc. A common pitfall however is when the last path segment of the mapping is a URI variable, e.g. /person/{id}. While a request for /person/1.json would correctly result in path variable id=1 and extension ".json", when the id naturally contains a dot, e.g. /person/joe#email.com the result does not match expectations. Clearly here ".com" is not a file extension.
if you do not want to use extension content negotiation you can disable it by this line in below code configurer.setUseSuffixPatternMatch(false); or I think the below solution is better to just use registered Suffix, it is up to your needs
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void configurePathMatch(PathMatchConfigurer configurer) {
//configurer.setUseSuffixPatternMatch(false);//this will disable all suffices from negotiation
configurer.setUseRegisteredSuffixPatternMatch(true);
}
}

Related

Spring 4: Multiple base path in one controller

I have a question about Spring 4.
My controller is accessible from a URL, but I want to have a second URL where only the beginning is different to access the same endpoints of this controller.
Here is my controller:
#RestController("MyController")
#RequestMapping(value={"/abc/def/ghi","/ijk/def/ghi"})
public class MyController {
// code continuation
But I get this error message.
Multiple class level mappings defined on class com.MyController
Did I miss something?
Thanks.
Edit : as M. Dudek mentioned, it was indeed necessary to upgrade Hateoas.
#RequestMapping has a String[] value parameter (not values), so you should be able to specify multiple values like this:
#RequestMapping(value={"/abc/def/ghi"},{"/ijk/def/ghi"})
maybe this?
#RestController("MyController")
#RequestMapping(value={"/abc/def/ghi","/ijk/def/ghi"})
public class MyController {
// code continuation

Is there a way to clear a "consumes = MediaType" in Spring Boot RestController?

Let's say I have a controller that has a variety of endpoints (GET/POST/PUT/DELETE) and generally they both produce and consume JSON, so I do:
#RestController
#RequestMapping(value=["/some/base/path"], produces = [MediaType.APPLICATION_JSON_UTF8_VALUE], consumes = [MediaType.APPLICATION_JSON_UTF8_VALUE])
public class SomeController {
...
}
But it turns out that my #GetMapping does not consume JSON (and I don't want to force callers to set Content-Type: application/json for GET requests. Is there a way, on the #GetMapping, to clear/empty the consumes = value that was set at the class level? Or is there another way to avoid repeating the consumes attribute on all methods in the class?
I've already tried setting the #GetMapping(value=["/some/path"], consumes = []) without any luck. For context, I'm converting from Jersey annotations to Spring REST controller style annotations and I'm finding this to be an annoying difference in behavior (setting a class-level #Consumes annotation doesn't get enforced against #GETs). And just looking for an elegant way to mirror existing behavior without cloning the consumes attribute all over the place.
I got your problem now .Try use the below solution and refer to this link that might help
https://github.com/spring-projects/spring-framework/pull/1257/commits/00e6ca412dffeb8a7a596f9312db19eb6cc49525
#GetMapping(value = "/get", consumes = MediaType.ALL_VALUE)
For your case , you need to delete the consumes part.I mean just use the Produces only.For example :
#GET
#Produces("application/json")
#Path("/{oid}")
public Book getBook(#PathParam("oid") String oid) {
return bookService.getBook(oid);
}
or check this url :
https://dzone.com/articles/spring-boot-building-restful-web-services-with-jersey

dropwizard: read configuration from a non-file source

What's the right way to read configuration in dropwizard from something like a database, or a REST call? I have a use case where I cannot have a yml file with some values, and should retrieve settings/config at startup time from a preconfigured URL with REST calls.
Is it right to just invoke these REST calls in the get methods of the ApplicationConfiguration class?
Similar to my answer here, you implement the ConfigurationSourceProvider interface the way you wish to implement and configure your dropwizard application to use it on your Application class by:
#Override
public void initialize(Bootstrap<MyConfiguration> bootstrap){
bootstrap.setConfigurationSourceProvider(new MyDatabaseConfigurationSourceProvider());
}
By default, the InputStream you return is read as YAML and mapped to the Configuration object. The default implementation
You can override this via
bootstrap.setConfigurationFactoryFactory(new MyDatabaseConfigurationFactoryFactory<>());
Then you have your FactoryFactory :) that returns a Factory which reads the InputStream and returns your Configuration.
public T build(ConfigurationSourceProvider provider, String path {
Decode.onWhateverFormatYouWish(provider.open(path));
}
elaborating a bit further on Nathan's reply, you might want to consider using the UrlConfigurationSourceProvider , which is also provided with dropwizard, and allows to retrieve the configuration from an URL.
Something like:
#Override
public void initialize(Bootstrap<MyRestApplicationConfiguration> bootstrap) {
bootstrap.setConfigurationSourceProvider(new UrlConfigurationSourceProvider());
}

Spring URLs: There's a difference between "/test" and "/test/" in the controller mapping

Simple example spring controller (if you're not familiar with spring, just look at the output html):
#Controller
#RequestMapping("test")
public class TestController {
#RequestMapping("")
#ResponseBody
public String pathTest(){
return "<html><head></head><body><a href='subpath'>subpath</a></body></html>";
}
}
If I go to http://mydomain/test, the link from the above html goes to: http://mydomain/subpath
If I go to http://mydomain/test/, the link from the above html goes to: http://mydomain/test/subpath
I guess this is simple, but I don't know how to ensure that the trailing '/' doesn't affect the application function. My primary concern is when users manually change the URL, they may or may not leave the trailing '/'.
What can I do to ensure my application works the same whether or not the final '/' exists?
Do not return <a href='subpath'>subpath</a> return
<a href='/test/subpath'>subpath</a> instead.

Multiple domains with spring mvc

Let's say I have an application that has to shorten URLs, but also do other things. (like google.com and goo.gl, or facebook.com and fb.me).
It will be easy to simply deploy two applications, but (for now) it's simpler to be just one. Using spring and spring-mvc. I have the following mappings:
#RequestMapping(value="/{shortUrlKey}", headers="Host=foo.br")
...
#RequestMapping(value="/{username}")
Alas, the headers annotation acts not as giving more specific information, but as restricting instead. So if I have these two, only the latter is invoked, even if I open it as http://foo.br/asdf. If leave only the former, it works for those coming from foo.br, and doesn't open anything if the host is different.
So, the questions:
how can I make two handlers for the same paths, but different URLs / Hosts
is it possible to resolve the host dynamically, with a property placeholder configurer (rather than hard-code it in the annotation)
Perhaps both would work if there is some pluggable mechanism for method resolution. Is there such?
My immediate suggestion would be to write a servlet filter (or a Spring HandlerInterceptor), which would take the host name from the request, prepend it to the original requested path, then forward on the request.
For example, given the requested URL http://goo.gl/my/path, the filter would forward to /goo.gl/my/path. The Spring MVC mappings would then have something to get their teeth into. The ant-style wildcard syntax (e.g. "**/my/path") or path-variable style (e.g. "{requestHost}/my/path" might be helpful there.
Alternatively, the filter could set a custom header or request attribute containing the requested host, but that's probably less flexible.
I'm not sure what you mean by the second part of your question, though.
Here's a working snippet:
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
if (request.getRequestURL().toString().contains(shortenerDomain)
&& !request.getRequestURI().startsWith(SHORT_URI_PREFIX)) {
request.getRequestDispatcher(SHORT_URI_PREFIX + request.getRequestURI())
.forward(request, response);
return false;
} else {
return true;
}
}
Based on your description, it sounds like you could have two controller methods with each domain header mapping:
#RequestMapping(value="/{shortUrlKey}", headers="Host=foo.br")
public void fooBr() { ... }
#RequestMapping(value="/{shortUrlKey}", headers="Host=bar.bz")
public void barBz() { ... }

Categories