ObjectMapper breaking AWS Lambda via API Gateway - java

There is an API Gateway calling a lambda function using the lambda proxy.
The below works fine body is logged and body is sent back:
package com.dapper.cloud.function;
import java.util.Map;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
public class GrantJwt implements RequestHandler<Map<String, Object>, APIGatewayProxyResponseEvent>{
#Override
public APIGatewayProxyResponseEvent handleRequest(Map<String, Object> input, Context context){
System.out.println(input.get("body").toString());
return new APIGatewayProxyResponseEvent().withStatusCode(200).withBody(input.get("body").toString());
}
}
When I update it to use the ObjectMapper like so:
package com.dapper.cloud.function;
import java.util.Map;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import com.fasterxml.jackson.databind.ObjectMapper;
public class GrantJwt implements RequestHandler<Map<String, Object>, APIGatewayProxyResponseEvent>{
#Override
public APIGatewayProxyResponseEvent handleRequest(Map<String, Object> input, Context context){
ObjectMapper m = new ObjectMapper();
System.out.println(input.get("body").toString());
return new APIGatewayProxyResponseEvent().withStatusCode(200).withBody(input.get("body").toString());
}
}
The logs do not show the body and the response is:
{
"message": "Internal server error"
}
Can I use Jackson in AWS Lambda?
Parent POM
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
<version>2.2.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9</version>
</dependency>
</dependencies>
Child Build
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

Well as foolish but if this helps anyone I am very happy.
ObjectMapper is not the issue. I did a deployment with travis-ci a couple times and apparently when that happens if a memory_size and timeout is not set a default 128 mb and 3 second is used. This differs from the defaults of a new lambda which is 512 mb and 15 seconds.
I opened a request to change this on travis forum.

Related

AWS Lambda gives class not found exception for jdbc and org.json JARS

I'm trying to run an AWS Lambda function with the help of eclipse and Maven using AWS tool kit. When I run the project as a Maven test, it successfully runs. But when I export the project as a .jar and upload the jar to AWS Lambda, it gives me the following error trace:
Input: ToRupeeDatabase error: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
Done inserting the data in RDS
The code says it runs successfully and the data has been inserted in the RDS, but it is being caught as an exception and the code is crashing.
Code:
package com.amazonaws.torupee.demo;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import org.json.JSONObject;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.logging.Level;
import java.util.logging.Logger;
public class RemoteDataCRON implements RequestHandler<Object, String> {
#Override
public String handleRequest(Object input, Context context) {
context.getLogger().log("Input: " + input);
try {
// Exception in the following line when uploaded on AWS Lambda!
Class.forName("com.mysql.jdbc.Driver");
String endPoint = "pathtodatabase?useSSL=false";
String username = "foor";
String password = "bar";
PreparedStatement stmt = null;
try {
Connection dbConnection = DriverManager.getConnection(endPoint, username, password);
} catch (SQLException ex) {
Logger.getLogger(RemoteDataCRON.class.getName()).log(Level.SEVERE, null, ex);
}
// Some processing here and org.json exception here!
} catch (Exception ex) {
System.err.println("Database error: " + ex);
}
System.out.println("Done inserting the data in RDS");
// TODO: implement your handler
return "Hello from Lambda!";
}
}
.pom file:
<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>
<groupId>com.amazonaws.torupee</groupId>
<artifactId>demo</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<forceJavacCompilerUse>true</forceJavacCompilerUse>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-bom</artifactId>
<version>1.11.256</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180130</version>
</dependency>
</dependencies>
</project>
Here is a list of solutions that I tried:
I tried adding external JARS for mysql and org.json but that gave me the same errors
I tried zipping the project instead of exporting it as a JAR but that gave me ClassNotFoundException on the handler itself
I then added the dependencies in the pom file itself as I thought that external JARS were not bundled when making a .jar file
I then changed the driver path from "com.mysql.jdbc.Driver" to "com.mysql.cj.jdbc.Driver" but that still gave me the exception on the console
Am I doing something wrong or building the Jar incorrectly, is it why Lambda gives me the error when I'm on the management console?
So I solved this by completely ditching the maven approach and did it using a simple java class. You can follow the solution for creating a simple AWS Lambda function in java step by step with this video tutorial I created.
https://www.youtube.com/watch?v=-Pm22SJibpQ&t=40s

Pact File Not Generated Inspite of test being Passed

