mock-server / mockserver

MockServer enables easy mocking of any system you integrate with via HTTP or HTTPS with clients written in Java, JavaScript and Ruby. MockServer also includes a proxy that introspects all proxied traffic including encrypted SSL traffic and supports Port Forwarding, Web Proxying (i.e. HTTP proxy), HTTPS Tunneling Proxying (using HTTP CONNECT) and SOCKS Proxying (i.e. dynamic port forwarding).
http://mock-server.com
Apache License 2.0
4.57k stars 1.07k forks source link

ClassNotFoundException when running maven plugin in non-forked mode #91

Closed ryan-ju closed 9 years ago

ryan-ju commented 9 years ago

I configured the maven plugin as follows,

            <plugin>
                <groupId>org.mock-server</groupId>
                <artifactId>mockserver-maven-plugin</artifactId>
                <version>3.9.1</version>
                <configuration>
                    <serverPort>9090</serverPort>
                    <proxyPort>9091</proxyPort>
                    <logLevel>DEBUG</logLevel>
                    <!--<initializationClass>org.mockserver.maven.ExampleInitializationClass</initializationClass>-->
                </configuration>
                <executions>
                    <execution>
                        <id>pre-integration-test</id>
                        <phase>pre-integration-test</phase>
                        <goals>
                            <goal>start</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>post-integration-test</id>
                        <phase>post-integration-test</phase>
                        <goals>
                            <goal>stop</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

and added a callback class as this

public class HelloCallback implements ExpectationCallback {

    public HelloCallback() {

    }

    @Override
    public HttpResponse handle(HttpRequest httpRequest) {
        for (Parameter parameter : httpRequest.getQueryStringParameters()) {
            if ("name".equals(parameter.getName())) {
                return response()
                        .withHeaders(new Header("Content-Type", "text/plain; charset=utf-8"))
                        .withBody("hello " + parameter.getName());
            }
        }
        return response()
                .withStatusCode(400)
                .withHeaders(new Header("Content-Type", "text/plain; charset=utf-8"))
                .withBody("Name not set!");
    }
}

and mocked the expectation in my test as this

    MockServerClient mockHello;

    @Before
    public void init() {
        mockHello = new MockServerClient("localhost", 9090);
        // Dynamic mocking
        mockHello.when(
                request()
                        .withMethod("GET")
                        .withPath("/hello"))
                .callback(callback().withCallbackClass(HelloCallback.class.getCanonicalName()));
    }

But when I build the project, maven complained java.lang.ClassNotFoundException

Is this a bug in the plugin? Do we have a working example that I can reference?

stevenkampen commented 9 years ago

@ryan-ju Is there any more info to that exception? I'm getting java.lang.ClassNotFoundException: com.jcraft.jzlib.Inflater, which seems to be a dependency of netty. Running mockserver on the command line and manually including the jzlib jar in the classpath does work, but I'm struggling with how to get those dependencies injected into the mockserver that is started by the maven build.

jamesbloomnektan commented 9 years ago

Sorry for the delay I've been busy on other projects. There are a number of integration tests that also act as example projects for the maven plugin. Please see: https://github.com/jamesdbloom/mockserver/tree/master/mockserver-maven-plugin-integration-tests/src/integration-tests for the scenarios. I suspect the specific scenario you are interested in is: https://github.com/jamesdbloom/mockserver/tree/master/mockserver-maven-plugin-integration-tests/src/integration-tests/mockserver-initializer-main-classpath or: https://github.com/jamesdbloom/mockserver/tree/master/mockserver-maven-plugin-integration-tests/src/integration-tests/mockserver-initializer-test-classpath depending on whether your org.mockserver.maven.ExampleInitializationClass is in the main or test classpath.

If these examples still don't resolve your issue please comment back and I'll look into it. Any addition access you can give me to the project or information about how your classpath is structured could help.

jamesdbloom commented 9 years ago

I don't believe com.jcraft.jzlib.Inflater is used by Netty and I can't find any jzlib or jcraft dependencies for any part of Netty or the MockServer. Do you have more information on this?

stevenkampen commented 9 years ago

@jamesdbloom I worked around this by disabling gzip compression in my api calls, since that's what seemed to require the jcraft lib. I'm not sure why I thought it was related to this issue. It clearly isn't.

jamesdbloom commented 9 years ago

If you are still having issues with missing dependencies you may need to specifically add the dependency to the main or test classpath. It may be that the class you are looking for is somehow included into the maven build in a non-standard way. I currently add all test classpath and main classpath artefacts as follows (see org.mockserver.maven.MockServerAbstractMojo):

/**
 * The main classpath location of the project using this plugin
 */
@Parameter(property = "project.compileClasspathElements", required = true, readonly = true)
protected List<String> compileClasspath;

/**
 * The test classpath location of the project using this plugin
 */
@Parameter(property = "project.testClasspathElements", required = true, readonly = true)
protected List<String> testClasspath;

private ClassLoader setupClasspath() throws MalformedURLException {
    if (compileClasspath != null && testClasspath != null) {
        URL[] urls = new URL[compileClasspath.size() + testClasspath.size()];
        for (int i = 0; i < compileClasspath.size(); i++) {
            urls[i] = new File(compileClasspath.get(i)).toURI().toURL();
        }
        for (int i = compileClasspath.size(); i < compileClasspath.size() + testClasspath.size(); i++) {
            urls[i] = new File(testClasspath.get(i - compileClasspath.size())).toURI().toURL();
        }

        ClassLoader contextClassLoader = URLClassLoader.newInstance(urls, Thread.currentThread().getContextClassLoader());
        Thread.currentThread().setContextClassLoader(contextClassLoader);
        return contextClassLoader;
    }
    return null;
}

Which version of maven are you using? It may also be caused by your version of maven not correctly populating project.compileClasspathElements or project.testClasspathElements. I can see some bugs relating to this in Maven 2.0 such as http://jira.codehaus.org/browse/MNG-1246

jamesdbloom commented 9 years ago

I'm going to close this issue, if you have more information that identifies a bug please open the issue again.