Spring Boot - Print interceptors with ordering - java

I have a rest service developed using spring boot. I have imported a number of external libraries which have some interceptors. Is there a way to print the list of interceptors along with order in which they will be triggered?

You can inject all beans of given type (in that case you can use the org.springframework.web.servlet.HandlerInterceptor interface) in any of your components. So if you want to print(or do something else with) all interceptors you can do something like this:
#Component
public class SomeBean {
#Autowired
private List<org.springframework.web.servlet.HandlerInterceptor> interceptors;
#PostConstruct //not required, but you can use it to print at the app startup
public void printInterceptors() {
//TODO use this.interceptors
}
}
Also, I guess that Spring prints the interceptors on startup, maybe in the debug log.

Related

Spring app with React UI - how to serve when #EnableWebMvc is applied?

So I have a React app I want to serve from my Spring app (ala this blog). As part of my gradle build task, I run the npm build command and copy the resulting files to /build/resources/main/static. This works fine and I can access my app at mysite.com/index.html, but I want to control who has access more granularly. As such, I applied #EnableWebMvc to my app, but from there, I can't seem to get my API controller to actually serve the view from the build directory. It seems no matter where I put it, it doesn't like serving directly from /build. Any way to make this work?
The handler looks like:
#Controller
class MyController {
#RequestMapping("/")
fun index(): String {
return "index"
}
}
As indicated in the Spring Boot documentation, you do not need - in fact, it is not recommended - to use #EnableWebMvc when using Spring Boot. They state, when describing Spring MVC auto-configuration:
Spring Boot provides auto-configuration for Spring MVC that works well with most applications.
And:
If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own #Configuration class of type WebMvcConfigurer but without #EnableWebMvc.
In the guide, they continue when describing static content handling:
By default, Spring Boot serves static content from a directory called /static (or /public or /resources or /META-INF/resources) in the classpath or from the root of the ServletContext. It uses the ResourceHttpRequestHandler from Spring MVC so that you can modify that behavior by adding your own WebMvcConfigurer and overriding the addResourceHandlers method.
In your example, following this advice, you can indicate the static resource handling location with something like (sorry, I am not fluent in Kotlin, forgive for write the example in Java):
#Controller
public class MyController implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static")
;
}
#GetMapping(path = "/")
public String index() {
return "index";
}
}
Please, adapt the paths in addResourceHandlers to your needs.
You can of course place this method in an ad hoc #Configuration.
Having said that, if when you say granular you mean security, the best approach you can take is to configure Spring Security and provide the necessary authorization rules: please, see the relevant documentation.

How to call Spring Framework repositories methods

