Skip to content
This repository was archived by the owner on Oct 8, 2023. It is now read-only.

Commit 25fdfbb

Browse files
committed
Improve error handling for service injection
1 parent b5a8c0d commit 25fdfbb

File tree

11 files changed

+226
-2
lines changed

11 files changed

+226
-2
lines changed

src/main/java/com/github/kaklakariada/aws/lambda/RequestHandlingService.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ public static <P extends ServiceParams> RequestHandlingService create(LambdaCont
6565
serviceFactory);
6666
listeners.add(serviceParamsSupplier);
6767
final Injector<P> injector = new Injector<>(new ServiceCache<>(serviceFactory), serviceParamsSupplier);
68+
LOG.debug("Injecting services into controller {} using service factory {}", controller, serviceFactory);
6869
injector.injectServices(controller);
70+
} else {
71+
LOG.debug("No service factory available, don't inject services");
6972
}
7073
final ObjectMapper objectMapper = createObjectMapper();
7174
final ControllerAdapter adapter = ControllerAdapter.create(objectMapper, controller);
@@ -102,7 +105,7 @@ private ApiGatewayResponse handleRequest(final ApiGatewayRequest request, Contex
102105
final String responseBody = serializeResult(result);
103106
return ApiGatewayResponse.ok(responseBody);
104107
} catch (final LambdaException e) {
105-
LOG.error("Error processing request: {}", e.getMessage());
108+
LOG.error("Error processing request: {}", e.getMessage(), e);
106109
return buildErrorResponse(e, context);
107110
} catch (final Exception e) {
108111
LOG.error("Error processing request: " + e.getMessage(), e);

src/main/java/com/github/kaklakariada/aws/lambda/inject/Injector.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,17 @@
2525

2626
import javax.inject.Inject;
2727

28+
import org.slf4j.Logger;
29+
import org.slf4j.LoggerFactory;
30+
2831
import com.github.kaklakariada.aws.lambda.controller.LambdaController;
2932
import com.github.kaklakariada.aws.lambda.exception.InternalServerErrorException;
3033
import com.github.kaklakariada.aws.lambda.service.ServiceCache;
3134
import com.github.kaklakariada.aws.lambda.service.ServiceParams;
3235

3336
public class Injector<P extends ServiceParams> {
37+
private static final Logger LOG = LoggerFactory.getLogger(Injector.class);
38+
3439
private final ServiceCache<P> cache;
3540
private final Supplier<P> serviceParams;
3641

@@ -42,15 +47,19 @@ public Injector(ServiceCache<P> cache, Supplier<P> serviceParams) {
4247
public void injectServices(LambdaController controller) {
4348
Arrays.stream(controller.getClass().getDeclaredFields())
4449
.filter(field -> field.getAnnotation(Inject.class) != null) //
45-
.filter(field -> field.getType().equals(Supplier.class)) //
4650
.forEach(field -> inject(controller, field));
4751
}
4852

4953
private void inject(LambdaController controller, Field field) {
54+
if (!field.getType().equals(Supplier.class)) {
55+
throw new IllegalStateException("Field " + field.getName() + " has unsupported type "
56+
+ field.getType().getName() + ", only Supplier is supported");
57+
}
5058
final ParameterizedType type = (ParameterizedType) field.getGenericType();
5159
assert type.getActualTypeArguments().length == 1;
5260
final Type typeToInject = type.getActualTypeArguments()[0];
5361
final Supplier<?> serviceSupplier = getServiceSupplier((Class<?>) typeToInject);
62+
LOG.debug("Injecting supplier of type {} into field {}", typeToInject.getTypeName(), field.getName());
5463
inject(controller, field, serviceSupplier);
5564
}
5665

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* aws-lambda-request-handler - Request handler for AWS Lambda Proxy model
3+
* Copyright (C) 2017 Christoph Pirkl <christoph at users.sourceforge.net>
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package com.github.kaklakariada.aws.lambda.example;
19+
20+
import javax.inject.Inject;
21+
22+
import com.github.kaklakariada.aws.lambda.controller.LambdaController;
23+
import com.github.kaklakariada.aws.lambda.controller.RequestHandlerMethod;
24+
25+
public class MyLambdaControllerWithUnsupportedServiceType implements LambdaController {
26+
27+
@Inject
28+
private MyServiceB serviceB;
29+
30+
@RequestHandlerMethod
31+
public String handleRequest() {
32+
return "Service B: " + serviceB.getValue();
33+
}
34+
}

src/test/java/com/github/kaklakariada/aws/lambda/inject/InjectorTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
*/
1818
package com.github.kaklakariada.aws.lambda.inject;
1919

20+
import static org.hamcrest.CoreMatchers.containsString;
2021
import static org.hamcrest.CoreMatchers.equalTo;
2122
import static org.hamcrest.MatcherAssert.assertThat;
2223
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -30,6 +31,7 @@
3031
import org.mockito.MockitoAnnotations;
3132

3233
import com.github.kaklakariada.aws.lambda.example.MyLambdaController;
34+
import com.github.kaklakariada.aws.lambda.example.MyLambdaControllerWithUnsupportedServiceType;
3335
import com.github.kaklakariada.aws.lambda.example.MyServiceB;
3436
import com.github.kaklakariada.aws.lambda.example.MyServiceParams;
3537
import com.github.kaklakariada.aws.lambda.service.ServiceCache;
@@ -79,6 +81,14 @@ public void testServiceInjectedIntoController() {
7981
assertThat(controller.handleRequest(), equalTo("Service B: " + VALUE2));
8082
}
8183

84+
@Test
85+
public void testUnsupportedServiceTypeInjected() {
86+
final IllegalStateException exception = assertThrows(IllegalStateException.class,
87+
() -> injector.injectServices(new MyLambdaControllerWithUnsupportedServiceType()));
88+
assertThat(exception.getMessage(), containsString(
89+
"Field serviceB has unsupported type com.github.kaklakariada.aws.lambda.example.MyServiceB, only Supplier is supported"));
90+
}
91+
8292
@Test
8393
public void testServiceParamsSupplierReturnsNull() {
8494
injector.injectServices(controller);

test-project/src/main/java/handler/echo/EchoHandler.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public EchoHandler() {
2020
}
2121

2222
public static class EchoController implements LambdaController {
23+
2324
@RequestHandlerMethod
2425
public EchoResponse handleRequest(@RequestBody EchoRequest body, Context context, ApiGatewayRequest request,
2526
@HeaderValue("User-Agent") String userAgent) {
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package handler.echo;
2+
3+
import java.util.function.Supplier;
4+
5+
import javax.inject.Inject;
6+
7+
import org.slf4j.Logger;
8+
import org.slf4j.LoggerFactory;
9+
10+
import com.github.kaklakariada.aws.lambda.LambdaRequestHandler;
11+
import com.github.kaklakariada.aws.lambda.controller.LambdaController;
12+
import com.github.kaklakariada.aws.lambda.controller.RequestHandlerMethod;
13+
import com.github.kaklakariada.aws.lambda.model.request.ApiGatewayRequest;
14+
15+
import handler.service.EchoServiceFactory;
16+
import handler.service.StageBasedEchoService;
17+
18+
public class ServiceBasedEchoHandler extends LambdaRequestHandler {
19+
20+
private static final Logger LOG = LoggerFactory.getLogger(ServiceBasedEchoHandler.class);
21+
22+
public ServiceBasedEchoHandler() {
23+
super(new ServiceBasedEchoController(), new EchoServiceFactory());
24+
}
25+
26+
public static class ServiceBasedEchoController implements LambdaController {
27+
@Inject
28+
private Supplier<StageBasedEchoService> echoService;
29+
30+
@RequestHandlerMethod
31+
public String echo(ApiGatewayRequest request) {
32+
LOG.info("Code uri: {}", echoService.get().getCodeUri());
33+
return echoService.get().echo(request.getPath());
34+
}
35+
}
36+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package handler.service;
2+
3+
import java.util.Map;
4+
5+
import com.github.kaklakariada.aws.lambda.model.request.ApiGatewayRequest;
6+
import com.github.kaklakariada.aws.lambda.service.ServiceFactory;
7+
import com.github.kaklakariada.aws.lambda.service.ServiceRegistry;
8+
9+
public class EchoServiceFactory implements ServiceFactory<EchoServiceParam> {
10+
11+
@Override
12+
public EchoServiceParam extractServiceParams(ApiGatewayRequest request, Map<String, String> env) {
13+
return new EchoServiceParam(request.getStageVariable("stage"), env.get("CODE_URI"));
14+
}
15+
16+
@Override
17+
public void registerServices(ServiceRegistry registry, EchoServiceParam params) {
18+
registry.addService(StageBasedEchoService.class,
19+
() -> new StageBasedEchoService(params.getStage(), params.getCodeUri()));
20+
}
21+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package handler.service;
2+
3+
import com.github.kaklakariada.aws.lambda.service.ServiceParams;
4+
5+
public class EchoServiceParam implements ServiceParams {
6+
private final String stage;
7+
private final String codeUri;
8+
9+
public EchoServiceParam(String stage, String codeUri) {
10+
this.stage = stage;
11+
this.codeUri = codeUri;
12+
}
13+
14+
public String getStage() {
15+
return stage;
16+
}
17+
18+
public String getCodeUri() {
19+
return codeUri;
20+
}
21+
22+
@Override
23+
public int hashCode() {
24+
final int prime = 31;
25+
int result = 1;
26+
result = prime * result + ((codeUri == null) ? 0 : codeUri.hashCode());
27+
result = prime * result + ((stage == null) ? 0 : stage.hashCode());
28+
return result;
29+
}
30+
31+
@Override
32+
public boolean equals(Object obj) {
33+
if (this == obj) {
34+
return true;
35+
}
36+
if (obj == null) {
37+
return false;
38+
}
39+
if (getClass() != obj.getClass()) {
40+
return false;
41+
}
42+
final EchoServiceParam other = (EchoServiceParam) obj;
43+
if (codeUri == null) {
44+
if (other.codeUri != null) {
45+
return false;
46+
}
47+
} else if (!codeUri.equals(other.codeUri)) {
48+
return false;
49+
}
50+
if (stage == null) {
51+
if (other.stage != null) {
52+
return false;
53+
}
54+
} else if (!stage.equals(other.stage)) {
55+
return false;
56+
}
57+
return true;
58+
}
59+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package handler.service;
2+
3+
public class StageBasedEchoService {
4+
private final String stage;
5+
private final String codeUri;
6+
7+
public StageBasedEchoService(String stage, String codeUri) {
8+
this.stage = stage;
9+
this.codeUri = codeUri;
10+
}
11+
12+
public String echo(String message) {
13+
return "Stage " + stage + ": " + message;
14+
}
15+
16+
public String getCodeUri() {
17+
return codeUri;
18+
}
19+
}

test-project/src/main/resources/log4j2.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@
1111
<Root level="info">
1212
<AppenderRef ref="Lambda" />
1313
</Root>
14+
<Logger name="com.github.kaklakariada" level="trace" />
1415
</Loggers>
1516
</Configuration>

0 commit comments

Comments
 (0)