I am trying to generate Pact file.The test is passing when is "Run As-Junit Test" in Eclipse. However, unable to really understand why the Pact Contract File is not generated. Can you please help? Below is my test code:
package pact;
import au.com.dius.pact.consumer.*;
import au.com.dius.pact.consumer.dsl.DslPart;
import au.com.dius.pact.consumer.dsl.PactDslJsonBody;
import au.com.dius.pact.model.PactFragment;
import org.junit.Assert;
import au.com.dius.pact.consumer.dsl.PactDslWithProvider;
import au.com.dius.pact.consumer.dsl.PactDslWithState;
import org.junit.Rule;
import org.junit.Test;
import utils.Configuration;
import java.io.IOException;
import static org.junit.Assert.assertEquals;
public class GetHelloWorldTest
{
#Rule
public PactProviderRule rule = new PactProviderRule("PP Provider", "localhost", 9000, this);
private String helloWorldResults;
#Pact(provider = Configuration.DUMMY_PROVIDER,consumer = Configuration.DUMMY_CONSUMER)
public PactFragment createFragment(PactDslWithProvider builder)//TODO
{
return builder
.uponReceiving("get hello world response")
.path("/hello-world")
.method("GET")
.willRespondWith()
.status(200)
.body("{\"id\":2,\"content\":\"Hello, Stranger!\"}")
.toFragment();
}
#Test
#PactVerification(value = "PP provider")
public void shouldGetHelloWorld() throws IOException
{
DummyConsumer restClient = new DummyConsumer(Configuration.SERVICE_URL);
Assert.assertEquals("{\"id\":32,\"content\":\"Hello, Stranger!\"}",restClient.getHelloWorld());
}
}
My POM File is as below :
<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>
<groupId>consumer</groupId>
<artifactId>consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.3.9</version>
</dependency>
<dependency>
<groupId>org.apache.maven.reporting</groupId>
<artifactId>maven-reporting-impl</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>fluent-hc</artifactId>
<version>4.5.2</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>3.0.24</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8</version>
</dependency>
<dependency>
<groupId>au.com.dius</groupId>
<artifactId>pact-jvm-consumer-junit_2.10</artifactId>
<version>2.4.18</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.4.7</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.13</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18</version>
<configuration>
<systemPropertyVariables>
<pact.rootDir>PPPPP/pact</pact.rootDir>
<buildDirectory>${project.build.directory}</buildDirectory>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</project>
I had the same problem that my Pact file has not been generated in the folder that I specified in the maven-surfire-plugin.
However I realized that the file has been generated, but in the folder "target > pacts". To generate the file I just needed to execute the maven goal "mvn test".
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<pact.rootDir>src/test/resources/pacts</pact.rootDir>
<buildDirectory>${project.build.directory}</buildDirectory>
</systemPropertyVariables>
I have set the pact.rootDir like this but it always generates the pact contract in the target/pact folder so now I am taking it from there.
It would seem that you're missing your state specification in the createFragment function.
To fix it in your example, change your function to this:
#Pact(state = "PP provider", provider = Configuration.DUMMY_PROVIDER,consumer = Configuration.DUMMY_CONSUMER)
public PactFragment createFragment(PactDslWithProvider builder)
From here, the verification process will know to check for that state because of the name, verify it, then write the Pact file out under the pacts directory, which is the default.
Here's an example that works for me:
package pact;
import au.com.dius.pact.consumer.*;
import au.com.dius.pact.model.PactFragment;
import org.junit.Rule;
import org.junit.Test;
import utils.Configuration;
import java.io.IOException;
import static org.junit.Assert.assertEquals;
public class GetHelloWorldTest
{
#Rule
public PactRule rule = new PactRule(Configuration.MOCK_HOST, Configuration.MOCK_HOST_PORT, this);
private DslPart helloWorldResults;
#Pact(state = "HELLO WORLD", provider = Configuration.DUMMY_PROVIDER, consumer = Configuration.DUMMY_CONSUMER)
public PactFragment createFragment(ConsumerPactBuilder.PactDslWithProvider.PactDslWithState builder)
{
helloWorldResults = new PactDslJsonBody()
.id()
.stringType("content")
.asBody();
return builder
.uponReceiving("get hello world response")
.path("/hello-world")
.method("GET")
.willRespondWith()
.status(200)
.headers(Configuration.getHeaders())
.body(helloWorldResults)
.toFragment();
}
#Test
#PactVerification("HELLO WORLD")
public void shouldGetHelloWorld() throws IOException
{
DummyConsumer restClient = new DummyConsumer(Configuration.SERVICE_URL);
assertEquals(helloWorldResults.toString(), restClient.getHelloWorld());
}
}
Pact JVM appears to ignore the buildDirectory property
Try the following configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18</version>
<configuration>
<systemPropertyVariables>
<pact.rootDir>${project.build.directory}/pacts</pact.rootDir>
<buildDirectory>${project.build.directory}</buildDirectory>
</systemPropertyVariables>
</configuration>
</plugin>