I know that there are questions similar to this one, but none of them have helped me. I'm following along this tutorial, and the part I can't wrap my mind around is:
#SpringBootApplication
public class Application {
private static final Logger log =
LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
#Bean
public CommandLineRunner demo(CustomerRepository repository) {
return (args) -> {
// save a couple of customers
...
// more lines, etc...
What I don't understand is where the repository passed into demo comes from. I know that the Autowired annotation can do something like that, but it isn't used at all here.
The more specific reason I ask is because I'm trying to adapt what they do here to an application I'm working on. I have a class, separate from all of the persistence/repository stuff, and I want to call repository methods like save and findAll. The issue is that the repository is an interface, so I can't instantiate an object of it to call the methods. So do I have to make a new class that implements the interface and create an object of that? Or is there an easier way using annotations?
When creating a #Bean, adding the repository in the parameters of the bean is enough to wire the repos in your bean. This works pretty much like adding #Autowired annotation inside a class that is annotated as #Component or something similar.
Spring works mostly with interface, since that is simplier to wire vs wiring concrete classes.
Can you try #Repository before the declaration of class? Worked for me in a Spring MVC structure.
#Repository
public class EntityDAOImpl implements EntityDAO{
...
}
The thing to wrap your head around is a Spring Boot application at startup time aims to resolve its dependancy tree. This means discovering and instantiating Beans that the application defines, and those are classes annotated with #Service, #Repository, etc.
This means the default constructor (or the one marked with #Autowire) of all beans is invoked, and after all beans have been constructed the application starts to run.
Where the #Bean annotation comes into play is if you have a bean which does not know the values of it's constructor parameters at compile time (e.g. if you want to wire in a "started at" timestamp): then you would define a class with an #Configuration annotation on it, and expose an #Bean method in it, which would return your bean and have parameters that are the beans dependencies. In it you would invoke the beans constructor and return the bean.
Now, if you want a certain method of some class to be invoked after the application is resolved, you can implement the CommandLineRunner interface, or you can annotate a method with #PostConstruct.
Some useful links / references:
https://docs.spring.io/spring-javaconfig/docs/1.0.0.m3/reference/html/creating-bean-definitions.html
https://www.baeldung.com/spring-inject-prototype-bean-into-singleton
Running code after Spring Boot starts
Execute method on startup in Spring

Spring configuration bean with defaults and multiple overrides

I am building a Spring Boot application that has reason to call out to multiple HTTP services. I would like to be able to configure my Clients with varying options, e.g. socket timeouts, as well as have a default.
Ideally, I could specify properties like this:
client.default.socket-timeout=500ms
client.slow-service.socket-timeout=1000ms # it's a bit slower
client.fast-service.socket-timeout=100ms
make a simple class like:
class ClientConfiguration {
#Value("${client.<client-name>.socket-timeout:${client.default.socket-timeout:30}}")
int socketTimeout;
}
And then be able to inject:
#Inject
public MyService(#Named("slow-service") ClientConfiguration slowServiceConfig) { ... }
Normally I set my configuration via #Value, but there doesn't appear to be a way to parametrize the key it uses. Especially not based on the bean name. I would love to avoid writing tons of boilerplate to create key names and fetch it from a PropertyResolver or other manual approach.
Does Spring (4.3.0) or Spring Boot (1.4.0.M3) have any good pattern to address this use case?
When we had similar requirement, instead of using individual #Value all over the code, we created a configuration service per group of keys.
#Service
public class SlowClientConfigurationService {
#Value("${client.slow.property.key}")
private String slowValue;
// getters, setters, sanity checks and so on...
}
and inject this service, where ever you need slow client configuration, which can provide multiple key values via getter/setters method, and also it keeps the code clean.
#Service
public class YourService{
#Autowire
private SlowClientConfigurationService configurationService ;
//...
}

Rest + Spring AOP + interface doesn't inject

I have a Spring AOP aspect used for logging, where a method can be included for logging by adding an annotation to it, like this:
#AspectLogging("do something")
public void doSomething() {
...
}
I've been using this on Spring beans and it's been working just fine. Now, I wanted to use it on a REST-service, but I ran into some problems. So, I have:
#Path("/path")
#Service
public class MyRestService {
#Inject
private Something something;
#GET
#AspectLogging("get some stuff")
public Response getSomeStuff() {
...
}
}
and this setup works just fine. The Rest-service that I'm trying to add the logging to now has an interface, and somehow that messes stuff up. As soon as I add the #AspectLogging annotation to one of the methods, no dependencies are injected in the bean, and also, the aspect is newer called!
I've tried adding an interface to the REST-service that works, and it gets the same error.
How can having an interface lead to this type of problems? The aspect-logger works on classes with interfaces elsewhere, seems it's only a problem when it's a REST-service..
Ref the below Spring documentation (para 2) -
To enable AspectJ annotation support in the Spring IoC container, you
only have to define an empty XML element aop:aspectj-autoproxy in your
bean configuration file. Then, Spring will automatically create
proxies for any of your beans that are matched by your AspectJ
aspects.
For cases in which interfaces are not available or not used in an
application’s design, it’s possible to create proxies by relying on
CGLIB. To enable CGLIB, you need to set the attribute
proxy-targetclass= true in aop:aspectj-autoproxy.
In case your class implements an interface, a JDK dynamic proxy will be used. However if your class does not implement any interfaces then a CGLIB proxy will be created. You can achieve this #EnableAspectJAutoProxy. Here is the sample
#Configuration
#EnableAspectJAutoProxy
public class AppConfig {
#Bean
public LoggingAspect logingAspect(){
return new LoggingAspect();
}
}
#Component
#Aspect
public class LoggingAspect {
...
...
}
In my opinion what you are actually trying to do is to add spring annotations to a class maintained by jersey. In the result you are receiving a proxy of proxy of proxy of somethng. I do not think so this is a good idea and this will work without any problems. I had a similar issue when I tried to implement bean based validation. For some reasons when there were #PahtParam and #Valid annotations in the same place validation annotations were not visible. My advice is to move your logging to a #Service layer instead of #Controller.

Spring web application healthchecks

I'm deploying Spring based web applications on Amazon's Beanstalk platform, and they give me the option of setting a "healthcheck" URL path for my application.
The idea is that their platform will do a request against that URL, after the deployment, to see if the application is successfully started. So, if the request results in an HTTP 200, the application is probably fine. But if it results in an HTTP 500 or something else, the platform knows there's a problem with the application.
So, I wish I could develop some kind of servlet that would check if the Spring Application Context was successfully initialised, or not, to give an appropriate HTTP response code to the platform.
Has anybody attempted something like this? For similar purposes?
I'm wondering if Spring already provides some elegant solution for this.
I'd suggest using health checks functionality from Metrics. You could set up a number of classes that extend HealthCheck class and implement check() method. These health check implementations would be Spring managed beans themselves and could autowire Spring beans and validate them. Then configure HealthCheckServlet to monitor application state. Also check metrics-spring project. It will make Spring and Metrics integration simpler.
If you are using Java Spring configuration you might have a Metrics config like this that extends MetricsConfigurerAdapter from metrics-spring
#Configuration
#EnableMetrics
public class MetricsConfig extends MetricsConfigurerAdapter { }
And then #Import(value = {MetricsConfig.class}) to your Spring config.
You also need and implementation of ServletContextListener to wire up HealthCheckServlet and Spring. This HealthCheckContextListener should be added to your web.xml
public class HealthCheckContextListener extends
HealthCheckServlet.ContextListener implements ServletContextListener {
private WebApplicationContext context;
public HealthCheckContextListener(WebApplicationContext context) {
this.context = context;
}
public HealthCheckContextListener() {}
#Override
public void contextInitialized(ServletContextEvent event) {
this.context = WebApplicationContextUtils.getRequiredWebApplicationContext(event.getServletContext());
event.getServletContext().setAttribute(HealthCheckServlet.HEALTH_CHECK_REGISTRY,
context.getBean(HealthCheckRegistry.class));
}
#Override
protected HealthCheckRegistry getHealthCheckRegistry() {
return (HealthCheckRegistry) context.getBean(HealthCheckRegistry.class);
}
}
The simplest thing you can do is this:
#Controller
class HealthCheckController {
#ResponseStatus(OK)
#RequestMapping(value = "/ping", method = HEAD) {
public void ping() {
}
}
Extendable to also test particular beans, DataSources etc.
You should consider what constitutes a healthy app for you (e.g., servlet tier? JMS queues? FTP servers? etc.) and have your health check verify those services' availability. Obviously the health check is going to run frequently, so you don't want to initiate expensive operations over and over again.
Spring Boot is a new project that aims to simplify Spring development by favoring convention instead of configuration. They have implemented a "health check" feature that you can add to a project via an Actuator add-in module.
Here's a reference to their Health Check implementation -- it uses a controller class to return "ok" and, if there is a data source, attempts to run a query to confirm that the database is accessible (something like "SELECT .. from dual" in Oracle syntax).
This can easily be done in the spring boot framework. By adding below dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
You can check the service by hitting the below URL.
localhost:serverPort/actuator/health

Categories

Resources