How to make post request in apache camel rest - spring

I am new apache rest dsl with spring boot, have made following changes
Main Class
package com.javaoutofbounds.pojo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication(scanBasePackages = {"com.ccs.batchfile"})
public class BatchFileApplication {
public static void main(String[] args) {
SpringApplication.run(BatchFileApplication.class, args);
}
}
Service class
package com.ccs.batchfile.service;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.rest.RestBindingMode;
import org.springframework.stereotype.Component;
#Component
public class BatchFileService extends RouteBuilder {
#Override
public void configure() throws Exception {
restConfiguration().component("servlet").bindingMode(RestBindingMode.json);
rest("/batchFile").consumes("application/json").produces("application/json").get("/routeStart").to("direct:startRoute");
}
}
Route class
package com.ccs.batchfile.routes;
import org.apache.camel.builder.RouteBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ccs.batchfile.processor.StartRouteProcessor;
#Component
public class StartRoute extends RouteBuilder{
#Autowired
private StartRouteProcessor startRouteProcessor;
#Override
public void configure() throws Exception {
from("direct:startRoute").log("Inside StartRoute")
.process(startRouteProcessor);
}
}
Processor class
package com.ccs.batchfile.processor;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.springframework.stereotype.Component;
#Component("startRouteProcessor")
public class StartRouteProcessor implements Processor{
public void process(Exchange exchange) throws Exception {
String message = exchange.getIn().getBody(String.class);
System.out.println(message);
}
}
I am not getting control to StartRouteProcessor, when i make below post request in postman
http://localhost:8080/batchFile/routeStart/
I have used below test payload to check if works.
{
"title" : "test title",
"singer" : "some singer"
}
When i post the above request i am getting 404 error. Kindly help on this please

I tried your example and you need to add two changes.
In your "main" class, the 'component scan' annotation is right, but you have to add a 'ServletRegistrationBean' with name 'CamelServlet':
package org.funcode.app.main;
import org.apache.camel.component.servlet.CamelHttpTransportServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
#SpringBootApplication(scanBasePackages = {"org.funcode.app"})
public class BatchFileApplication {
private static final String CAMEL_URL_MAPPING = "/api/*";
private static final String CAMEL_SERVLET_NAME = "CamelServlet";
public static void main(String[] args) {
SpringApplication.run(BatchFileApplication.class, args);
}
#Bean
public ServletRegistrationBean servletRegistrationBean() {
ServletRegistrationBean registration =
new ServletRegistrationBean(new CamelHttpTransportServlet(), CAMEL_URL_MAPPING);
registration.setName(CAMEL_SERVLET_NAME);
return registration;
}
}
And if you want view on the log the content you posted on the request, you need to change the method of the request to "post":
package org.funcode.app.main;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.rest.RestBindingMode;
import org.springframework.stereotype.Component;
#Component
public class BatchFileService extends RouteBuilder {
#Override
public void configure() throws Exception {
restConfiguration().component("servlet").bindingMode(RestBindingMode.json);
rest("/batchFile")
.consumes("application/json")
.produces("application/json")
.post("/routeStart")
.to("direct:startRoute");
}
}
I hope it helps.

Related

Open tracer Jaeger Trace not getting reflect for apache camel

I am new to apache camel and open tracing with Jaeger, I trying to get the traces for apache camel in Jaeger UI but its not getting captured through Open Tracing.
import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import org.springframework.stereotype.Component;
#Component
public class RouteBuilderClient {
public void test() throws Exception {
DefaultCamelContext camelContext = new DefaultCamelContext();
camelContext.addRoutes(new RouteBuilder() {
#Override
public void configure() throws Exception {
from("timer:first-timer")
.to("log:first-timer");
}
});
camelContext.start();
camelContext.stop();
}
}
However if if I extend the RouteBuilder class(Below is the sample code) and then I override the configure method then traces are getting generated for Apache camel. Is there any way without extending the routeBuilder I can get the traces?
import org.apache.camel.builder.RouteBuilder;
import org.springframework.stereotype.Component;
#Component
public class RouteBuilderClient extends RouteBuilder {
#Override
public void configure() throws Exception {
from("timer:first-timer")
.to("log:first-timer");
}
}
My controller class:
import org.apache.camel.opentracing.starter.CamelOpenTracing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
#CamelOpenTracing
public class JaegarClientApplication {
public static void main(String[] args) {
SpringApplication.run(JaegarClientApplication.class, args);
}
}
Try adding this in your setup() method, before starting the Camel context:
OpenTracingTracer ottracer = new OpenTracingTracer();
ottracer.init(camelContext);
camelContext.start();
Below is my code that Worked successfully.
import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.opentracing.OpenTracingTracer;
public class RouteBuilderClient3 {
public void test() throws Exception {
RouteBuilder builder = new RouteBuilder() {
public void configure() {
from("timer:first-timer3").transform().constant("Rajesh client 3")
.to("log:first-timer3");
}
};
CamelContext myCamelContext = new DefaultCamelContext();
myCamelContext.addRoutes(builder);
OpenTracingTracer ottracer = new OpenTracingTracer();
ottracer.init(myCamelContext);
myCamelContext.start();
// myCamelContext.stop();
}
}

