I am using the AspectJ Maven plugin to build my project and use an AspectLibrary, which is a jar in which I have my aspects defined.
Here is the Aspect that I am trying to use
#Around("execution(* *(..))&&#annotation(com.cisco.commerce.pricing.lp.commons.util.annotations.TimeMe)")
public Object timeMeAroundAspect(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {// NOSONAR
Timer timer = Timer.instance().start();
MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
Method method = signature.getMethod();
TimeMe timeMeAnnotation = method.getAnnotation(TimeMe.class);
String name = timeMeAnnotation.name();
boolean log = timeMeAnnotation.log();
boolean addToMetrics = timeMeAnnotation.addToMetrics();
Object response = null;
try {
response = proceedingJoinPoint.proceed();
} finally {
try {
Long timeTaken = timer.timeTaken();
if (log) {
LOGGER.info("MethodName: {} Time taken: {}", name, timeTaken);
}
if (addToMetrics) {
ExecutionDetailsUtil.addMethodExecutionTime(name, timeTaken);
}
} catch (Exception e) {
LOGGER.warn("Exception while trying to log time", e);
}
}
return response;
}
This code is in a jar file, which I am using as the aspectLibrary in my pom
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<showWeaveInfo>true</showWeaveInfo>
<verbose>true</verbose>
<encoding>UTF-8</encoding>
<source>${java.source-target.version}</source>
<target>${java.source-target.version}</target>
<Xlint>ignore</Xlint>
<aspectLibraries>
<aspectLibrary>
<groupId>it.cvc.ciscocommerce.lps.lp-commons</groupId>
<artifactId>lp-commons</artifactId>
</aspectLibrary>
</aspectLibraries>
<complianceLevel>${java.source-target.version}</complianceLevel>
</configuration>
<executions>
<execution>
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
Below is my annotation defintion
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface TimeMe {
public String name();
public boolean log() default true;
public boolean addToMetrics() default true;
}
Here is the snippet where I am trying to use this annotation (in a different code base which uses the above jar as a dependency)
#TimeMe(name = "classifyLine")
private void classifyLine(PricingObject pricingObject,
PricingLineObject pricingLineObject, LineTypes lineTypes) {
//logic
}
My build runs fine and prints the following in the MAVEN Console
[INFO] Join point 'method-execution(void com.cisco.pricing.lps.main.ListPriceService.classifyLine(com.cisco.pricing.lps.bean.PricingObject, com.cisco.pricing.lps.bean.PricingLineObject, com.cisco.pricing.lps.dto.LineTypes))' in Type 'com.cisco.pricing.lps.main.ListPriceService' (ListPriceService.java:235) advised by around advice from 'com.cisco.commerce.pricing.lp.commons.util.logging.LoggingAspectDefiner' (lp-commons-2019.03.01-SNAPSHOT.jar!LoggingAspectDefiner.class(from LoggingAspectDefiner.java))
I exploded the war file and looked at the class files generated. I have the following AjcClosure1 class generated for the java file where I used the annotation.
public class ListPriceService$AjcClosure1 extends AroundClosure {
public Object run(Object[] paramArrayOfObject) {
Object[] arrayOfObject = this.state;
ListPriceService.classifyLine_aroundBody0((ListPriceService)
arrayOfObject[0],
(PricingObject)arrayOfObject[1],
(PricingLineObject)arrayOfObject[2], (LineTypes)arrayOfObject[3],
(JoinPoint)arrayOfObject[4]);return null;
}
public ListPriceService$AjcClosure1(Object[] paramArrayOfObject)
{
super(paramArrayOfObject);
}
}
And in the java class file, where I use the annotation, I see no changes to the classifyLine method.
However, when I run my application, the annotation is not working. It doesn't execute the Aspect I have defined in the jar.
I have no clue why. Is my pattern not matching? It matches and works fine in a Spring application but not in this non Spring application.
Related
I am learning to do unit and double tests with Junit and the Mockito framework, but I am not getting the expected result in a specific test with 'mocks'. I do an assertThat that should return positive test, instead, it returns an error that says Mockito cannot mock this class. It is a class called 'Console' that must print and collect values from the user's keyboard, but of course, in unit tests this should be 'mocked' to avoid 'intervening test' in antipattern, where the test asks for data to the developer, that is, I need to 'mock up' a user input. This 'Console' class is like a small facade of the typical java BufferedReader class.
I pass you the classes involved:
Console:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Console {
private BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
public String readString(String title) {
String input = null;
boolean ok = false;
do {
this.write(title);
try {
input = this.bufferedReader.readLine();
ok = true;
} catch (Exception ex) {
this.writeError("characte string");
}
} while (!ok);
return input;
}
public int readInt(String title) {
int input = 0;
boolean ok = false;
do {
try {
input = Integer.parseInt(this.readString(title));
ok = true;
} catch (Exception ex) {
this.writeError("integer");
}
} while (!ok);
return input;
}
public char readChar(String title) {
char charValue = ' ';
boolean ok = false;
do {
String input = this.readString(title);
if (input.length() != 1) {
this.writeError("character");
} else {
charValue = input.charAt(0);
ok = true;
}
} while (!ok);
return charValue;
}
public void writeln() {
System.out.println();
}
public void write(String string) {
System.out.print(string);
}
public void writeln(String string) {
System.out.println(string);
}
public void write(char character) {
System.out.print(character);
}
public void writeln(int integer) {
System.out.println(integer);
}
private void writeError(String format) {
System.out.println("FORMAT ERROR! " + "Enter a " + format + " formatted value.");
}
}
ConsoleTest:
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import java.io.BufferedReader;
import java.io.IOException;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.*;
import static org.mockito.MockitoAnnotations.initMocks;
public class ConsoleTest {
#Mock
private BufferedReader bufferedReader;
#InjectMocks
private Console console;
#BeforeEach
public void before(){
initMocks(this);
//this.console = new Console();
}
#Test
public void givenConsoleWhenReadStringThenValue() throws IOException {
String string = "yes";
when(this.bufferedReader.readLine()).thenReturn(string);
assertThat(this.console.readString("title"), is(string));
}
}
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
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>
<modules>
</modules>
<artifactId>solution.java.swing.socket.sql</artifactId>
<groupId>usantatecla.tictactoe</groupId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>${project.groupId}.${project.artifactId}</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.6.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>3.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>3.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
<version>2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.3</version>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>default-report</id>
<phase>post-integration-test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<dependencies>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>1.2.0</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.22.2</version>
<dependencies>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>1.2.0</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Thanks and greetings to the community!
I personally am not a huge fun of Mockito, I prefer to have full control of my classes using an interface and two implementations (one for production and one for test).
So this doesn't respond directly to your question about Mockito but it allows you to perfectly control the behaviour of your code without the need to use another framework.
You may define a very simple interface:
public interface Reader {
String readLine();
}
Then, you use that interface in your class Console:
public class Console {
private final Reader reader;
public Console(Reader reader) {
this.reader = reader;
}
//Replace all your this.bufferedReader.readLine() by this.reader.readLine();
}
So, in your production code you can use the real implementation with the Buffered reader:
public class ProductionReader implements Reader {
private final BufferedReader bufferedReader = new BufferedReader(...);
#Override
public String readLine() {
this.bufferedReader.readLine();
}
}
Console console = new Console(new ProductionReader());
... While in your tests you can use a test implementation:
public class TestReader implements Reader {
#Override
public String readLine() {
return "Yes";
}
}
Console console = new Console(new TestReader());
Note that while in your specific case you may mock the behaviour using Mockito, there are a lot of other cases when you will need a more complex approach and the a ove will allow you to have full control and full debuggability of your code without the need of adding any dependency.
I am getting below error when aspectj compiler runs.
[ERROR] Type mismatch: cannot convert from List<Object> to List<Tag>
My code is,
final List<Tag> customTags =
pathVariables.entrySet().stream().filter(entry -> {
return tagList.contains(entry.getKey());
}).map(tag -> {
return new Tag() {
#Override
public String getValue() {
logger.info("Key for the attached tag is: {}",
tag.getKey());
return tag.getKey();
}
#Override
public String getKey() {
logger.info("Value for the attached tag is: {}", (String)tag.getValue());
return (String) tag.getValue();
}
};
}).collect(Collectors.toList());
pom.xml
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.7</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.8.7</version>
</dependency>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.8</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<complianceLevel>1.8</complianceLevel>
<encoding>UTF-8</encoding>
<verbose>true</verbose>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal> <!-- use this goal to weave all your main classes -->
<goal>test-compile</goal> <!-- use this goal to weave all your test classes -->
</goals>
</execution>
</executions>
</plugin>
Things that I have tried,
1. Adding properties so as to tell maven compiler plugin to comply with java 8
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>
Changing AspectJ version to 1.8.13
In both of the cases I got same error. If I use,
final List customTags = ...
with the same code I do not get this error. Am I missing anything?
Tried running dummy code of similar structure,
Map<String, Object> HOSTING1 = new HashMap<>();
HOSTING1.put("1", "linode.com");
HOSTING1.put("2", "heroku.com");
HOSTING1.put("3", "digitalocean.com");
HOSTING1.put("4", "aws.amazon.com");
List<String> tagList = Arrays.asList("1", "2", "3");
final List<Tag> customTags = HOSTING1.entrySet().stream().filter(entry -
> {
return tagList.contains(entry.getKey());
}).map(tag -> {
return new Tag() {
#Override
public String getValue() {
System.out.println("Value for the attached tag is: {}" + tag.getValue());
return (String) tag.getValue();
}
#Override
public String getKey() {
System.out.println("Key for the attached tag is: {}" + tag.getKey());
return (String) tag.getKey();
}
};
}).collect(Collectors.toList());
Explicitly specifying .map(tag -> {... helped! Without that AspectJ compiler was causing the issue. Code is,
final List<Tag> customTags =
pathVariables.entrySet().stream().filter(entry -> {
return tagList.contains(entry.getKey());
}).<Tag>map(tag -> {
return new Tag() {
#Override
public String getValue() {
logger.info("Key for the attached tag is: {}",
tag.getKey());
return tag.getKey();
}
#Override
public String getKey() {
logger.info("Value for the attached tag is: {}", (String)tag.getValue());
return (String) tag.getValue();
}
};
}).collect(Collectors.toList());
I would like to run a Main class with exec-maven-plugin and from my dependencies generate documentation like a swagger file.
The annotation that I care is javax.ws.rs.Path which has #Retention(RetentionPolicy.RUNTIME)
My Java code
public class ContextClassReader extends ClassReader {
private static final ExtensibleClassLoader CLASS_LOADER = new ExtensibleClassLoader();
public ContextClassReader(final String className) throws IOException {
super(CLASS_LOADER.getResourceAsStream(className.replace('.', '/') + ".class"));
final URL resource = CLASS_LOADER.getResource(className.replace('.', '/') + ".class");
}
public static ClassLoader getClassLoader() {
return CLASS_LOADER;
}
public static void addClassPath(final URL url) {
CLASS_LOADER.addURL(url);
}
private static class ExtensibleClassLoader extends URLClassLoader {
ExtensibleClassLoader() {
super(new URL[]{});
}
#Override
public void addURL(final URL url) {
super.addURL(url);
}
}
Here is the loading of class and testing it for annotations.
final Class<?> clazz = ContextClassReader.getClassLoader().loadClass(className);
isAnnotationPresent(clazz);
public static boolean isAnnotationPresent(final AnnotatedElement annotatedElement) {
... annotatedElement.getAnnotations().length --> 0
... clazz.getMethods().length() ---> works !
}
My pom.xml
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>java</executable>
<workingDirectory>XXXXXXXXXXXXXXXXXXX</workingDirectory>
<addResourcesToClasspath>true</addResourcesToClasspath>
<additionalClasspathElements>true</additionalClasspathElements>
<includeProjectDependencies>true</includeProjectDependencies>
<includePluginDependencies>true</includePluginDependencies>
<includeProjectDependencies>true</includeProjectDependencies>
<mainClass>XXX.Main</mainClass>
</configuration>
</plugin>
I am new to AWS and I am currently trying to understand Lambda functions and to trigger it when I upload file to S3 bucket.
I wrote a handler class for this:
public class Hello implements RequestHandler<Employee, String> {
public String handleRequest(Employee input, Context context) {
context.getLogger().log("helloWorld");
return "Hello World " ;
}
}
This was just a basic and I could see the "helloworld" printed in logs in CloudWatch when I upload a file to S3 bucket.
But Now what I want to log the metadata of the file (fileName, createdTime etc.).
I went thru a sample template example in AWS Lambda page, where I can see using Nodejs, we have the event as the argument and we can extract the name and other fields using this field.
const aws = require('aws-sdk');
const s3 = new aws.S3({ apiVersion: '2006-03-01' });
exports.handler = (event, context, callback) => {
const bucket = event.Records[0].s3.bucket.name;
...
}
But as a Java developer, I tried to use S3EventNotification as the argument:
public class Hello implements RequestHandler<S3EventNotification, String> {
public String handleRequest(S3EventNotification input, Context context) {
context.getLogger().log(input.getRecords().get(0).getEventSource());
return "Hello World " ;
}
}
But I am getting below error:
An error occurred during JSON parsing: java.lang.RuntimeException
java.lang.RuntimeException: An error occurred during JSON parsing
Caused by: lambdainternal.util.ReflectUtil$ReflectException: java.lang.NoSuchMethodException: com.amazonaws.services.s3.event.S3EventNotification$S3ObjectEntity.<init>(java.lang.String, java.lang.Long, java.lang.String, java.lang.String)
Caused by: java.lang.NoSuchMethodException: com.amazonaws.services.s3.event.S3EventNotification$S3ObjectEntity.<init>(java.lang.String, java.lang.Long, java.lang.String, java.lang.String)
How can I achieve the same thing in Java? Thanks.
Try some variant of the following:
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.S3Event;
public class Hello implements RequestHandler<S3Event, Void> {
#Override
public Void handleRequest(S3Event s3event, Context context) {
try {
S3EventNotificationRecord record = s3event.getRecords().get(0);
String bkt = record.getS3().getBucket().getName();
String key = record.getS3().getObject().getKey().replace('+', ' ');
key = URLDecoder.decode(key, "UTF-8");
} catch (Exception e) {
// do something
}
return null;
}
}
And here are the corresponding dependencies that I used in pom.xml:
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>1.11.228</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
<version>2.0.1</version>
</dependency>
And here is the build specification from my pom.xml (which will cause dependent classes to be pulled into my built JAR):
<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>
</execution>
</executions>
</plugin>
</plugins>
</build>
None of this is very simple, unfortunately, but that's Java and Maven for you. AWS Lambda programming in Node.js or Python is much simpler (and more fun) than in Java, so if there's no strong requirement to write it in Java, you're better off not writing in Java.
Also note that if the Lambda is going to be invoked asynchronously then the output type should be Void rather than String (see docs).
I have resource class which itself's talks with a internal service. This resource acts a rest API for the service. The service layer can throw unexpected exceptions, thus the resource should handle those handled unexpected exceptions and log it. I am using dropwizard framework which in turns use jersey. It goes like this.
#PATH(/user)
#GET
public Response getUser(#QueryParam("id") String userId) {
assertNotNull(userId);
try {
User user = service.getUser(userId);
return Response.ok(user).build();
}
catch (MyOwnException moe) { //basically 400's
return Response.status(400).entity(moe.getMsg()).build();
}
catch (Exception e) { //unexpected exceptions
logger.debug(e.getMessage);
return Response.status(500).entity(moe.getMsg()).build();
}
}
The problem here is that i have to do this exact same exception handling for each REST api endpoint. Can i do some kind of exception mapping for this particular resource so that i can put all the handling logic and logging there?
I know i can build a mapper for an particular exception in jersey, but that is for the whole module not a single class.
Afaig you can't register an ExceptionMapper to a resource method. I've tried this by implementing a DynamicFeature which was looking for a custom Annotation and then tried to register a custom ExceptionMapper with the FeatureContext.
The result was disillusioning:
WARNING: The given contract (interface javax.ws.rs.ext.ExceptionMapper) of class path.to.CustomExceptionMapper provider cannot be bound to a resource method.
Might not work:
But...
For a resource class this is in fact easy. Just register your ExceptionMapper for your resource class within your ResourceConfig. For me it looks like:
#ApplicationPath("/")
public class ApplicationResourceConfig extends ResourceConfig {
public ApplicationResourceConfig() {
// [...]
register(YourExceptionMapper.class, YourResource.class);
// [...]
}
}
So if you are okay with having this on resource class level, do it like this.
Otherwise you might need to use Aspects (but I don't see any reasons to do so). Example:
Aspect
#Aspect
public class ResourceAspect {
Logger logger = [...]
private static final String RESOURCE = "execution(public !static javax.ws.rs.core.Response path.to.resources..*(..)) && #annotation(path.to.HandleMyOwnException)";
#Around(RESOURCE)
public Object translateRuntimeException(ProceedingJoinPoint p) throws Throwable {
try {
return p.proceed();
} catch (MyOwnException moe) {
return Response.status(400).entity(moe.getMsg()).build();
} catch (Exception e) { //unexpected exceptions
logger.debug(e.getMessage);
return Response.status(500).entity(e.getMessage()).build();
}
}
}
Please notice, the RESOURCE config. Here it works for none static methods under path.to.resources which returning Response and are anntotated with the HandleMyOwnException annotation.
HandleMyOwnException
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface HandleMyOwnException {}
ResourceMethod
#GET
#PATH("/user")
#HandleMyOwnException
public Response getUser(#QueryParam("id") String userId) {
assertNotNull(userId);
return Response.ok(service.getUser(userId)).build();
}
pom.xml
<!-- deps -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.2</version> <!-- or newer version -->
</dependency>
<!-- build plugins -->
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<showWeaveInfo>true</showWeaveInfo>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<versionRange>[1.7,)</versionRange>
<goals>
<goal>compile</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
<plugins>
<pluginManagement>
Have a nice day!
EDITED
~ Added more complete pom.xml config
~ Corrected missing path for Annotation in ResourceAspect
Why not just factor out the exception handling into a private method?
#PATH(/user)
#GET
public Response getUser(#QueryParam("id") String userId) {
assertNotNull(userId);
return handleExceptions(() -> {
User user = service.getUser(userId);
return Response.ok(user).build();
});
}
private Response handleExceptions(Callable<Response> callable) {
try {
return callable.call();
}
catch (MyOwnException moe) { //basically 400's
return Response.status(400).entity(moe.getMsg()).build();
}
catch (Exception e) { //unexpected exceptions
logger.debug(e.getMessage);
return Response.status(500).entity(e.getMessage()).build();
}
}