Skip to content

Instantly share code, notes, and snippets.

@PiotrNowicki
Created September 27, 2011 19:28
Show Gist options
  • Save PiotrNowicki/1245983 to your computer and use it in GitHub Desktop.
Save PiotrNowicki/1245983 to your computer and use it in GitHub Desktop.
Arquillian - multiple deployments for different containers
/////////////////////////////////////////////////////////////////////////////////////////
// DeploymentScenarioGenerator extension
/////////////////////////////////////////////////////////////////////////////////////////
/**
* Registers the {@link FlexibleRegisterDeployment} which allows to choose the
* {@link Deployment} annotated method from the test class which will be used
* for particular target container.
*
* @author PedroKowalski
*
*/
public class DeploymentRegisterer implements LoadableExtension {
@Override
public void register(ExtensionBuilder builder) {
builder.service(DeploymentScenarioGenerator.class,
FlexibleRegisterDeployment.class);
}
/**
* Chooses the appropriate {@link Deployment} annotated method basing on the
* chosen target container. The target container is defined using
* {@link UseInContainer} annotation.
*
* If there is only one {@link Deployment} annotated method, it will be
* chosen by default. It's assumed that no container-specific deployment
* means that no special steps are need to be taken for different
* containers.
*
* @see DeploymentRegisterer
* @see TargetContainerName
* @see UseInContainer
*
* @author PedroKowalski
*
*/
public static class FlexibleRegisterDeployment implements
DeploymentScenarioGenerator {
/**
* We need to know what container are we actually using.
*/
@Inject
Instance<ContainerRegistry> container;
private static final Logger log = Logger
.getLogger(FlexibleRegisterDeployment.class.getName());
@Override
public List<DeploymentDescription> generate(TestClass testClass) {
Method m = getMethodForDeployment(testClass, getTargetContainer());
WebArchive deployment;
try {
deployment = (WebArchive) m.invoke(testClass);
} catch (Exception e) {
throw new IllegalStateException(e);
}
return Arrays.asList(new DeploymentDescription(
"On-the-fly deployment", deployment));
}
/**
* Gets the deployment method for particular target container.
*
* @param clazz
* test class which contains {@link Deployment} annotated
* method(s).
* @param targetContainer
* target container adapter which is active in classpath.
* @return deployment method to be invoked for specified target
* container.
*/
private Method getMethodForDeployment(TestClass clazz,
TargetContainerName targetContainer) {
Method[] methods = clazz.getMethods(Deployment.class);
if (methods.length == 0) {
throw new IllegalStateException(
"At least one @Deployment method is required");
} else {
for (Method method : methods) {
if (method.getAnnotation(UseInContainer.class).value()
.equals(targetContainer)) {
return method;
}
}
MessageFormat msg = new MessageFormat(
"Deployment method cannot be found. Are you sure you have an appropriate @UseInContainer annotation on one of your @Deployment methods in {1}?");
throw new IllegalStateException(msg.format(new Object[] {
targetContainer, clazz.getName() }));
}
}
/**
* Gets the target container which is in user's classpath and is used in
* the test run.
*
* If no value is specified, the default container (
* {@link TargetContainerName#GLASSFISH}) will be chosen.
*
* @return name of the target container to be used.
*/
private TargetContainerName getTargetContainer() {
DeployableContainer<?> dc = container.get().getContainers().get(0)
.getDeployableContainer();
TargetContainerName result = TargetContainerName.get(dc.getClass());
log.info("Using '" + result + "' as a target container.");
return result;
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////
// Possible target containers
/////////////////////////////////////////////////////////////////////////////////////////
/**
* Represents possible target container which deployment can be explicitly set
* in test class.
*
* @author PedroKowalski
*
*/
public enum TargetContainerName {
/**
* Glassfish 3.1 container.
*/
GLASSFISH("container.glassfish"),
/**
* JBoss AS7 container.
*/
JBOSSAS7("org.jboss.as.arquillian.container");
/**
* Holds the unique part of the container adapter package name.
*/
private String packageName;
private static final Logger log = Logger
.getLogger(TargetContainerName.class.getName());
private TargetContainerName(String packageName) {
this.packageName = packageName;
}
public String getPackageName() {
return packageName;
}
/**
* Gets the {@link TargetContainerName} basing on the runtime deployment
* class passed as an argument.
*
* @param clazz
* deployment class for which the target container should be
* returned
* @return target container name
*/
public static TargetContainerName get(Class<?> clazz) {
for (TargetContainerName tcn : values()) {
String packageName = clazz.getPackage().getName().toLowerCase();
if (packageName.contains(tcn.getPackageName())) {
return tcn;
}
}
// No matches found - go with the default.
log.warning("No matching container for '" + clazz.getName()
+ "' found. Falling back to default.");
return GLASSFISH;
}
}
/////////////////////////////////////////////////////////////////////////////////////////
// Exemplary usage in test class
/////////////////////////////////////////////////////////////////////////////////////////
@Deployment
@UseInContainer(TargetContainerName.GLASSFISH)
public static WebArchive createGlassFishDeployment() {}
@Deployment
@UseInContainer(TargetContainerName.JBOSSAS7) {}
/////////////////////////////////////////////////////////////////////////////////////////
// UseInContainer annotation
/////////////////////////////////////////////////////////////////////////////////////////
/**
* Defines that the Deployment should be used only when particular container
* adapter is active.
*
* @author PedroKowalski
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface UseInContainer {
/**
* Name of the container for which the deployment should be used.
*/
TargetContainerName value();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment