What is difference between * and ** in springFrameWorkMvc.webMVCConfig? - spring

I have studied about spring, especially spring-boot.
So I made a project, set config into this project. But I didn't know spring well.
So I searched these things, just copied the codes.
And now I find a strange thing that I mentioned in title. Please see below codes.
#Configuration
#EnableWebMvc
public class WebMVCAutoConfig implements WebMvcConfigurer{
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/*")
.addResourceLocations("classpath:/static/");
//I used this for get some images out of the project.
registry.addResourceHandler("/external/**")
.addResourceLocations("file:D:///resource/");
}
}
As you can see, both 'addResourceHandler' have * in argument.
But I can not understand why I have to use two * in bottom-code.
From I write this codes, When I access by http://localhost:port/pre-setting-url, It works.
But If I use only one * in bottom-code, pre-setting-url are not work. I can not get images.
I know the meaning of * as 'all', But it is not?
What is the meaning of * and **
Help me!
thank you.

/* means any resource directly under / like /foo or /bar, but not /foo/something.
** also includes subresources, so /external/** matches /external/foo/something or /external/foo/somethingelse.

Related

Why does Spring Boot ignore my CustomErrorController?

I have a custom ErrorController like this:
#Controller
public class CustomErrorController implements ErrorController {
#RequestMapping("/error42")
public String handleError(HttpServletRequest request) {
Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
System.err.println(status);
if (Objects.isNull(status)) return "error";
int statusCode = Integer.parseInt(status.toString());
String view = switch (statusCode) {
case 403 -> "errors/403";
case 404 -> "errors/404";
case 500 -> "errors/500";
default -> "error";
};
return view;
}
}
And then I've set the server.error.path property like this:
server.error.path=/error42
So far, so good. Everything works fine. All the errors go through my CustomErrorController.
But when I set the error path to server.error.path=/error - and of course I change the request mapping annotation to #RequestMapping("/error") - this won't work anymore.
Spring Boot now completely ignores my CustomErrorController. I know, I've set the path to the one Spring Boot usually defines as standard, but is there no way to override this?
Many thanks for any information clearing up this weird behavior.
I found the error, and it was solely my own fault. Since especially at the beginning of a Spring Boot career, the setting options quickly become overhelming, and one can lose sight of one or the other adjustment made, I would still like to leave this question and answer it myself.
The culprit was a self-configured view that i did weeks ago and completely lost track of:
#Configuration
#EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
/* FYI: will map URIs to views without the need of a Controller */
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login")
.setViewName("/login");
registry.addViewController("/error") // <--- Take this out !!!
.setViewName("/error");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
}
May this help others facing the same mystery, why once again nothing runs quite as desired...

RequestMapping Packages in Spring

So I'm currently developing a platform for my work using Spring MVC 3.2, with an XML configuration, and what I'm looking for is some syntactic sugar.
Basically we have numerous controllers, and since I've been the one who organized all the packages, I packed them in the same method I've gotten used to in Angular JS (i.e related concepts with related).
So now I have a package structure of:
com.company.general
com.company.general.security
com.company.general.accounts
com.company.reports
com.company.reports.someReport
com.company.reports.anotherReport
Now the big issue I'm personally having (it's more I'm looking for an easy way to do this) is trying set a standard path for a specific package.
After reading the above I realize it is not so clear, so I'll try and clarify.
Right now, each of my controllers under the reports package, have:
#Controller
#RequestMapping("/reports/reportName")
Now the only thing that changes in that chunk of code is the reportName for different controllers.
I'm unsure how to, if it is at all possible, to have it so I can specify, all controllers under package com.company.reports has a default "/reports/" path, and then when I specify the #RequestMapping in the controller it simply appends to this.
I thought this would be something doable through when I setup the since it seemed logical with it doing the assignment (or what I believe the assignment of paths) but to no avail.
Any help would be much appreciated, many thanks
You can, maybe, try with an abstract class:
#RequestMapping(value = "/reports")
public abstract class AbstractReportController {
...
}
public class MyReport extends AbstractReportController {
#RequestMapping(value = "/myReportName")
public String aMethod(Model model) {
...
}
}
public class AnotherReport extends AbstractReportController {
#RequestMapping(value = "/anotherReportName")
public String aMethod(Model model) {
...
}
}
This work.

How to use bazaarvoice dropwizard configurable assets bundle

