java spring restful-url with semi-colon - java

I am currently working on a project that requires the use of a semi-colon in our restful-url scheme.
As you can imagine, we're having issues pulling this off - the underlying Java HTTPServletRequest isn't playing nicely.
Is there a way to work around this issue?
example restulf-URL:
http://service/BOB;MIKE/
Looks like Spring is only working on /service/bob - the ;MIKE gets truncated.
We've tried %3B (or %3F something like that) and it doesn't work.
Thanks in advance!
ct

While #Amos M. Carpenter answer is correct, here is the required configuration to turn this behavior off :
#Configuration
#EnableWebMvc
public class WebMvcConfiguration extends WebMvcConfigurerAdapter
{
#Override
public void configurePathMatch(PathMatchConfigurer configurer)
{
configurer.getUrlPathHelper().setRemoveSemicolonContent(false);
}
}

this is the list of all the delimiters you can legally use in a URI:
! $ & ( ) * , ; = + ' : # / ?
try each and see which works for you.
apparently Spring robs you of the ;. I'm not sure if that's a Servlet thing, but in any case, it sucks. A web framework should allow developers to construct ANY legal URIs.

Seems this is intentional on Spring's part, but at least it's configurable.
You need to tell your handler mapping to setRemoveSemicolonContent(false) (default is true). See the Javadoc for more details.
The reason why this was done is because they apparently wanted to remove the ;jsessionid=... suffix from URIs.

Related

Is it possible to create necessary / required interfaces?

i have a little kont in my brain about structuring our code. We have a REST Backend based on SpringBoot. To handle requests regarding to security checks we use HandlerInterceptors. In some specific cases we need a specific interceptor and not our default one. The default one is registered in a 3rd party lib that no one can forget it. But i want all coders to think about this specific interceptor.
Actually, i just said it to them to achieve this.
Here's my question: Is there an option to create required (or necessary) interfaces which must be implemented? This would be a way to provide our security code by lib and to have the security that every coder implemented our specific interface (also if he just does nothing with it).
pseudo code:
public interface thinkForIt(){
Object SecBean specificSecBean;
public void methodToThinkOn();
}
public SecImpl implements thinkForIt(){
#Override
public void methodToThinkOn(){
return null; // i thought about it but i do not need to do anyting!
}
If the interface thinkForIt would have any annotations like #required, users could get warning or error if they did not implement it...
Looking for a solution and thanks for your comments in advance!
Your overall design is questionable; you are reinventing security code, which is always a red flag. Use Spring Security instead.
However, there's a simple way to ensure that "some bean of type Foo" has been registered with the context:
#Component
#RequiredArgsConstructor
public class ContextConfigurationVerifier {
final Foo required;
}

Using an parameter variable from an advice Aspectj

I am making an address book application and I am brand new to aspectj and I am trying to use a variable int inside the aspect but eclipse is saying it "Cannot be resolved to a variable".
What do I need to do to use the variable? Thanks for any help you can give me.
Aspect
before(): execution(* *.deleteAddress(int <--PARAMETER I WANT TO USE))
{
fileServices.addXMLToFile(fileServices.makeXML(FileServices.map.get(WHERE I WANT TO PUT THE PARAMETER)), FileServices.ProductionFileName);
}
Here is the code if that will help
public void deleteAddress(int keyNumber) throws Exception
{
Address oldAddress = map.get(keyNumber);
map.remove(keyNumber);
addXMLToFile(makeXML(oldAddress), BackupFileName);
}
You need to use args() in order to bind positional parameters to advice method arguments.
The Spring manual explains that for Spring AOP (which is technically different, but shares a subset of syntax with AspectJ), but they syntax which is rather unusual for beginners, referring to pointcuts defined in in a different class.
Better read the AspectJ manual which also explains it. I just noticed you use native AspectJ syntax anyway, which means Spring AOP is not your topic. Let me just leave the reference in my answer for Spring AOP users.
In your case the answer - now in native AspectJ syntax again - would be (untested, just texting freestyle):
before(int keyNumber) : execution(* *.deleteAddress(int)) && args(keyNumber) {
fileServices.addXMLToFile(
fileServices.makeXML(
FileServices.map.get(keyNumber)
),
FileServices.ProductionFileName
);
}

When and how cglib-proxied component instance is created

I'd like to learn if there are some rules / conditions that a Spring component is wrapped (proxied) by CGLIB. For example, take this case:
#Component
public class TestComponent {
}
#Service
//#Transactional(rollbackFor = Throwable.class)
public class ProcessComponent {
#Autowired
private TestComponent testComponent;
public void doSomething(int key) {
// try to debug "testComponent" instance here ...
}
}
If we let it like this and debug the testComponent field inside the method, then we'll see that it's not wrapped by CGLIB.
Now if we uncomment the #Transactional annotation and debug, we'll find that the instance is wrapped: it's of type ProcessComponent$$EnhancerByCGLIB$$14456 or something like that. It's clearly because Spring needs to create a proxy class to handle the transaction support.
But I'm wondering, is there any way that we can detect how and when does this wrapping happen ? For example, some specific locations in Spring's source code to debug into to find more information; or some documentations on the rules of how they decide to create a proxy.
For your information, I need to know about this because I'm facing a situation where some component (not #Transactional, above example is just for demonstrating purpose) in my application suddenly becomes proxied (I found a revision a bit in the past where it is not). The most important issue is that this'll affect such components that also contain public final methods and another issue (also of importance) is that there must have been some unexpected changes in the design / structure of classes. For these kind of issues, of course we must try to find out what happened / who did the change that led to this etc...
One note is that we have just upgraded our application from Spring Boot 2.1.0RELEASE to 2.1.10RELEASE. And checking the code revision by revision up till now is not feasible, because there have been quite a lot of commits.
Any kind of help would be appreciated, thanks in advance.
You could debug into org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(Class, String, TargetSource).
If any advisor is found, the bean will be proxied.
If you use a #Lookup method injection it will also proxy the component class.

How to set a Spring Boot property with an underscore in its name via Environment Variables?

I want to set hibernate.format_sql in a Spring Boot app. I want to set it using environment variables.
Spring Boot rather handily converts all environment variables from, for example, FOO_BAR_BAZ to properties called foo.bar.baz inside the Spring context.
How can I set a property that has an underscore in the target name, in Spring Boot, using environment variables? Presumably HIBERNATE_FORMAT_SQL will be translated to hibernate.format.sql?
This is an old question but I'll answer it in case somebody else (like me) ends up here looking for this information.
HIBERNATE_FORMAT_SQL should do the trick
Actually it is not the OS environment variable that is "translated" but rather the Spring property name that is.
The name is translated in several ways and looked up against available environment variables. E.g. "hibernate.format.sql" is looked up as:
hibernate.format.sql (as is)
hibernate_format_sql (dots replaced with underscores)
hibernate_format_sql (dashes replaced with underscores, the same in your case)
hibernate_format_sql (dashes & dots replaced with underscores, the same in your case)
Then the same with UPPERCASE:
HIBERNATE.FORMAT.SQL (as is)
HIBERNATE_FORMAT_SQL (dots replaced with underscores)
HIBERNATE_FORMAT_SQL (dashes replaced with underscores, the same again)
HIBERNATE_FORMAT_SQL (dashes & dots replaced with underscores, the same again)
Although you cannot set an environment variable with a dot in the name with the set or export commands it is however possible with the env command. I defer judgement whether this is a good idea or not:
env "my.dotted.name=\"a value\"" the-command-you-want-to-run
Have a look at SystemEnvironmentPropertySource.java
for details. I link to a specific version but you should make sure to look at the version you are using.
To troubleshoot these kinds of problems in a production environment you could try turning on debug logging for the property resolving code:
logging:
level:
org.springframework.core.env: DEBUG
... or by setting the appropriate environment variable :)
Edit:
I highly recommend being familiar with the relevant Spring Boot documentation topic:
https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config
For the more tricky examples in the comments here, e.g. spring.jpa.properties.hibernate.criteria.literal_handling_mode, there might be different solutions available depending on how you launch you application.
You could set the variable as JSON, embedded in an environment variable.
env SPRING_APPLICATION_JSON='{"spring":{"jpa":{"properties":{"hibernate":{"criteria":{"literal_handling_mode":"BIND"}}}}}}' ./gradlew bootRun
Simply setting the variable as is might work also:
env spring.jpa.properties.hibernate.criteria.literal_handling_mode=BIND ./gradlew bootRun
Both of the above worked in my setup in so far as I was able to get the value in the running Spring Boot application this way:
#Value("${spring.jpa.properties.hibernate.criteria.literal_handling_mode}")
private String testSettingThroughEnvVariable;
Hope this helps! YMMV
I had a same issue, environment variable spring_jpa_properties_hibernate_default_schema
translated by Spring as spring.jpa.properties.hibernate.default.schema but Hibernate needs hibernate.default_schema.
For sertain reason (devops problems) i could not change it just to spring.jpa.properties.hibernate.default_schema - it`s work on local machine.
I solved it like this
#Component
public class HibernateConfig implements HibernatePropertiesCustomizer {
private final static String HIBERNATE_CUSTOM_DEFAULT_SCHEMA_PARAM = "hibernate.default.schema";
#Override
public void customize(Map<String, Object> hibernateProperties) {
if (hibernateProperties.containsKey(HIBERNATE_CUSTOM_DEFAULT_SCHEMA_PARAM)) {
hibernateProperties.put(AvailableSettings.DEFAULT_SCHEMA, hibernateProperties.get(HIBERNATE_CUSTOM_DEFAULT_SCHEMA_PARAM));
}
}
}
Turns out SPRING_JPA_SHOW_SQL=true works just fine. I don't know whether this means that names for that particular property are overloaded, or whether Spring is doing something more clever. It solved my issue and gave the desired behaviour for the example I asked about though.

Controller arguments annotated with Spring 3 MVC PathParameter is stripping data after the last '.'

When experimenting with Spring MVC, I noticed the values passed to controller arguments annotated with #PathVariable will have all the characters from the last '.' on stripped, unless the last character is a '/'.
For example, given the following code:
#RequestMapping("/host/${address})"
public String getHost(#PathVariable String address, Model model) {
model.addAttribute("host", hostRepository.getHost(address));
return "host";
}
If the URL is "/host/127.0.0.1", the value of address will be "127.0.0". If the URL is "/host/127.0.0.1/", the value of address will be "127.0.0.1".
Is there away to prevent this stripping?
There are plenty of such reports in their issue tracker already (for example, SPR-5778). But they don't fix it, so it seems to be a legitimate behaviour.
The official workaround is to set useDefaultSuffixPattern = false on DefaultAnnotationHandlerMapping, but it has several drawbacks:
It is applied to all controllers
It completely disables extension handling (for example, for ContentNegotiationViewResolver)
It breaks "trailing slash doesn't matter" rule
More sophisticated workarounds use a customized PathMatcher, as described here.
It's apparently been handled as a file extension and stripped. Not sure if it's a bug. I would fill an issue at their issuetracker.
Update: please check this topic, it's actually not a bug and it can be solved programmatically: Trying to create REST-ful URLs with mulitple dots in the “filename” part - Spring 3.0 MVC

Categories