AWS Lambda RequestHandler for a void output - java

Consider a simple Lambda written in Java:
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
public class Hello implements RequestHandler<Integer, String>{
public String handleRequest(int myCount, Context context) {
return String.valueOf(myCount);
}
}
The handler interface is defined as RequestHandler<InputType, OutputType>, but when my Lambda reacts to events and just does some side effects, is the output type unnecessary and I have to write something like this:
public class Hello implements RequestHandler<SNSEvent, Void>{
public Void handleRequest(SNSEvent snsEvent, Context context) {
...
return null;
}
}
Which is annoying.
Is there an alternative to RequestHandler for a void handler?:
public class Hello implements EventHandler<SNSEvent>{
public void handleEvent(SNSEvent snsEvent, Context context) {
...
}
}

You don't need to implement an interface for your Lambda entry point. Your handler class can just be a POJO with a signature that fulfils the requirements explained in the documentation.
For example:
package example;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.events.SNSEvent;
public class Hello {
public void handleEvent(SNSEvent event, Context context) {
// Process the event
}
}
In this case you should use example.Hello::handleEvent as the handler configuration.
See also this example from the official docs:
package example;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.LambdaLogger;
public class Hello {
public String myHandler(int myCount, Context context) {
LambdaLogger logger = context.getLogger();
logger.log("received : " + myCount);
return String.valueOf(myCount);
}
}

Related

How do I convert this test rule to JUnit5?

I have some custom rule using junit4 which I would like to convert to junit5. However I'm not able to find good documentation on migrating a MethodRule implementation other than that I should be using junit5 extension instead of rule.
public class MyRule implements MethodRule {
private static final Logger LOGGER = LoggerFactory.getLogger(MyRule.class);
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface MyAnnotation { }
#Override
public Statement apply(final Statement statement, final FrameworkMethod frameworkMethod, final Object o) {
Statement result = statement;
if (hasMyAnnotation(frameworkMethod)) {
result = new Statement() {
#Override
public void evaluate() {
LOGGER.info("Skipping test");
}
};
}
}
return result;
}
private static boolean hasMyAnnotation(final Annotatable frameworkMethod) {
return frameworkMethod.getAnnotation(MyAnnotation.class) != null;
}
My class is using junit4 Statement, FrameworkMethod etc to find out if my method has an annotation... then to skip it. How can I convert this?
Solution 1, Disable test with custom annotation
JUnit 5 provides a type of extension that can control whether or not a test should be run. This is defined by implementing the ExecutionCondition interface.
Extension implementation:
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
import org.junit.jupiter.api.extension.ExecutionCondition;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.platform.commons.logging.Logger;
import org.junit.platform.commons.logging.LoggerFactory;
import org.junit.platform.commons.util.AnnotationUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
public class SkipConditionExtension implements ExecutionCondition {
private static final Logger LOGGER = LoggerFactory.getLogger(SkipConditionExtension.class);
#Override
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
AnnotatedElement element = context.getElement().orElse(null);
if (hasMyAnnotation(element, MyAnnotation.class)) {
LOGGER.info(() ->"Skipping test");
return ConditionEvaluationResult.disabled(String.format("Skipped test: %s by #MyAnnotation", element));
}
return ConditionEvaluationResult.enabled("Test enabled");
}
private <T extends Annotation> boolean hasMyAnnotation(final AnnotatedElement element, Class<T> annotation) {
return element != null && AnnotationUtils.findAnnotation(element, annotation).isPresent();
}
}
Registring extenssion:
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
#ExtendWith(SkipConditionExtension.class)
public class TestObject {
#Test
public void test1() {
}
#Test
#MyAnnotation
public void test2() {
}
}
Output:
INFO: Skipping test
Skipped test: public void com.test.TestObject.test2() by #MyAnnotation
Solution 2, Skip test via invocation interseptor
InvocationInterceptor iterface defines the API for Extensions that wish to intercept calls to test.
Current implementation will behave exactly like your previous Rule.
Extension implementation:
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.InvocationInterceptor;
import org.junit.jupiter.api.extension.ReflectiveInvocationContext;
import org.junit.platform.commons.logging.Logger;
import org.junit.platform.commons.logging.LoggerFactory;
import org.junit.platform.commons.util.AnnotationUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
public class SkipCondition implements InvocationInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(SkipConditionExtension.class);
#Override
public void interceptTestMethod(Invocation<Void> invocation, ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
AnnotatedElement element = extensionContext.getElement().orElse(null);
if (hasMyAnnotation(element, MyAnnotation.class)) {
LOGGER.info(() ->"Skipping test");
invocation.skip();
} else {
invocation.proceed();
}
}
private <T extends Annotation> boolean hasMyAnnotation(final AnnotatedElement element, Class<T> annotation) {
return element != null && AnnotationUtils.findAnnotation(element, annotation).isPresent();
}
}
Registring extenssion:
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
#ExtendWith(SkipCondition.class)
public class TestObject {
#Test
public void test1() {
}
#Test
#MyAnnotation
public void test2() {
}
}
Please note, you can perform automatic extension registration according to documentation.