KafkaBindingRebalanceListener Bean not autowired by KafkaMessageChannelBinder Bean

Documentation is pretty straight forward which suggests exposing a Bean of type KafkaBindingRebalanceListener and onPartitiosnAssigned method would be called internally. I'm trying to do the same and somehow while spring framework creates its KafkaMessageChannelBinder Bean the ObjectProvider.getIfUnique() always return null as it not able to find the required bean. It seems when application starts SpringFramework strats creating its Beans first and isnt able to find the Rebalance Listener Bean as it is not yet created. Following are the three code snippets from project. Please help if im missing anything to instruct application to create Beans in application package first before going to Spring Framework.
RebalanceListener
package io.spring.dataflow.sample.seekoffset.config;
import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.common.TopicPartition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.stream.binder.kafka.KafkaBindingRebalanceListener;
import org.springframework.stereotype.Component;
import java.util.Collection;
#Component
public class KafkaRebalanceListener implements KafkaBindingRebalanceListener {
Logger logger = LoggerFactory.getLogger(SeekOffsetConfig.class);
#Override
public void onPartitionsAssigned(String bindingName, Consumer<?, ?> consumer, Collection<TopicPartition> partitions, boolean initial) {
logger.debug("onPartitionsAssigned");
}
}
ConfigClass
package io.spring.dataflow.sample.seekoffset.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.messaging.Message;
#EnableBinding(Sink.class)
public class SeekOffsetConfig {
Logger logger = LoggerFactory.getLogger(SeekOffsetConfig.class);
#StreamListener(Sink.INPUT)
public void receiveMessage(Message<String> message) {
logger.debug("receiveMessage()");
}
}
ApplicationClass
package io.spring.dataflow.sample.seekoffset;
import io.spring.dataflow.sample.seekoffset.config.KafkaRebalanceListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
public class SeekOffsetApplication {
Logger logger = LoggerFactory.getLogger(SeekOffsetApplication.class);
public static void main(String[] args) {
SpringApplication.run(SeekOffsetApplication.class, args);
}
}
What version are you using? This works fine for me with Boot 2.3.2 and Hoxton.SR6:
#SpringBootApplication
#EnableBinding(Sink.class)
public class So63157778Application {
public static void main(String[] args) {
SpringApplication.run(So63157778Application.class, args);
}
#StreamListener(Sink.INPUT)
public void listen(String in) {
System.out.println(in);
}
#Bean
KafkaBindingRebalanceListener rebal() {
return new KafkaBindingRebalanceListener() {
#Override
public void onPartitionsAssigned(String bindingName, Consumer<?, ?> consumer,
Collection<TopicPartition> partitions, boolean initial) {
System.out.println(bindingName + " assignments: " + partitions + ", initial call :" + initial);
}
};
}
}
input assignments: [input-0], initial call :true
This works for me too:
#SpringBootApplication
#EnableBinding(Sink.class)
public class So63157778Application {
public static void main(String[] args) {
SpringApplication.run(So63157778Application.class, args);
}
#StreamListener(Sink.INPUT)
public void listen(String in) {
System.out.println(in);
}
}
#Component
class Foo implements KafkaBindingRebalanceListener {
#Override
public void onPartitionsAssigned(String bindingName, Consumer<?, ?> consumer,
Collection<TopicPartition> partitions, boolean initial) {
System.out.println(bindingName + " assignments: " + partitions + ", initial call :" + initial);
}
}

In Spring Boot Test, how do I map a temporary folder to a configuration property?