Hi all,
at Can DropWizard serve assets from outside the jar file? I have read, that it is possible to serve static files outside of jar file with dropwizard-configurable-assets-bundle (later only DCAB).
But there are no examples available on the web. The only one, at their github page is not very helpful for me.
Firstly, there is said, that I should implement AssetsBundleConfiguration, but there is no mention where should I use it then.
Next, in service I should put this row:
bootstrap.addBundle(new ConfiguredAssetsBundle("/assets/", "/dashboard/"));
But unfortunately, it is showing me an error, that it is not applicable for that argument.
And in third part there is some yaml, but I don't know, whether it's produced by bundle, or whether I should put it somewhere.
And I noticed, that paths are relative to src/main/resources. Is there also option how to access files outside of that?
So the steps are pretty much like described in the README.md
You start with dependency
dependencies {
compile 'com.bazaarvoice.dropwizard:dropwizard-configurable-assets-bundle:0.2.0-rc1'
}
AssetBundleConfiguration interface needs to be implemented by you standard configuration file. So in my case:
public class BookRespositoryConfiguration extends Configuration
implements AssetsBundleConfiguration {
#Valid
#NotNull
#JsonProperty
private final AssetsConfiguration assets = new AssetsConfiguration();
#Override
public AssetsConfiguration getAssetsConfiguration() {
return assets;
}
}
This configuration is referred in you Application class
public class BooksRepositoryApplication
extends Application<BookRespositoryConfiguration> {
#Override
public void initialize(Bootstrap bootstrap) {
bootstrap.addBundle(new ConfiguredAssetsBundle("/assets/", "/books/"));
}
#Override
public void run(BookRespositoryConfiguration configuration,
Environment environment) throws Exception {
//...
}
}
And finally configuration. The configuration path is relative to the document-root, so in my case the assets are located outside the application folder.
assets:
overrides:
/books: ../book-repository
Now after running the app you can easily navigate to http://localhost:8080/books/some-static-files.html
Look at upto-date dropwizard-configurable-assets-bundle maintained at official dropwizard-bundles.
https://github.com/dropwizard-bundles/dropwizard-configurable-assets-bundle.

ZK & Spring - Safe to use Executions.getCurrent() in Spring Bean?

I want to create a utility Bean for common URL parsing in my ZK Composers. However, I want to make sure it is safe to use things like Executions.getCurrent() in a Spring managed Bean. I'm pretty sure it is as Executions.getCurrent() is static to begin with.
Here's what I'm thinking of doing..
#Component
public MyUrlBean {
// TODO I will, of course, program to an interface here =)
private static final String MY_OBJECT_URL_PARAMETER = "my_obj";
public MyObject getMyObjectFromURL() {
Execution ex = Executions.getCurrent();
String value = ex.getParameter(MY_OBJECT_URL_PARAMETER)
// ... db fetch and the like
}
}
..used like so..
#VariableResolver(DelegatingVariableResolver.class)
public MyComposer extends SelectorComposer<Window> {
#WireVariable
public MyUrlBean myUrlBean;
#Override
public void doAfterCompose(Window component) {
MyObject myObject = myUrlBean.getMyObjectFromURL();
// ...
}
}
So, doing things this way, should everything work fine or should I anticipate problems with user sessions clashing or the like?
Spring beans are NOT static singletons, correct? Instead they are instance classes that are autowired to save computation time of actually newing up objects, correct? If that is the case then there definitely won't be clashes between users like this.
Anyway, as I mentioned, Executions.getCurrent() is static. Hmm, how does that work with multiple users accessing a webapp?
Yes, it's safe.
I don't have much official sources to link here, but for what it's worth, my previous team has been using this in almost every page (to get a user context) of an app serving over 3000 users in production with no recorded problem in two years.

Using Aspect to annotate methods with #InsightOperation for Spring Insight

I wanted to instrument a large number of classes to use with Spring Insight and instead of adding the #InsightOperation manually to the methods, I wrote an aspect to annotate the methods using point cuts.
However, this is not working. While the manual annotation affects the Spring Insight trace logging, the AspectJ method does not work.
Is there anything I am doing wrong here? (I decompiled the classes after aspectizing and do find the annotation in the class methods)
This is the aspect code snippet:
declare #method :public * com.example.IExample.execute(..) : #InsightOperation;
Spring documentation says this:
Use of the #Insight* annotations are
optional. They make it easy for end
users to define custom operation
frames and end points without needing
to create a plug-in. Because end user
code modification is required to use
the annotations, they are an option
for users who cannot or do not wish to
write aspects.
http://static.springsource.com/projects/tc-server/2.5/devedition/htmlsingle/devedition.html
So looks like the only way is to write a custom plugin
http://static.springsource.com/projects/tc-server/2.5/devedition/htmlsingle/devedition.html#tutorial-plugin
It is possible that the Insight LTW does not pick up your introduced annotations. I'll have to dig deeper on that.
In the meantime, you can try a more low-level annotation:
com.springsource.insight.collection.method.MethodOperationsCollected
If you look at the spring-core plugin, you will see that it does something similar:
public aspect RepositoryMethodOperationCollectionAspect {
declare #type: #Repository * : #MethodOperationsCollected;
}
An easy work around is to call another method from within your aspect method to continue executing the join point. I only tried calling a static method in a static class. See below my code for adding the #InsightOperation to all my JSON serialization.
My aspect:
#Aspect
public class JSONSerializerAspect {
#Around("call(* *.JSONSerializer.serialize(..)) && args(target)")
public Object serialize(ProceedingJoinPoint joinPoint, Object target) throws Throwable {
return JSONSerializationWrapper.serialize(joinPoint, target);
}
}
The static class it is calling:
public class JSONSerializationWrapper {
#InsightOperation(label = "JSON_SERIALIZATION")
public static Object serialize(ProceedingJoinPoint joinPoint, Object target) throws Throwable {
return joinPoint.proceed(new Object[]{target});
}
}
I'm using this myself and tested that it works.

Resources