How to create bean with custom BeanName in Spring?

Problem
There is a Processor class which processes something based on its typesToProcess:
import org.springframework.stereotype.Component;
#Component
public class Processor {
private String typesToProcess;
public Processor(String typesToProcess) {
this.typesToProcess = typesToProcess;
}
public void process(String type) {
if (typesToProcess.equals(type)) {
// process
}
}
}
I need to create some Processor instances to work at different places. The problem is I don't know how many Processor instances should be created when the Spring Application is bootstrapping, as well as their 'typesToProcess'. Further more, the number of Processor instances might change when the application is running. I need to read the types from some configuration file which is stored in database periodically.
Attempts
One way to solve this problem I can thing out is using typesToProcess + Processor as the bean name, though I know it wont work. Is there any other way?
import com.meituan.picture.selection.processor.impl.Processor;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class ProcessorContainer implements ApplicationContextAware {
private ApplicationContext applicationContext;
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public Processor getProcessor(String type) {
String realBeanName = "processor" + type;
// obviouslly this wont work
return applicationContext.getBean(realBeanName, Processor.class);
}
}
I solved similar kind of problem by specifying scope of my bean as prototype without using bean name. Below example explains my implementation:
Create your Processor class as shown below:
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import lombok.Getter;
import lombok.Setter;
#Component
#Getter
#Setter
#Scope("prototype")
public class Processor {
private String typesToProcess;
public Processor(String typesToProcess) {
this.typesToProcess = typesToProcess;
}
public void process(String type) {
if (typesToProcess.equals(type)) {
// process
}
}
}
Implement ApplicationContextAware to generate beans at runtime:
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
#Service
public class ApplicationContextAwareImpl implements ApplicationContextAware {
private static ApplicationContext context;
#Override
public void setApplicationContext(ApplicationContext applicationContext) {
ApplicationContextAwareImpl.initApplicationContext(applicationContext);
}
private static void initApplicationContext(ApplicationContext applicationContext) {
ApplicationContextAwareImpl.context = applicationContext;
}
public static <T> T getBean(Class<T> requiredType) {
return context.getBean(requiredType);
}
public static Processor getProcessor(String typesToProcess) {
Processor processor = ApplicationContextAwareImpl.getBean(Processor.class);
processor.setTypesToProcess(typesToProcess);
return processor;
}
}
Use ApplicationContextAwareImpl.getProcessor() method to generate beans programmatically:
Processor type1Processor = ApplicationContextAwareImpl.getProcessor("type1");

Why class name is same as class used in import statement

