Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for parent classloading and Jetty JSP example #4

Merged
merged 1 commit into from
Jun 17, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# Junit-Servers
---------------------

Simple library that will allow you to use a custom rule to start and stop an embedded
container inside your Junit tests (currently Jetty and Tomcat supported out of the box).
Expand All @@ -12,7 +11,7 @@ With Maven, add explicit dependency:
<dependency>
<groupId>com.github.mjeanroy</groupId>
<artifactId>junit-servers-jetty</artifactId>
<version>0.4.2</version>
<version>0.4.3</version>
<scope>test</scope>
</dependency>
```
Expand All @@ -21,7 +20,7 @@ With Maven, add explicit dependency:
<dependency>
<groupId>com.github.mjeanroy</groupId>
<artifactId>junit-servers-tomcat</artifactId>
<version>0.4.2</version>
<version>0.4.3</version>
<scope>test</scope>
</dependency>
```
Expand Down Expand Up @@ -129,6 +128,8 @@ public class MyTest {
When embedded jetty is created, you can easyly use a custom configuration using a fluent API:

- Define custom enironment properties that will be initialized before server startup and removed after server shutdown.
- Define an override descriptor for web.xml, for example for loading a spring configuration with additional setup from test resources.
- Define additional parent classpath from either existing Maven dependencies or jar files in a directory, helping with JSPs.
- Define custom hooks to execute custom code before server startup and after server shutdown.

```java
Expand All @@ -150,6 +151,13 @@ public class MyTest {
.withWebapp("webapp")
.withPort(9090)
.withProperty("spring.profiles.active", "test")
.withOverrideDescriptor("src/test/resources/WEB-INF/web.xml")
.withParentClasspath(WebAppContext.class, new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().startsWith("apache-jstl");
}
})
.withHook(new Hook() {
@Override
public void pre(EmbeddedServer server) {
Expand Down Expand Up @@ -415,10 +423,10 @@ public class MyTest {
}
```

## Licence
## Licence

MIT License (MIT)

## Contributing
## Contributing

If you found a bug or you thing something is missing, feel free to contribute and submit an issue or a pull request.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
import static java.util.Collections.unmodifiableList;
import static java.util.Collections.unmodifiableMap;

import java.net.URL;

/**
* Generic configuration that should be extended for
* each custom embedded server.
Expand Down Expand Up @@ -79,6 +81,16 @@ public abstract class AbstractConfiguration {
*/
private final String classpath;

/**
* Additional parent (classloader) classpath.
*
* The path will be added to application parent classlodaer classpath
* before server is started.
*
*/

private final List<URL> parentClasspath;

/**
* Map of environment properties to set before server start.
*
Expand All @@ -101,6 +113,8 @@ public abstract class AbstractConfiguration {
*/
private final List<Hook> hooks;

private String overrideDescriptor;

/**
* Initialize configuration.
*
Expand All @@ -114,6 +128,8 @@ protected AbstractConfiguration(AbstractConfigurationBuilder builder) {
this.port = builder.getPort();
this.envProperties = builder.getEnvProperties();
this.hooks = builder.getHooks();
this.parentClasspath = builder.getParentClasspath();
this.overrideDescriptor = builder.getOverrideDescriptor();
}

public String getPath() {
Expand All @@ -128,9 +144,17 @@ public String getClasspath() {
return classpath;
}

public List<URL> getParentClasspath() {
return parentClasspath;
}

public int getPort() {
return port;
}

public String getOverrideDescriptor() {
return overrideDescriptor ;
}

public Map<String, String> getEnvProperties() {
return unmodifiableMap(envProperties);
Expand All @@ -152,7 +176,9 @@ public boolean equals(Object o) {
Objects.equals(webapp, c.webapp) &&
Objects.equals(classpath, c.classpath) &&
Objects.equals(envProperties, c.envProperties) &&
Objects.equals(hooks, c.hooks);
Objects.equals(hooks, c.hooks) &&
Objects.equals(overrideDescriptor, c.overrideDescriptor) &&
Objects.equals(parentClasspath, c.parentClasspath);
}
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,17 @@
import com.github.mjeanroy.junit.servers.servers.Hook;

import java.io.File;
import java.io.FileFilter;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static com.github.mjeanroy.junit.servers.commons.Preconditions.notBlank;
import static com.github.mjeanroy.junit.servers.commons.Preconditions.notNull;
Expand Down Expand Up @@ -73,6 +80,13 @@ public abstract class AbstractConfigurationBuilder<T extends AbstractConfigurati
* @see com.github.mjeanroy.junit.servers.servers.configuration.AbstractConfiguration#classpath
*/
private String classpath;

/**
* Parent classpath URLs
*
*/

private List<URL> parentClasspath;

/**
* Map of properties.
Expand All @@ -88,6 +102,8 @@ public abstract class AbstractConfigurationBuilder<T extends AbstractConfigurati
*/
private final List<Hook> hooks;

private String overrideDescriptor;

/**
* Build default configuration.
*/
Expand Down Expand Up @@ -216,4 +232,59 @@ public T withHook(Hook hook) {
this.hooks.add(notNull(hook, "hook"));
return self();
}


/**
* Change parent classpath value.
*
* @param classpath New webapp value.
* @return this
*/
public T withParentClasspath(List<URL> classpath) {
this.parentClasspath = classpath;
return self();
}

/**
* Change parent classpath value.
*
* @param classpath New webapp value.
* @return this
*/
public T withParentClasspath(Class<?> cls, FileFilter filter) {
URLClassLoader urlClassLoader = (URLClassLoader) cls.getClassLoader();

Set<URL> urls = new HashSet<>();
for(URL url : urlClassLoader.getURLs()) {
if(filter.accept(new File(url.getFile()))) {
urls.add(url);
}
}
this.parentClasspath = new ArrayList<>(urls);
return self();
}

/**
* Change parent classpath value.
*
* @param classpath New webapp value.
* @return this
*/
public T withParentClasspath(URL ... classpath) {
this.parentClasspath = Arrays.asList(classpath);
return self();
}

public List<URL> getParentClasspath() {
return parentClasspath;
}

public T withOverrideDescriptor (String overrideDescriptor) {
this.overrideDescriptor = overrideDescriptor;
return self();
}

public String getOverrideDescriptor() {
return overrideDescriptor;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,23 @@

package com.github.mjeanroy.junit.servers.jetty;

import com.github.mjeanroy.junit.servers.exceptions.ServerInitializationException;
import com.github.mjeanroy.junit.servers.exceptions.ServerStartException;
import com.github.mjeanroy.junit.servers.exceptions.ServerStopException;
import com.github.mjeanroy.junit.servers.servers.AbstractEmbeddedServer;
import static com.github.mjeanroy.junit.servers.commons.Strings.isNotBlank;
import static com.github.mjeanroy.junit.servers.jetty.EmbeddedJettyConfiguration.defaultConfiguration;
import static org.eclipse.jetty.util.resource.Resource.newResource;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;

import javax.servlet.ServletContext;

import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.util.resource.FileResource;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.FragmentConfiguration;
import org.eclipse.jetty.webapp.JettyWebXmlConfiguration;
Expand All @@ -41,12 +49,10 @@
import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.eclipse.jetty.webapp.WebXmlConfiguration;

import javax.servlet.ServletContext;
import java.io.File;

import static com.github.mjeanroy.junit.servers.commons.Strings.isNotBlank;
import static com.github.mjeanroy.junit.servers.jetty.EmbeddedJettyConfiguration.defaultConfiguration;
import static org.eclipse.jetty.util.resource.Resource.newResource;
import com.github.mjeanroy.junit.servers.exceptions.ServerInitializationException;
import com.github.mjeanroy.junit.servers.exceptions.ServerStartException;
import com.github.mjeanroy.junit.servers.exceptions.ServerStopException;
import com.github.mjeanroy.junit.servers.servers.AbstractEmbeddedServer;

/**
* Jetty Embedded Server.
Expand Down Expand Up @@ -128,23 +134,42 @@ protected WebAppContext createdWebAppContext() throws Exception {
final String path = configuration.getPath();
final String webapp = configuration.getWebapp();
final String classpath = configuration.getClasspath();
final List<URL> parentClasspath = configuration.getParentClasspath();
final String overrideDescriptor = configuration.getOverrideDescriptor ();
final Resource baseResource = configuration.getBaseResource();

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

if(parentClasspath != null && !parentClasspath.isEmpty()) {
classLoader = new URLClassLoader(parentClasspath.toArray(new URL[parentClasspath.size()]), classLoader);
}

WebAppContext ctx = new WebAppContext();
ctx.setClassLoader(Thread.currentThread().getContextClassLoader());
ctx.setClassLoader(classLoader);
ctx.setContextPath(path);

// Useful for WebXmlConfiguration
ctx.setBaseResource(newResource(webapp));
if(baseResource == null) {
// use default base resource
ctx.setBaseResource(newResource(webapp));
} else {
ctx.setBaseResource(baseResource);
}

if(overrideDescriptor != null) {
ctx.setOverrideDescriptor(overrideDescriptor);
}

ctx.setConfigurations(new Configuration[]{
new WebInfConfiguration(),
new WebInfConfiguration(),
new WebXmlConfiguration(),
new AnnotationConfiguration(),
new JettyWebXmlConfiguration(),
new MetaInfConfiguration(),
new FragmentConfiguration(),
new FragmentConfiguration()
});

ctx.addOverrideDescriptor(overrideDescriptor);

if (isNotBlank(classpath)) {
// Fix to scan Spring WebApplicationInitializer
// This will add compiled classes to jetty classpath
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@

import static com.github.mjeanroy.junit.servers.commons.Preconditions.positive;

import org.eclipse.jetty.util.resource.Resource;

/**
* Jetty configuration settings.
*/
Expand All @@ -46,6 +48,8 @@ public final class EmbeddedJettyConfiguration extends AbstractConfiguration {
*/
private final boolean stopAtShutdown;

private Resource baseResource;

/**
* Get configuration builder.
*
Expand All @@ -69,6 +73,7 @@ private EmbeddedJettyConfiguration(Builder builder) {
super(builder);
this.stopTimeout = builder.getStopTimeout();
this.stopAtShutdown = builder.isStopAtShutdown();
this.baseResource = builder.getBaseResource();
}

public int getStopTimeout() {
Expand All @@ -89,12 +94,18 @@ public int hashCode() {
return super.hashCode();
}

public Resource getBaseResource() {
return baseResource;
}

public static class Builder extends AbstractConfigurationBuilder<Builder, EmbeddedJettyConfiguration> {

private int stopTimeout;

private boolean stopAtShutdown;

private Resource baseResource;

private Builder() {
stopTimeout = 30000;
stopAtShutdown = true;
Expand All @@ -118,6 +129,10 @@ public boolean isStopAtShutdown() {
return stopAtShutdown;
}

public Resource getBaseResource() {
return baseResource;
}

/**
* Update stop timeout value.
* @param stopTimeout New stop timeout value.
Expand All @@ -141,5 +156,11 @@ private Builder toggleStopAtShutdown(boolean stopAtShutdown) {
this.stopAtShutdown = stopAtShutdown;
return this;
}

public Builder withBaseResource(Resource resource) {
this.baseResource = resource;
return this;
}

}
}
Empty file.
Loading