I am trying to send my API application metrics to AWS Cloudwatch using the mircometer registry's timer. I have successfully managed to send custom metrics by implementing it manually so far. But, I want to send the metrics using the #Timed annotation, and it doesn't work. Here are the things I have tried so far:
#Timed("test")
#RestController
public class TempHandler{
#GetMapping(value="/path")
#Timed(value="ping")
public ResponseEntity ping(#RequestHeader Map<String,String> headers){
return applyHeaders(Response.status(200).entity("ok"));
}
}
I have created a #Configuration class as well to return a TimedAspect object.
#Configuration
public class TimedConfiguration {
#Bean
public TimedAspect timedAspect(MeterRegistry registry) {
return new TimedAspect(registry);
}
}
I have included the spring AOP dependancy in my build.gradle as well. Please help me to figure out what I am doing wrong. Thanks!
Related
I have tried to find documentation on how to manually configure a RestController (i.e in a Configuation class). That means without using the RestController annotation. Considering all the other annotations, like mapping, pathvariables etc. is at all possible?
A controller is essentially a component with a request mapping. See RequestMappingHandlerMapping.
#Override
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
If you want to instantiate a "rest controller" through configuration, you can probably do so via the following:
#Configuration
public class MyConfiguration {
#Bean
public MyController() {
return new MyController();
}
}
#ResponseBody
public class MyController {
#RequestMapping("/test")
public String someEndpoint() {
return "some payload";
}
}
But I don't think you'll be able to configure the request mappings (path variables, etc) in the configuration though; at least I haven't seen an example nor figured out how.
I try to make a chatbot using springboot (websocket), i want to know if it's possible to push a dynamic message in Scheduler, and i need some help, i'can't fugure it out.
I want to push the message in the Scheduler Configure how could i do that:
#EnableScheduling
#Configuration
public class SchedulerConfig {
#Autowired
SimpMessagingTemplate template;
#Scheduled(fixedDelay = 3000)
public void sendAdhocMessages() {
template.convertAndSend("/topic/user", new UserResponse("Fixed Delay Scheduler"));
}
}
in the sendAdhocMessages method i want to pass a message that will be displayed in an html page. in the Official doc it's impossible to pass a parameter to a method which is annotated by #Scheduled, is there any methd to do that?
The official documentation contains a hint to, how you could pass values to the scheduled method. Maybe you could provide a bean that acts as a message provider. In the scheduler class you autowire the message provider and request the messages.
A short code example:
#Componet
public class MessageProvider {
private String message;
// getter and setter ...
}
In the scheduler you could use the message provider like following:
#EnableScheduling
#Configuration
public class SchedulerConfig {
#Autowired
SimpMessagingTemplate template;
#Autowired
MessageProvider messageProvider;
#Scheduled(fixedDelay = 3000)
public void sendAdhocMessages() {
String currentMessage = messageProvider.getMessage();
template.convertAndSend("/topic/user", new UserResponse(currentMessage));
}
}
I have a very simple Spring Boot application. I launch this through the basic SpringApplication.run(Startup.class, args); and have a custom #Configuration class in there that overrides the default converters. I decided to add Swagger to the mix of things so that I can generate better documentation for our internal user base as there are gads of endpoints.
When I started things up, Swagger simply wouldn't work.
I decided to start a front-scratch Spring Boot with just one endpoint to document to see what went wrong. Out-of-the box this worked perfectly fine and I was able to get Swagger running via just hitting the http://localhost:8080/swagger-ui.html base URL.
When I implemented my custom #Configuration class that extended WebMvcConfigurationSupport, Swagger no longer worked.
My configuration overrode a single method:
#Configuration
public class StartupConfiguration extends WebMvcConfigurationSupport {
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(getJsonConverter());
}
}
That's it. I decided to add the default converters as well without any luck. Then I just emptied the class and left it as:
#Configuration
public class StartupConfiguration extends WebMvcConfigurationSupport {
}
Swagger is still broken - if I remove the class completely, then it works.
What can I do to keep my custom configuration data and run Swagger? I would also love to move it to something like http://localhost:8080/swagger/ rather than the default file it uses, but that is a completely separate issue for now.
My launch of Swagger looks like this:
#Configuration
#EnableSwagger2
public class SwaggerConfiguration {
#Bean
public Docket getDocket() {
// ...
return new Docket(DocumentationType.SWAGGER_2)
.groupName("Core API")
.apiInfo(infoBuilder.build())
.select().paths(PathSelectors.regex("/*"))
.build();
}
}
Overriding the default resource handler worked for me. I added the following to the configuration class extending WebMvcConfigurationSupport:
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry
.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
I am trying to add an interceptor to a simple Spring-boot-mongodb-rest app, as can be seen here : http://spring.io/guides/gs/accessing-mongodb-data-rest/, in order to perform certain actions after the default rest handler is invoked. Here is my MongoRepository, whose CRUD operation is called upon a POST request to the server:
#RepositoryRestResource(collectionResourceRel = "reminder", path = "reminder")
public interface ReminderRepository extends MongoRepository<Reminder, String> {
List<Reminder> findBySendee(#Param("sendee") String sendee);
}
I am trying to register an interceptor for all HTTP requests by extending the WebMvcConfigurerAdapter class like this:
#Configuration
#ComponentScan
public class RemindxWebConfig extends WebMvcConfigurerAdapter {
#Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(new RemindxInterceptor());
}
}
As mentioned in the spring boot docs, I have not added the #EnableWebMvc annotation to this. While running the application, the addInterceptors function does get called and adds the interceptor. However, the given interceptor is not called after the POST handler is invoked. I am unable to figure out a way to have spring use this RemindxWebConfig for all MongoRepository http requests. Any inputs are appreciated.
I have a use case where my application hosts REST API and web application and we need to add custom header to REST APIs only. REST APIs are enabled through Spring Data REST. Typically we could use Servlet Filter to achieve this but we need code the logic of isolating requests to our REST API and add the custom headers. It would be nice if Spring Data REST API allows to add a default header to all the responses it generates. What are your thoughts? Don't say I am lazy :)
For folks looking for actual implementation details..
Interceptor
public class CustomInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
System.out.println("adding CORS headers.....");
response.addHeader("HEADER-NAME", "HEADER-VALUE");
return true;
}
}
Java Configuration
#Configuration
public class RepositoryConfig extends
RepositoryRestMvcConfiguration {
#Override
public RequestMappingHandlerMapping repositoryExporterHandlerMapping() {
RequestMappingHandlerMapping mapping = super
.repositoryExporterHandlerMapping();
mapping.setInterceptors(new Object[] { new CustomInterceptor() });
return mapping;
}
}
As Spring Data REST is built on top of Spring MVC, the easiest way is to configure a custom HandlerInterceptor as described in the reference documentation.
With Spring Data REST the easiest way is to extend RepositoryRestMvcConfiguration and override repositoryExporterHandlerMapping, call the parent method and then invoke ….setInterceptors(…) on it.
Finally I managed to make the setup of custom interceptor working also on spring-data-rest 2.4.1.RELEASE.
#Configuration
public class RestMvcConfig extends RepositoryRestMvcConfiguration {
#Autowired UserInterceptor userInterceptor;
#Autowired ApplicationContext applicationContext;
#Override
public DelegatingHandlerMapping restHandlerMapping() {
RepositoryRestHandlerMapping repositoryMapping = new RepositoryRestHandlerMapping(resourceMappings(), config());
repositoryMapping.setInterceptors(new Object[] { userInterceptor }); // FIXME: not nice way of defining interceptors
repositoryMapping.setJpaHelper(jpaHelper());
repositoryMapping.setApplicationContext(applicationContext);
repositoryMapping.afterPropertiesSet();
BasePathAwareHandlerMapping basePathMapping = new BasePathAwareHandlerMapping(config());
basePathMapping.setApplicationContext(applicationContext);
basePathMapping.afterPropertiesSet();
List<HandlerMapping> mappings = new ArrayList<HandlerMapping>();
mappings.add(basePathMapping);
mappings.add(repositoryMapping);
return new DelegatingHandlerMapping(mappings);
}
}
I had to override the restHandlerMapping method, copy-paste it's content and add a line repositoryMapping.setInterceptors for adding custom interceptor, in my case the UserInterceptor.
Is there any better way?