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

ARQ-1447 Inject Injector created through GuiceFilter. #2

Merged
merged 1 commit into from Jul 31, 2013
Jump to file or symbol
Failed to load files and symbols.
+580 −31
Diff settings

Always

Just for now

View
@@ -1,4 +1,5 @@
<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/maven-v4_0_0.xsd">
<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/maven-v4_0_0.xsd">
<!-- Parent -->
<parent>
@@ -37,6 +38,18 @@
<artifactId>guice</artifactId>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-servlet</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.spec</groupId>
<artifactId>jboss-javaee-web-6.0</artifactId>
<type>pom</type>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -27,7 +27,8 @@
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Annotation used for configuring Guice within model.
* Annotation used for configuring Guice within test. Allows to define a set of modules that will be used for
* instantiating the Guice Injector prior running the tests.
*
* @author <a href="mailto:jmnarloch@gmail.com">Jakub Narloch</a>
*/
@@ -17,16 +17,25 @@
package org.jboss.arquillian.guice.api.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Allows to construct custom injector in the model class.
* Allows to construct custom injector in the test class.
* <p />
* This is a marker annotation which allows to define a static factory method within the test that will be responsible
* for creating the instance of the Guice injector at the runtime.
*
* The method should have fallowing signature:
* <pre>
* public static Injector [method_name]();
* </pre>
*
* The actual return type must be assignable into a Injector type, otherwise a {@link ClassCastException} will be
* thrown.
*
* @author <a href="mailto:jmnarloch@gmail.com">Jakub Narloch</a>
*/
@@ -0,0 +1,38 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2013, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.arquillian.guice.api.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Marks that the test is using the Injector created within the servlet context. This annotation must be used with
* WebArchive deployment and properly configured {@link org.jboss.arquillian.guice.api.servlet.ArquillianGuiceFilter}.
*
* @author <a href="mailto:jmnarloch@gmail.com">Jakub Narloch</a>
*/
@Documented
@Retention(RUNTIME)
@Target(TYPE)
@Inherited
public @interface GuiceWebConfiguration {
}
@@ -0,0 +1,129 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2013, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.arquillian.guice.api.servlet;
import com.google.inject.Injector;
import com.google.inject.servlet.GuiceFilter;
import org.jboss.arquillian.guice.api.utils.InjectorHolder;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import java.lang.ref.WeakReference;
/**
* A custom implementation of the standard {@link GuiceFilter} that additionally bind the created {@link Injector} with
* current executing thread, allowing to retrieve the injector from directly from the test.
* <p />
* The implementation uses the fact that the injector is being passed between the {@link
* com.google.inject.servlet.GuiceServletContextListener} and {@link GuiceFilter} as a attribute stored in {@link
* ServletContext}. This class does not alter the default behaviour of the {@link GuiceFilter} (which by the for most
* of the attributes and methods defines the package scope so could not be easily modified). Since this class inherits
* from the {@link GuiceFilter} it's the only filter that is required to setup the Guice in servlet environment and in
* the same time enable the Arquillian tests.
* <p />
* The implementation delegates to {@link InjectorHolder} for storing the Injector instance and binding it with the
* executing thread.
*
* @author <a href="mailto:jmnarloch@gmail.com">Jakub Narloch</a>
* @see GuiceFilter
* @see InjectorHolder
*/
public class ArquillianGuiceFilter extends GuiceFilter {
/**
* Stores the servlet context.
*/
private WeakReference<ServletContext> servletContext = new WeakReference<ServletContext>(null);
/**
* {@inheritDoc}
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// retrieves the servlet context
servletContext = new WeakReference<ServletContext>(filterConfig.getServletContext());
// stores the injector
bindInjector();
// invokes the base method
super.init(filterConfig);
}
/**
* {@inheritDoc}
*/
@Override
public void destroy() {
// removes the injector
removeInjector();
// calls the base method
super.destroy();
}
/**
* Binds the injector in the {@link InjectorHolder} with currently executing thread.
*/
private void bindInjector() {
Injector injector = getInjector();
if (injector != null) {
InjectorHolder.bindInjector(injector);
}
}
/**
* Removes the injector from the {@link InjectorHolder}.
*/
private void removeInjector() {
InjectorHolder.removeInjector();
}
/**
* Retrieves the servlet context.
*
* @return the servlet context
*/
private ServletContext getServletContext() {
return servletContext.get();
}
/**
* Retrieves the injector from the servlet context attribute.
*
* @return the injector retrieved from servlet context attribute
*/
private Injector getInjector() {
ServletContext servletContext = getServletContext();
if (servletContext != null) {
return (Injector) servletContext.getAttribute(Injector.class.getName());
}
return null;
}
}
@@ -0,0 +1,73 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2013, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.arquillian.guice.api.utils;
import com.google.inject.Injector;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Binds the {@link Injector} with the currently executing thread.
*
* @author <a href="mailto:jmnarloch@gmail.com">Jakub Narloch</a>
*/
public final class InjectorHolder {
/**
* Each key value pair stores the caseloader and the associated injector instance.
*/
private static final Map<ClassLoader, Injector> threadInjectors = new ConcurrentHashMap<ClassLoader, Injector>();
/**
* Binds the injector instance with currently executing thread.
*
* @param injector the injector instance to bind
*/
public static void bindInjector(Injector injector) {
threadInjectors.put(Thread.currentThread().getContextClassLoader(), injector);
}
/**
* Removes any injector that has been bound with currently executing thread.
*/
public static void removeInjector() {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (loader != null) {
threadInjectors.remove(loader);
}
}
/**
* Retrieves the injector instance that has been bound with the thread.
*
* @return the injector instance or null if non injector has been bound
*/
public static Injector getInjector() {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (loader != null) {
return threadInjectors.get(loader);
}
return null;
}
}
View
@@ -1,4 +1,5 @@
<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/maven-v4_0_0.xsd">
<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/maven-v4_0_0.xsd">
<!-- Parent -->
<parent>
@@ -101,6 +102,18 @@
<artifactId>guice</artifactId>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-servlet</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.spec</groupId>
<artifactId>jboss-javaee-web-6.0</artifactId>
<type>pom</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
@@ -42,6 +42,11 @@ public GuiceExtensionConsts() {
*/
public static final String GUICE_ARTIFACT_NAME = "com.google.inject:guice";
/**
* Represents the Guice extension servlet artifact name.
*/
public static final String GUICE_SEVLET_ARTIFACT_NAME = "com.google.inject.extensions:guice-servlet";
/**
* Represents the default Guice maven artifact version.
*/
@@ -19,6 +19,8 @@
import org.jboss.arquillian.container.test.spi.RemoteLoadableExtension;
import org.jboss.arquillian.container.test.spi.client.deployment.CachedAuxilliaryArchiveAppender;
import org.jboss.arquillian.guice.api.annotation.GuiceConfiguration;
import org.jboss.arquillian.guice.api.servlet.ArquillianGuiceFilter;
import org.jboss.arquillian.guice.api.utils.InjectorHolder;
import org.jboss.arquillian.guice.impl.GuiceExtensionConsts;
import org.jboss.arquillian.guice.impl.container.GuiceEnricherRemoteExtension;
import org.jboss.arquillian.guice.impl.enricher.GuiceInjectionEnricher;
@@ -46,6 +48,8 @@
.addPackage(InjectorProducer.class.getPackage())
.addPackage(GuiceExtensionConsts.class.getPackage())
.addPackage(GuiceConfiguration.class.getPackage())
.addPackage(ArquillianGuiceFilter.class.getPackage())
.addPackage(InjectorHolder.class.getPackage())
.addAsServiceProvider(RemoteLoadableExtension.class, GuiceEnricherRemoteExtension.class);
}
}
Oops, something went wrong.
ProTip! Use n and p to navigate between commits in a pull request.