I want to do a self-cleaning test
In my situation, I have one of the components depend on a directory
public class FileRepositoryManagerImpl implements ....
#Value("${acme.fileRepository.basePath}")
private File basePath;
}
The value is defined in the application.yml file, and in DEV it points to a directory under build.
This is not the worst idea, because gradle clean will eventually clean up the mess the tests create.
But, really, what I would like to achieve here, is to make sure that every test runs in an isolated temporary directory that is cleaned up after execution.
I know that JUnit has a tool for the temporary directories. But once I have defined that directory in the scope of JUnit 4, how do I tell Spring to use that temporary directory?
I tried the inner class unsuccessfully:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = { SecurityBeanOverrideConfiguration.class, App.class })
#EnableConfigurationProperties
public abstract class AbstractFileRepositoryManagerIntTests {
private final static TemporaryFolder temporaryFolder = new TemporaryFolder();
#ClassRule
public static TemporaryFolder getTemporaryFolder()
{
return temporaryFolder;
}
#ConfigurationProperties(prefix = "acme")
static class Configuration
{
public FileRepository getFileRepository()
{
return new FileRepository();
}
static class FileRepository
{
public File basePath() throws Exception
{
return temporaryFolder.newFolder("fileRepositoryBaseDir");
}
}
}
}
I was thinking about tinkering with the Environment, but what should be the correct way to inject properties programmatically in a Spring Boot test?
I can think of at least four different approaches to your problem. All with their own advantages and disadvantages.
Approach 1: ReflectionTestUtils
You are using #Value annotation on a private instance property (please, don't to that anymore!). Hence, you can not change acme.fileRepository.basePath on the fly without reflection.
package demo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Component;
import java.io.File;
#SpringBootApplication
public class FileRepositoryApp {
public static void main(String[] args) {
SpringApplication.run(FileRepositoryApp.class, args);
}
#Component
public class FileRepository {
#Value("${acme.fileRepository.basePath}")
private File basePath;
public File getBasePath() {
return basePath;
}
}
}
Changing basePath after each test with ReflectionTestUtils.setField. Because we are using Spring's TestExecutionListener, that gets initialized before Junit rules are initialized, we are forced to manage the temporary folder in beforeTestExecution and afterTestMethod.
package demo;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.TestExecutionListener;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.util.ReflectionTestUtils;
import java.io.IOException;
import static junit.framework.TestCase.assertEquals;
import static org.springframework.test.context.TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = FileRepositoryApp.class)
#TestExecutionListeners(listeners = FileRepositoryAppTest.SetBasePath.class, mergeMode = MERGE_WITH_DEFAULTS)
public class FileRepositoryAppTest {
private static TemporaryFolder temporaryFolder = new TemporaryFolder();
#Autowired
private FileRepositoryApp.FileRepository fileRepository;
#Test
public void method() {
System.out.println(temporaryFolder.getRoot().getAbsolutePath());
System.out.println(fileRepository.getBasePath());
assertEquals(temporaryFolder.getRoot(), fileRepository.getBasePath());
}
#Test
public void method1() {
System.out.println(temporaryFolder.getRoot().getAbsolutePath());
System.out.println(fileRepository.getBasePath());
assertEquals(temporaryFolder.getRoot(), fileRepository.getBasePath());
}
static class SetBasePath implements TestExecutionListener {
#Override
public void beforeTestExecution(TestContext testContext) throws IOException {
temporaryFolder.create();
if (testContext.hasApplicationContext()) {
FileRepositoryApp.FileRepository bean = testContext.getApplicationContext().getBean(FileRepositoryApp.FileRepository.class);
ReflectionTestUtils.setField(bean, "basePath", temporaryFolder.getRoot());
}
}
#Override
public void afterTestMethod(TestContext testContext) {
temporaryFolder.delete();
}
}
}
Approach 2: Configuration properties
Introduce a configuration properties class for your application configuration. It gives you type safety for free and we don't rely on reflection anymore.
package demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.io.File;
#SpringBootApplication
public class FileRepositoryWithPropertiesApp {
public static void main(String[] args) {
SpringApplication.run(FileRepositoryWithPropertiesApp.class, args);
}
#Component
public class FileRepository {
private final FileRepositoryProperties fileRepositoryProperties;
public FileRepository(FileRepositoryProperties fileRepositoryProperties) {
this.fileRepositoryProperties = fileRepositoryProperties;
}
public File getBasePath() {
return fileRepositoryProperties.getBasePath();
}
}
#Component
#ConfigurationProperties(prefix = "acme.file-repository")
public class FileRepositoryProperties {
private File basePath;
public File getBasePath() {
return basePath;
}
public void setBasePath(File basePath) {
this.basePath = basePath;
}
}
}
Because we are using Spring's TestExecutionListener, that gets initialized before Junit rules are initialized, we are forced to manage the temporary folder in beforeTestExecution and afterTestMethod.
package demo;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.TestExecutionListener;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.IOException;
import static junit.framework.TestCase.assertEquals;
import static org.springframework.test.context.TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = FileRepositoryWithPropertiesApp.class)
#TestExecutionListeners(listeners = FileRepositoryWithPropertiesTest.SetBasePath.class, mergeMode = MERGE_WITH_DEFAULTS)
public class FileRepositoryWithPropertiesTest {
private static TemporaryFolder temporaryFolder = new TemporaryFolder();
#Autowired
private FileRepositoryWithPropertiesApp.FileRepository bean;
#Test
public void method() {
System.out.println(temporaryFolder.getRoot().getAbsolutePath());
System.out.println(bean.getBasePath());
assertEquals(temporaryFolder.getRoot(), bean.getBasePath());
}
#Test
public void method1() {
System.out.println(temporaryFolder.getRoot().getAbsolutePath());
System.out.println(bean.getBasePath());
assertEquals(temporaryFolder.getRoot(), bean.getBasePath());
}
static class SetBasePath implements TestExecutionListener {
#Override
public void beforeTestExecution(TestContext testContext) throws IOException {
temporaryFolder.create();
if (testContext.hasApplicationContext()) {
FileRepositoryWithPropertiesApp.FileRepositoryProperties bean = testContext.getApplicationContext().getBean(FileRepositoryWithPropertiesApp.FileRepositoryProperties.class);
bean.setBasePath(temporaryFolder.getRoot());
}
}
#Override
public void afterTestMethod(TestContext testContext) {
temporaryFolder.delete();
}
}
}
Approach 3: Refactor your code (my favorite)
Extract basePath into its own class and hide it behind an api. Now you don't need to poke with your application properties and a temporary folder anymore.
package demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.io.File;
#SpringBootApplication
public class FileRepositoryWithAbstractionApp {
public static void main(String[] args) {
SpringApplication.run(FileRepositoryWithAbstractionApp.class, args);
}
#Component
public class FileRepository {
private final FileRepositorySource fileRepositorySource;
public FileRepository(FileRepositorySource fileRepositorySource) {
this.fileRepositorySource = fileRepositorySource;
}
public File getBasePath() {
return fileRepositorySource.getBasePath();
}
}
#Component
public class FileRepositorySource {
private final FileRepositoryProperties fileRepositoryProperties;
public FileRepositorySource(FileRepositoryProperties fileRepositoryProperties) {
this.fileRepositoryProperties = fileRepositoryProperties;
}
// TODO for the sake of brevity no real api here
public File getBasePath() {
return fileRepositoryProperties.getBasePath();
}
}
#Component
#ConfigurationProperties(prefix = "acme.file-repository")
public class FileRepositoryProperties {
private File basePath;
public File getBasePath() {
return basePath;
}
public void setBasePath(File basePath) {
this.basePath = basePath;
}
}
}
We don't need any additional testing facility anymore and we can use #Rule on TemporaryFolder instead.
package demo;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import static junit.framework.TestCase.assertEquals;
import static org.mockito.Mockito.when;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = FileRepositoryWithAbstractionApp.class)
public class FileRepositoryWithAbstractionTest {
#Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
#MockBean
private FileRepositoryWithAbstractionApp.FileRepositorySource fileRepositorySource;
#Autowired
private FileRepositoryWithAbstractionApp.FileRepository bean;
#Before
public void setUp() {
when(fileRepositorySource.getBasePath()).thenReturn(temporaryFolder.getRoot());
}
#Test
public void method() {
System.out.println(temporaryFolder.getRoot().getAbsolutePath());
System.out.println(bean.getBasePath());
assertEquals(temporaryFolder.getRoot(), bean.getBasePath());
}
#Test
public void method1() {
System.out.println(temporaryFolder.getRoot().getAbsolutePath());
System.out.println(bean.getBasePath());
assertEquals(temporaryFolder.getRoot(), bean.getBasePath());
}
}
Approach 4: TestPropertySource
Use Spring's TestPropertySource annotation to override properties in a test selectively. Because a Java anntotation can not have a dynamic value, you need to decide beforehand where you want to create your directory and keep in mind your test is bound to a specific operating system due to the used os path separator.
package demo;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import static demo.FileRepositoryTestPropertySourceTest.BASE_PATH;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = FileRepositoryApp.class)
#TestPropertySource(properties = "acme.fileRepository.basePath=" + BASE_PATH)
public class FileRepositoryTestPropertySourceTest {
static final String BASE_PATH = "/tmp/junit-base-path";
private Path basePath = Paths.get(BASE_PATH);;
#Autowired
private FileRepositoryApp.FileRepository fileRepository;
#Before
public void setUp() throws IOException {
Files.deleteIfExists(basePath);
Files.createDirectories(basePath);
}
#After
public void after() throws IOException {
Files.deleteIfExists(basePath);
}
#Test
public void method() {
System.out.println(fileRepository.getBasePath());
}
}
If you use JUnit 5.4+ then you can leverage their #TempDir that works just fine without manual lifecycle management of the directory. That is you don't need to create and delete it manually, in contrast to #TemporaryFolder from JUnit 4.
Here is a working example of how you can achieve your goal:
//Your bean into which you want to inject the property
#Component
public class FileRepositoryManager {
#Value("${acme.fileRepository.basePath}")
private File basePath;
public File getBasePath() {
return basePath;
}
}
//Test that uses ApplicationContextInitializer machinery to set the desired properties
#SpringBootTest
#ContextConfiguration(initializers = Initializer.class)
class FileRepositoryManagerTest {
#TempDir
static File tempDir;
#Autowired
FileRepositoryManager fileRepositoryManager;
#Test
void basePathIsSet() {
assertNotNull(fileRepositoryManager.getBasePath());
}
static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
#Override
public void initialize(ConfigurableApplicationContext context) {
TestPropertyValues.of(
"acme.fileRepository.basePath=" + tempDir
).applyTo(context);
}
}
}