Get client ip in Jersey 2.22.2

I am trying to access the clients IP that are calling my rest server but I only get null as a response. The web-server is running and I can access it from the web browser.
I have tried with
#Context HttpServletRequest
And also with
#Context ContainerRequest request
request.getRequestHeader("HTTP_FORWARDED")
//HTTP_X_FORWARDED
//HTTP_CLIENT_IP
But neither succeeds, the response is null or blank.
Setup
Jersey v: 2.22.2
Grizzly v: 2.3.22
Java v: 8
Rest.java
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.UriInfo;
#Path("/rest")
public class Rest {
#GET
#Path("/test/")
#Produces(MediaType.APPLICATION_JSON)
public TestAddress test(#Context HttpServletRequest re){
System.out.println(re.getRemoteAddr());
TestAddress adr = new TestAddress();
adr.setAge(32);
adr.setName("Fidde");
adr.setSurename("Lass");
//System.out.println(uriInfo.getBaseUri());
return adr;
}
main.java
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
import java.io.IOException;
import java.net.URI;
public class Main {
// Base URI the Grizzly HTTP server will listen on
public static final String BASE_URI = "http://localhost:8080/myapp/";
/**
* Starts Grizzly HTTP server exposing JAX-RS resources defined in this application.
* #return Grizzly HTTP server.
*/
public static HttpServer startServer() {
// create a resource config that scans for JAX-RS resources and providers
// in com.example package
final ResourceConfig rc = new ResourceConfig().packages("com.example");
// create and start a new instance of grizzly http server
// exposing the Jersey application at BASE_URI
return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
}
/**
* Main method.
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException {
final HttpServer server = startServer();
System.out.println(String.format("Jersey app started with WADL available at "
+ "%sapplication.wadl\nHit enter to stop it...", BASE_URI));
System.in.read();
server.stop();
}
}
Pom.xml
http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
Test
Bootstrap
jar
0.0.1-SNAPSHOT
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>backend.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.22.2</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.2.3</version>
<scope>compile</scope>
</dependency>
</dependencies>
<properties>
<jersey.version>2.22.2</jersey.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
HttpServletRequest provides a getRemoteAddr() method that should returns the remote IP address.
Note that proxying or NATing may modify the IP address.
EDIT :
The solution is to inject a grizzly request :
#GET
#Path("/test/")
#Produces(MediaType.APPLICATION_JSON)
public TestAddress test(#Context org.glassfish.grizzly.http.server.Request re) {
System.out.println(re.getRemoteAddr());
...
}
This is working for me, but it is totally grizzly dependant.

Accessing compiled resources in a Pax Exam contained test

I've been trying to run a JMH benchmark test in an OSGI container created with Pax Exam (similarly to how it's described in this SO answer, but with Pax Exam thrown into the mix as well). But am having some problems getting the JMH generated resource files created during the compilation to load.
After the tests have been compiled, the following can be found in the target/test-classes directory:
$ ls -l target/test-classes/META-INF
BenchmarkList CompilerHints
In a test I use some code (that I cannot change) that (effectively) looks for the file like so:
getClass().getClassLoader().getResources("META-INF/BenchmarkList");
Running this fails (returns 0 results) and I get the following error:
java.lang.RuntimeException: ERROR: Unable to find the resource: /META-INF/BenchmarkList
at org.openjdk.jmh.runner.AbstractResourceReader.getReaders(AbstractResourceReader.java:96)
at org.openjdk.jmh.runner.BenchmarkList.find(BenchmarkList.java:104)
at org.openjdk.jmh.runner.Runner.internalRun(Runner.java:228)
at org.openjdk.jmh.runner.Runner.run(Runner.java:178)
at com.company.project.performance.MyBenchmarkTest.launchBenchmark(MyBenchmarkTest.java:145)
I've tried creating a bundle containing the file, like so:
streamBundle(bundle()
.add("META-INF/BenchmarkList", new FileInputStream("target/test-classes/META-INF/BenchmarkList"))
.build()),
Which does create a JAR with the following contents:
META-INF/MANIFEST.MF
META-INF/
META-INF/BenchmarkList
But the problem persists. How could I make the resource file available for JMH?
An MCVE:
pom.xml:
<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>
<groupId>com.company.project</groupId>
<artifactId>performance</artifactId>
<version>0.0.1</version>
<packaging>jar</packaging>
<name>MCVE for JMH+PaxExam issue</name>
<prerequisites>
<maven>3.0</maven>
</prerequisites>
<properties>
<apache-servicemix.version>5.4.0</apache-servicemix.version>
<junit.version>4.11</junit.version>
<jmh.version>1.10.1</jmh.version>
<pax-exam.version>4.4.0</pax-exam.version>
<tinybundles.version>2.1.0</tinybundles.version>
<maven-sunfire-report-plugin.version>2.18.1</maven-sunfire-report-plugin.version>
<maven-depends-plugin.version>1.2</maven-depends-plugin.version>
<maven-compiler-plugin.version>3.3</maven-compiler-plugin.version>
<javac.target>1.7</javac.target>
</properties>
<dependencies>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>${jmh.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>${jmh.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam</artifactId>
<version>${pax-exam.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-container-karaf</artifactId>
<version>${pax-exam.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-junit4</artifactId>
<version>${pax-exam.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.servicemix</groupId>
<artifactId>apache-servicemix</artifactId>
<version>${apache-servicemix.version}</version>
<scope>test</scope>
<type>zip</type>
</dependency>
<dependency>
<groupId>org.ops4j.pax.tinybundles</groupId>
<artifactId>tinybundles</artifactId>
<version>${tinybundles.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.servicemix.tooling</groupId>
<artifactId>depends-maven-plugin</artifactId>
<version>${maven-depends-plugin.version}</version>
<executions>
<execution>
<id>generate-depends-file</id>
<goals>
<goal>generate-depends-file</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-sunfire-report-plugin.version}</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>${maven-sunfire-report-plugin.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${javac.target}</source>
<target>${javac.target}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
src/test/java/com/company/project/performance/MyBenchmarkTest.java:
package com.company.project.performance;
import static org.ops4j.pax.exam.CoreOptions.junitBundles;
import static org.ops4j.pax.exam.CoreOptions.maven;
import static org.ops4j.pax.exam.CoreOptions.options;
import static org.ops4j.pax.exam.CoreOptions.streamBundle;
import static org.ops4j.pax.exam.CoreOptions.wrappedBundle;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.karafDistributionConfiguration;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
import static org.ops4j.pax.tinybundles.core.TinyBundles.bundle;
import static org.ops4j.pax.tinybundles.core.TinyBundles.withBnd;
import java.io.File;
import java.io.FileInputStream;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.MavenUtils;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.options.MavenArtifactUrlReference;
#RunWith(PaxExam.class)
public class MyBenchmarkTest
{
public static final String BENCHMARK_LIST = "META-INF/BenchmarkList";
#Benchmark
public void measureThroughput() throws InterruptedException
{
TimeUnit.MILLISECONDS.sleep(100);
}
#Configuration
public Option[] config() throws Exception
{
String karafVersion = MavenUtils.getArtifactVersion("org.apache.karaf", "apache-karaf");
MavenArtifactUrlReference servicemixUrl = maven()
.groupId("org.apache.servicemix")
.artifactId("apache-servicemix")
.versionAsInProject()
.type("zip");
return options(karafDistributionConfiguration()
.frameworkUrl(servicemixUrl)
.useDeployFolder(false)
.karafVersion(karafVersion)
.unpackDirectory(new File("target/exam")),
keepRuntimeFolder(),
junitBundles(),
wrappedBundle(maven("org.openjdk.jmh", "jmh-core")),
streamBundle(bundle()
.add(BENCHMARK_LIST, new FileInputStream("target/test-classes/" + BENCHMARK_LIST))
.build(withBnd())));
}
#Test
public void launchBenchmark() throws Exception
{
Options opts = new OptionsBuilder()
.include("com.company.project.performance.*")
.warmupIterations(1)
.forks(1)
.build();
new Runner(opts).run();
}
}
The issue is clearly an import export issue.
As your test which is using your meta data, isn't aware of those extra data.
The bundle you generated with the streamBundle, needs to add an extra header information actually exporting those extra data.
streamBundle(bundle()
.add(BENCHMARK_LIST, new FileInputStream("target/test-classes/" + BENCHMARK_LIST))
.set(Constants.EXPORT_PACKAGE, BENCHMARK_LIST)
and in your test you'll need to make sure you are actually importing it.
#ProbeBuilder
public TestProbeBuilder probeConfiguration(TestProbeBuilder probe) {
//make sure the needed imports are there.
probe.setHeader(Constants.IMPORT_PACKAGE, "*,"+BENCHMARK_LIST);
return probe;
}
on the other hand it might just be a lot better to actually try to add those extra data into the test-bundle (your test class is generated into a bundle on the fly)
Therefore the following should be added to the configuration
.metaInfResource(BENCHMARK_LIST)

500 Error in Embedded Jetty Application

I keep getting a 500 error when I run this code and I cannot, for the life of me, figure out why. If anyone can also help me figure out how to get a stacktrace to print out that'd be awesome as well. Here's the code I have (it's a Maven project):
EDIT: Nothing prints to the server log but I believe this is because Jetty is embedded
package pojo;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.glassfish.jersey.servlet.ServletContainer;
public class Main {
public static void main(String[] args) throws Exception {
Server server = new Server(8112);
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
server.setHandler(context);
ServletHolder h = new ServletHolder(new ServletContainer());
h.setInitParameter("com.sun.jersey.config.property.resourceConfigClass", "com.sun.jersey.api.core.PackagesResourceConfig");
h.setInitParameter("com.sun.jersey.config.property.packages", "resources");
h.setInitOrder(1);
context.addServlet(h, "/*");
try
{
server.start();
server.join();
}
catch (Throwable t)
{
t.printStackTrace(System.err);
}
}
}
I'm trying to access this resource:
package resources;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.UriInfo;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
import java.util.ArrayList;
import java.util.List;
import pojo.Party;
#Path("/parties")
public class AllPartiesResource {
#Context
UriInfo url;
#Context
Request request;
String name;
public static final Timer allTime = DBConnection.registry.timer(MetricRegistry.name("Timer","all-parties"));
#GET
#Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
public List<Party> getAllParties() throws Exception
{
final Timer.Context context=allTime.time(); //start the timer
List<Party> list = new ArrayList<Party>();
DBConnection.readAllData();
list.addAll(DBConnection.getPartyCollection().values());
context.stop(); //stops timer
return list;
// ---> code for Jackson
// String string;
// DBConnection.readAllData();
// ObjectMapper jsonMapper = new ObjectMapper();
// string=jsonMapper.writeValueAsString(DBConnection.getPartyCollection());
// return string;
}
#GET
#Path("count")
#Produces(MediaType.TEXT_PLAIN)
public String getPartyCount() throws Exception
{
DBConnection.readAllData();
return String.valueOf(DBConnection.getPartyCollection().size());
}
#Path("{party}") //points to OnePartyResource.class
public OnePartyResource getParty(#PathParam("party")String party)
{
name = party;
return new OnePartyResource(url,request,party);
}
}
Here's my pom:
<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>
<groupId>PartyAPI</groupId>
<artifactId>PartyAPIMaven</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>com.codahale.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.17.1</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.0.4.v20130625</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>9.0.4.v20130625</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlets</artifactId>
<version>9.0.4.v20130625</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.6.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jax-rs-ri</artifactId>
<version>2.0-m13</version>
</dependency>
<dependency>
<groupId>com.google.code.simple-spring-memcached</groupId>
<artifactId>spymemcached</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>oss.sonatype.org</id>
<name>OSS Sonatype Staging</name>
<url>https://oss.sonatype.org/content/groups/staging</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.6</version>
<configuration>
<createDependencyReducedPom>true</createDependencyReducedPom>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>com.resteasy.Star.Main</Main-Class>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
</project>
When I enter in localhost:8112/parties I get the following:
HTTP ERROR: 500
Problem accessing /parties. Reason:
Request failed.
Powered by Jetty://
Figured this error out too. Essentially in my setInitParam() method I'm trying to call a package that doesn't exist. The com.sun.jersey... package didn't exist in my pom. After adding it (and deleting glassfish) it worked perfectly.

Categories