0

I have to test/call Spring Boot Controllers in aws lamda locally. I am using "serverless" to locally

Here is my "RequestHandler"

public class ReqHandler 

implements RequestStreamHandler
{
    private static SpringBootLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;
    static {
        try {
            handler = SpringBootLambdaContainerHandler.getAwsProxyHandler(OrderManagementSystemApplication.class);
        } catch (Exception e) {
            // if we fail here. We re-throw the exception to force another cold start
            e.printStackTrace();
            throw new RuntimeException("Could not initialize Spring Boot application", e);
        }
    }

    private ApplicationContext getApplicationContext(String [] args) {
        return new SpringApplicationBuilder(OrderManagementSystemApplication.class)
                .run(args);
    }

    @Override
    public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
        handler.activateSpringProfiles("la");
        ApplicationContext app = getApplicationContext(new String[]{});
        OrderController orderController = app.getBean(OrderController.class);


        handler.proxyStream(inputStream, outputStream, context);
    }
}

but at line - "OrderController orderController = app.getBean(OrderController.class);"

I am getting below exception

java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at com.serverless.InvokeBridge.invoke(InvokeBridge.java:102)
        at com.serverless.InvokeBridge.<init>(InvokeBridge.java:40)
        at com.serverless.InvokeBridge.main(InvokeBridge.java:153)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.muqit.OMS.controller.OrderController' available
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:343)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:335)
        at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1123)
        at org.muqit.OMS.lamdas.ReqHandler.handleRequest(ReqHandler.java:51)
        ... 7 more

here is my Application.class.

@SpringBootApplication
@Configuration
@EnableAutoConfiguration
//@EnableJpaAuditing
@Profile("la")
@ComponentScan(basePackages = "org.muqit.OMS.controller")
public class OrderManagementSystemApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(OrderManagementSystemApplication.class, args);
    }


    @Bean
    public OMSServiceImpl getOMSService() {
        return new OMSServiceImpl();
    }
}

here is my POM,

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.1.RELEASE</version>
    </parent>
    <groupId>org.muqit.OMS</groupId>
    <artifactId>OrderManagementSystem</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>OrderManagementSystem</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
</dependency>

        <dependency>
    <groupId>com.amazonaws.serverless</groupId>
    <artifactId>aws-serverless-java-container-springboot2</artifactId>
    <version>1.4</version>
</dependency>

       </dependencies>

    <build>
        <plugins>

            <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.3</version>
            <configuration>
                <createDependencyReducedPom>false</createDependencyReducedPom>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <artifactSet>
                            <excludes>
                                <exclude>org.apache.tomcat.embed:*</exclude>
                            </excludes>
                        </artifactSet>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        </plugins>
    </build>






</project>

Please tell me if I am doing anything wrong or if there is any other approach we have to test/call restController locally using aws lambda serverless.

Farhan
  • 105
  • 1
  • 10
  • For starters use the `spring-boot-maven-plugin` to create a proper Spring Boot jar instaed of trying to use the shade plugin. – M. Deinum Sep 30 '19 at 08:43
  • I tried with it but got BELOW exception at my local console when tried to execute requestHadler through serverless -----> Java.lang.ClassNotFoundException: org.muqit.OMS.lamdas.ReqHandler at java.net.URLClassLoader.findClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Unknown Source) at com.serverless.InvokeBridge.getInstance(InvokeBridge.java:72) – Farhan Sep 30 '19 at 09:00
  • Without the plugin it won't create a valid Spring Boot application. Also `@Configuration` and `@EnableAutoConfiguration` isn't needed, that is implied by `@SpringBootApplication` already. You have an `@Profile` on your class make sure that that is active in your server less environment. Finally shouldn't you be using dependency injection instead of recreating the context (you are basically starting the application twice, which seems like overkill, especially in a server less environment). – M. Deinum Sep 30 '19 at 09:03
  • I removed Configuration and EnableAutoConfiguration and I am not sure what profile Annotation does I just put it to avoid lengthy error messages and I tried @Autowired OrderController oc; for dependency Injection but "oc" is always null in this case. Can you please sujjest me how can I inject dependency ? – Farhan Sep 30 '19 at 09:46
  • `@Profile` enables configuration ONLY when that profile is set. So basically currently you are running without any config. If you get an error the `@Profile` isn't the fix.Looking at the official documentation from AWS, they also use the shade plugin. Nonetheless you should only use the handler (from the documentation as well) to invoke the application. So what you are doing in your handler is something you shouldn't be doing in the first place. – M. Deinum Sep 30 '19 at 09:58
  • I have copied handler from https://github.com/awslabs/aws-serverless-java-container/wiki/Quick-start---Spring-Boot, What I just want is to call my controllers from handler but I am unable to do that. I there any way to do that ? – Farhan Sep 30 '19 at 10:26
  • No you didn't copy it, as that handler only passes along the input/output and context. It doesn't mess around with creating a context etc. – M. Deinum Sep 30 '19 at 10:27

0 Answers0