Intercept calls to RestController in Spring Boot

I've looked at similar problems:
how to intercept all requests in spring REST controllers?
spring boot adding http request interceptors
And still can't figure out the solution.
I have a Spring Boot app that runs a bunch of Rest Controllers and want to intercept calls and perform some business logic before the request is passed to the controllers. I have this:
My Application class for Sprint Boot:
package com.amazonaws.lambda.keefinty.application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
#SpringBootApplication(scanBasePackages="com.amazonaws.lambda.keefinty.controllers")
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
My Configuration class in same package a Application:
package com.amazonaws.lambda.keefinty.application;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.amazonaws.lambda.keefinty.interceptors.MyInterceptor;
#Configuration
public class MyConfiguration extends WebMvcConfigurerAdapter {
#Bean
public MyInterceptor getInterceptor() {
return new MyInterceptor();
}
#Override
public void addInterceptors (InterceptorRegistry registry) {
System.out.println("\n\nAdding interceptors\n\n");
registry.addInterceptor(getInterceptor()).addPathPatterns("/**");
}
}
And finally the interceptor class:
package com.amazonaws.lambda.keefinty.interceptors;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
#Component
public class MyInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.print("\\n\\nIn MyInterceptor.preHandle\\n\\n");
String token = request.getParameter("token");
if (StringUtils.isBlank(token)) {
throw new Exception("Invalid User Id or Password. Please try again.");
}
return true;
}
#Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception exception) throws Exception {
// TODO Auto-generated method stub
System.out.print("\n\nIn MyInterceptor.afterCompletion\\n\\n");
}
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
System.out.print("\\n\\nIn MyInterceptor.postHandle\\n\\n");
}
}
The Configuration class never seems to get called to register the interceptors nor does MyInterceptor.
By declaring #SpringBootApplication(scanBasePackages="com.amazonaws.lambda.keefinty.controllers") only annotated components from com.amazonaws.lambda.keefinty.controllers package and it's sub packages will be discovered.
You MyConfiguration class is in com.amazonaws.lambda.keefinty.application package which is not part of the declared component scan package.
One way to resolve this is to remove scanBasePackages argument from your #SpringBootApplication declaration. This will allow MyConfiguration to be component scanned as by default the package in which #SpringBootApplication is declared is component scanned.

Spring Boot AOP #before not working

I have written this code :
It seems perfect but not working
When i run the code it runs fine
I hit the URL for (/) and only the greetings method is called
AOP method is not getting called
This is my main Class
DemoApplication.java
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.aop.AOPSample;
com.services.TaskService;
#SpringBootApplication
#ComponentScan({"com.aop","com.services"})
#RestController
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#RequestMapping("/")
public void greetings(){
new TaskService().startService();
System.out.println("In Greetings");
}
}
AOPSample.java
package com.aop;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
#Aspect
#Component
public class AOPSample {
#Before("execution(public void com.services.TaskService.startService())")
public void beforeSampleCreation() {
System.out.println("Hello world");
}
}
TaskService.java
package com.services;
public class TaskService {
public void startService(){
}
public void endService(){
}
}
Output:
In Greetings

Resources