Below snippet of code is from ITDIAgentException.java file
Can some one help me understand "why class name is same as class used in import statement"(ITDIAgentException)
import com.ibm.di.entry.Entry;
import com.ibm.di.exception.ITDIAgentException;
public class ITDIAgentException extends Exception {
private Entry entry = null;
public ITDIAgentException(String paramString) { super(paramString); }
public Entry getEntry() { return this.entry; }
public void setEntry(Entry paramEntry) { this.entry = paramEntry; }
}
EDIT
You have ITDIAgentException twice: Once in the import statement, and once in the class definition. You are not allowed to have both (would create a namespace clash in the code), but you can access com.ibm.di.exception.ITDIAgentException (assuming that it is different from the class you are creating) by using the full package and class name.
import com.ibm.di.exception.ITDIAgentException;
public class ITDIAgentException extends Exception {

HK2 Factory invoked prior to Jersey filter when #Context is used for setter/field/constructor injection

I've been able to inject into my jersey resource from a filter as per How to inject an object into jersey request context?. This allows me to successfully inject into a method parameter:
#GET
public Response getTest(#Context MyObject myObject) { // this works
However, for setter/field/constructor injection, the HK2 Factory is invoked before the jersey filter, which means the provide() method returns null:
#Override
public MyObject provide() {
// returns null because the filter has not yet run,
// and the property has not yet been set
return (MyObject)context.getProperty("myObject");
}
Is there a way to define when the HK2 Factory will run so that it is invoke after the filter runs? If not, then the workaround is to define MyObject as an interface and define an additional implementation that takes a ContainerRequestContext in its constructor; any attempt to actually use the instance would then lazily delegate to the implementation that gets set on the ContainerRequestContext's property (presumably you wouldn't actually use the instance until after the filter runs -- at which point the property would be set).
But I would like to understand if it is possible to delay the point at which the HK2 Factory runs so that it runs after the filter (it already runs after the filter in the case of method parameter injection). If it is not possible, then I would like to understand if there is a fundamental reason why.
Oddly it only works for me with #PreMatching on the filter (which limits access to some things you may or may not need). Not quite sure what's going on under the hood, that cause it not to work without it :-(. Below is a complete test using Jersey Test Framework.
import java.io.IOException;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import javax.ws.rs.ext.Provider;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.process.internal.RequestScoped;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.internal.inject.AbstractContainerRequestValueFactory;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Assert;
import org.junit.Test;
public class FilterInjectionTest extends JerseyTest {
private static final String MESSAGE = "Inject OK";
private static final String OBJ_PROP = "myObject";
public static class MyObject {
private final String value;
public MyObject(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
#PreMatching
#Provider
public static class MyObjectFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext context) throws IOException {
MyObject obj = new MyObject(MESSAGE);
context.setProperty(OBJ_PROP, obj);
}
}
public static class MyObjectFactory
extends AbstractContainerRequestValueFactory<MyObject> {
#Override
#RequestScoped
public MyObject provide() {
return (MyObject) getContainerRequest().getProperty(OBJ_PROP);
}
#Override
public void dispose(MyObject t) {
}
}
#Path("method-param")
public static class MethodParamResource {
#GET
public String getResponse(#Context MyObject myObject) {
return myObject.getValue();
}
}
#Path("constructor")
public static class ConstructorResource {
private final MyObject myObject;
#Inject
public ConstructorResource(#Context MyObject myObject) {
this.myObject = myObject;
}
#GET
public String getResponse() {
return myObject.getValue();
}
}
#Path("field")
public static class FieldResource {
#Inject
private MyObject myObject;
#GET
public String getResponse() {
return myObject.getValue();
}
}
#Override
public Application configure() {
ResourceConfig config = new ResourceConfig();
config.register(MethodParamResource.class);
config.register(MyObjectFilter.class);
config.register(ConstructorResource.class);
config.register(FieldResource.class);
config.register(new AbstractBinder() {
#Override
protected void configure() {
bindFactory(MyObjectFactory.class)
.to(MyObject.class).in(Singleton.class);
}
});
return config;
}
#Test
public void methoParamInjectionOk() {
String response = target("method-param").request().get(String.class);
Assert.assertEquals(MESSAGE, response);
System.out.println(response);
}
#Test
public void costructorInjectionOk() {
String response = target("constructor").request().get(String.class);
Assert.assertEquals(MESSAGE, response);
System.out.println(response);
}
#Test
public void fieldInjectionOk() {
String response = target("field").request().get(String.class);
Assert.assertEquals(MESSAGE, response);
System.out.println(response);
}
}
UPDATE
The solution, without having to make it a #PreMatching filter, is to inject with javax.inject.Provider. This will allow you to lazily retrieve the object. I guess what happens with the constructor and field injection is that right after matching the resource class, it it immediately created and injected. Because the filter hasn't been called yet, there is no object for the factory. It works for the method injection, because it is just like any other method call. The object is passed to it when the method is called. Below is the example with the javax.inject.Provider
#Path("constructor")
public static class ConstructorResource {
private final javax.inject.Provider<MyObject> myObjectProvider;
#Inject
public ConstructorResource(javax.inject.Provider<MyObject> myObjectProvider) {
this.myObjectProvider = myObjectProvider;
}
#GET
public String getResponse() {
return myObjectProvider.get().getValue();
}
}
#Path("field")
public static class FieldResource {
#Inject
private javax.inject.Provider<MyObject> myObjectProvider;;
#GET
public String getResponse() {
return myObjectProvider.get().getValue();
}
}

Guice Injection into Google Cloud Endpoints Transformer

I have a Google Cloud Endpoints application successfully working with Guice.
I wish to inject a Singleton into an Api Transformer.
Let's say I wish to transform Something into SomethingElse, where Something declares it's transformer to be:
import com.google.api.server.spi.config.Transformer;
import com.google.inject.Inject;
import com.google.inject.Singleton;
#Singleton
public class MyApiTransformer
implements Transformer<Something, SomethingElse> {
private MySingleton singleton;
#Inject
public MyApiTransformer(MySingleton singleton) {
this.singleton = singleton;
}
#Override
public Something transformFrom(SomethingElse somethingElse) {
return singleton.something(somethingElse);
}
#Override
public SomethingElse transformTo(Something something) {
return singleton.somethingElse(something);
}
}
Notice that I wish to delegate transformation to my Guice singleton. When I try the above transformer I get the following error:
java.io.IOException: com.google.appengine.repackaged.org.codehaus.jackson.map.JsonMappingException: Failed to instantiate custom serializer MyApiTransformer, constructors not found: [(interface java.lang.reflect.Type), (class java.lang.Class), ()]
It seems that Guice is not providing the ApiTransformers so Jackson does not know how to instantiate the class without a default constructor.
How can Guice inject the Singleton into the ApiTransformer?
Give your Transformer a default constructor and do static Injection:
import com.google.api.server.spi.config.Transformer;
import com.google.inject.Inject;
public class MyApiTransformer
implements Transformer<Something, SomethingElse> {
#Inject
private static MySingleton singleton;
public MyApiTransformer() {
}
#Override
public Something transformFrom(SomethingElse somethingElse) {
return singleton.something(somethingElse);
}
#Override
public SomethingElse transformTo(Something something) {
return singleton.somethingElse(something);
}
}
in your Module:
public class MyModule
extends AbstractModule {
#Override
protected void configure() {
requestStaticInjection(MyApiTransformer.class);
}
}

Categories