You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by mg...@apache.org on 2013/06/27 10:04:24 UTC

[2/5] git commit: Port of wicket-cdi to support cdi-1.1

Port of wicket-cdi to support cdi-1.1

Package is split up into wicket-cdi-1.1-core and wicket-cdi-1.1-weld.
Refactored some classes to use cdi injection instead of constructors.
Worked with tomcat and glassfish in my limited testing.


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/befbf9c7
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/befbf9c7
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/befbf9c7

Branch: refs/heads/master
Commit: befbf9c77219e8744d376eb40c73b4e9890aa306
Parents: e75eeaa
Author: John Sarman <jo...@gmail.com>
Authored: Wed Jun 26 13:01:21 2013 -0400
Committer: John Sarman <jo...@gmail.com>
Committed: Wed Jun 26 13:01:21 2013 -0400

----------------------------------------------------------------------
 wicket-experimental/pom.xml                     |   1 +
 wicket-experimental/wicket-cdi-1.1/pom.xml      |  36 ++
 .../wicket-cdi-1.1/wicket-cdi-1.1-core/pom.xml  |  88 ++++
 .../apache/wicket/cdi/AbstractCdiContainer.java | 136 ++++++
 .../org/apache/wicket/cdi/AbstractInjector.java |  65 +++
 .../main/java/org/apache/wicket/cdi/Auto.java   |  36 ++
 .../org/apache/wicket/cdi/AutoConversation.java |  48 ++
 .../org/apache/wicket/cdi/BehaviorInjector.java |  45 ++
 .../org/apache/wicket/cdi/CdiConfiguration.java | 256 +++++++++++
 .../apache/wicket/cdi/CdiShutdownCleaner.java   |  56 +++
 .../apache/wicket/cdi/ComponentInjector.java    |  61 +++
 .../cdi/ConversationExpiredException.java       |  51 +++
 .../wicket/cdi/ConversationExpiryChecker.java   |  75 ++++
 .../wicket/cdi/ConversationIdMetaKey.java       |  24 +
 .../wicket/cdi/ConversationPropagation.java     |  77 ++++
 .../wicket/cdi/ConversationPropagator.java      | 447 +++++++++++++++++++
 .../wicket/cdi/ConversationalComponent.java     |  30 ++
 .../java/org/apache/wicket/cdi/DetachEvent.java |  28 ++
 .../apache/wicket/cdi/DetachEventEmitter.java   |  81 ++++
 .../cdi/ICdiAwareRequestCycleListener.java      |  39 ++
 .../wicket/cdi/IConversationPropagation.java    |  51 +++
 .../wicket/cdi/INonContextualManager.java       |  55 +++
 .../org/apache/wicket/cdi/NonContextual.java    | 153 +++++++
 .../apache/wicket/cdi/NonContextualManager.java |  73 +++
 .../java/org/apache/wicket/cdi/Propagation.java |  37 ++
 .../org/apache/wicket/cdi/SessionInjector.java  |  51 +++
 .../src/main/resources/META-INF/beans.xml       |   0
 .../wicket/cdi/ApacheLicenceHeaderTest.java     |  40 ++
 .../wicket/cdi/ComponentInjectorTest.java       | 133 ++++++
 .../wicket-cdi-1.1/wicket-cdi-1.1-weld/pom.xml  |  87 ++++
 .../wicket/cdi/weld/WeldCdiContainer.java       |  98 ++++
 .../src/main/resources/META-INF/beans.xml       |   0
 .../cdi/weld/ApacheLicenceHeaderTest.java       |  40 ++
 33 files changed, 2498 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/pom.xml
----------------------------------------------------------------------
diff --git a/wicket-experimental/pom.xml b/wicket-experimental/pom.xml
index b0bb5d7..0e2d493 100644
--- a/wicket-experimental/pom.xml
+++ b/wicket-experimental/pom.xml
@@ -33,6 +33,7 @@
 		<module>wicket-bootstrap</module>
 		<module>wicket-examples-parent</module>
 		<module>wicket-bean-validation</module>
+		<module>wicket-cdi-1.1</module>
 	</modules>
 	<build>
 		<pluginManagement>

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/pom.xml
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/pom.xml b/wicket-experimental/wicket-cdi-1.1/pom.xml
new file mode 100644
index 0000000..c9f11c3
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.
+-->
+<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">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.apache.wicket</groupId>
+		<artifactId>wicket-experimental</artifactId>
+		<version>7.0.0-SNAPSHOT</version>
+		<relativePath>../pom.xml</relativePath>
+	</parent>
+	<artifactId>wicket-cdi-1.1</artifactId>
+    <version>0.1-SNAPSHOT</version>
+	<packaging>pom</packaging>
+	<name>Wicket CDI 1.1</name>
+	<description>Wicket CDI 1.1 Parent.</description>
+	<modules>
+		<module>wicket-cdi-1.1-core</module>
+		<module>wicket-cdi-1.1-weld</module>
+		<!--<module>wicket-cdi-1.1-owb</module>-->
+	</modules>
+</project>

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/pom.xml
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/pom.xml b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/pom.xml
new file mode 100644
index 0000000..87b4265
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/pom.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You 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.
+-->
+<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">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.apache.wicket</groupId>
+		<artifactId>wicket-cdi-1.1</artifactId>
+		<version>0.1-SNAPSHOT</version>
+		<relativePath>../pom.xml</relativePath>
+	</parent>
+	<artifactId>wicket-cdi-1.1-core</artifactId>
+	<packaging>jar</packaging>
+        <version>0.1-SNAPSHOT</version>
+	<name>Wicket CDI 1.1 Core</name>
+	<description>
+		Provides integration between Wicket and CDI containers. Enables injection of
+		components and behaviors, as well as other non-contextual object instances.
+		Also enables propagation of conversations between wicket artifacts such as pages
+		and resources.
+	</description>
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.wicket</groupId>
+			<artifactId>wicket-core</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>javax.enterprise</groupId>
+			<artifactId>cdi-api</artifactId>
+			<version>1.1</version>
+			<scope>provided</scope>
+		</dependency>		
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>javax.el</groupId>
+			<artifactId>javax.el-api</artifactId>
+			<version>2.2.4</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+	<build>
+		<pluginManagement>
+			<plugins>
+				<plugin>
+					<groupId>org.codehaus.mojo</groupId>
+					<artifactId>clirr-maven-plugin</artifactId>
+					<executions>
+						<execution>
+							<id>clirr-check</id>
+							<phase>compile</phase>
+							<goals>
+								<goal>check</goal>
+							</goals>
+							<configuration>
+								<comparisonVersion>6.1.0</comparisonVersion>
+								<failOnError>true</failOnError>
+								<logResults>true</logResults>
+							</configuration>
+						</execution>
+					</executions>
+					<configuration>
+						<comparisonVersion>6.1.0</comparisonVersion>
+						<failOnError>true</failOnError>
+						<logResults>true</logResults>
+					</configuration>
+				</plugin>
+			</plugins>
+		</pluginManagement>
+	</build>
+</project>

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/AbstractCdiContainer.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/AbstractCdiContainer.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/AbstractCdiContainer.java
new file mode 100644
index 0000000..3e302eb
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/AbstractCdiContainer.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+import javax.inject.Inject;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.MetaDataKey;
+import org.apache.wicket.Page;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.util.lang.Args;
+
+/**
+ * Provides access to CDI features from inside a Wicket request
+ * 
+ * @author igor
+ * 
+ */
+public abstract class AbstractCdiContainer
+{
+	private static final MetaDataKey<AbstractCdiContainer> CONTEXT_KEY = new MetaDataKey<AbstractCdiContainer>()
+	{
+		private static final long serialVersionUID = 1L;
+	};
+		
+	/**
+	 * Constructor
+	 * 	
+	 */
+	public AbstractCdiContainer()
+	{
+	}
+
+	protected abstract INonContextualManager getNonContextualManager();
+	
+	/**
+	 * Deactivates conversational context
+	 * 
+	 * @param cycle
+	 */
+	public abstract void deactivateConversationalContext(RequestCycle cycle);
+
+	/**
+	 * Activates the conversational context and starts the conversation with the specified cid
+	 * 
+	 * @param cycle
+	 * @param cid
+	 */
+	public abstract void activateConversationalContext(RequestCycle cycle, String cid);
+	
+
+	protected HttpServletRequest getRequest(RequestCycle cycle)
+	{
+		return (HttpServletRequest)cycle.getRequest().getContainerRequest();
+	}
+
+	/**
+	 * Retrieves a conversation id, if any, that is associated with a {@link Page} instance
+	 * 
+	 * @param page
+	 *            page instance
+	 * @return conversation id, if any
+	 */
+	public String getConversationMarker(Page page)
+	{
+		return page.getMetaData(ConversationIdMetaKey.INSTANCE);
+	}
+
+	/**
+	 * Removes conversation marker from the page instance which prevents the conversation from
+	 * propagating to the page. This method should usually be called from page's {@code onDetach()}
+	 * method.
+	 * 
+	 * @param page
+	 */
+	public void removeConversationMarker(Page page)
+	{
+		Args.notNull(page, "page");
+
+		page.setMetaData(ConversationIdMetaKey.INSTANCE, null);
+		page.getPageParameters().remove(ConversationPropagator.CID_ATTR);
+	}
+
+	/**
+	 * Binds this container instance to the {@link Application}, making it possible to retrieve it
+	 * later
+	 * 
+	 * @param application
+	 */
+	protected void bind(Application application)
+	{
+		application.setMetaData(CONTEXT_KEY, this);
+	}
+
+	/**
+	 * Retrieves container instance stored in the application
+	 * 
+	 * @param application
+	 * @return container instance or {@code null} if none
+	 */
+	public static final AbstractCdiContainer get(Application application)
+	{
+		AbstractCdiContainer ctx = application.getMetaData(CONTEXT_KEY);
+		if (ctx == null)
+		{
+			throw new IllegalStateException("No CDI Context bound to application");
+		}
+		return ctx;
+	}
+
+	/**
+	 * Retrieves container instance stored in the current thread's application
+	 * 
+	 * @return container instance or {@code null} if none
+	 */
+	public static final AbstractCdiContainer get()
+	{
+		return get(Application.get());
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/AbstractInjector.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/AbstractInjector.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/AbstractInjector.java
new file mode 100644
index 0000000..51967d4
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/AbstractInjector.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+import org.apache.wicket.util.lang.Args;
+
+/**
+ * Base class for injectors
+ * 
+ * @author igor
+ */
+class AbstractInjector
+{
+	private final AbstractCdiContainer container;
+	private static final String[] ignoredPackages =new String[]{
+		"org.apache.wicket.markup.html",       
+		"org.apache.wicket.protocol.html",
+		"org.apache.wicket.behavior",    
+	};
+
+	public AbstractInjector(AbstractCdiContainer container)
+	{
+		Args.notNull(container, "container");
+		this.container = container;
+	}
+
+	protected <T> void postConstruct(T instance)
+	{
+		container.getNonContextualManager().postConstruct(instance);
+	}
+
+	protected <T> void inject(T instance)
+	{
+		if(!ignore(instance.getClass())) {
+			container.getNonContextualManager().inject(instance);
+		}
+	}
+        
+	private static boolean ignore(Class clazz)
+	{
+		String packageName = clazz.getName();
+		for(String ignore:ignoredPackages)
+		{
+			if(packageName.contains(ignore))
+			{
+				return true;
+			}
+		}           
+		return false;
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/Auto.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/Auto.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/Auto.java
new file mode 100644
index 0000000..5157a40
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/Auto.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import javax.inject.Qualifier;
+
+/**
+ * Qualifier for injecting the Automatic Conversation begin boolean 
+ * 
+ * @author jsarman
+ */
+@Qualifier
+@Target( { ElementType.TYPE,ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Auto 
+{
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/AutoConversation.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/AutoConversation.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/AutoConversation.java
new file mode 100644
index 0000000..4d21530
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/AutoConversation.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+import javax.enterprise.context.ConversationScoped;
+import org.apache.wicket.util.io.IClusterable;
+
+/**
+ * A bean that can be used to override whether the lifecycle of the conversation should be managed
+ * automatically or not. See {@link CdiConfiguration#setAutoConversationManagement(boolean)} for
+ * details.
+ * 
+ * @author igor
+ */
+@ConversationScoped
+public class AutoConversation implements IClusterable
+{
+	private boolean automatic;
+
+	public AutoConversation()
+	{
+		automatic = false;
+	}
+
+	public void setAutomatic(boolean automatic)
+	{
+		this.automatic = automatic;
+	}
+
+	public boolean isAutomatic()
+	{
+		return automatic;
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/BehaviorInjector.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/BehaviorInjector.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/BehaviorInjector.java
new file mode 100644
index 0000000..53f0f58
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/BehaviorInjector.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+import org.apache.wicket.IBehaviorInstantiationListener;
+import org.apache.wicket.behavior.Behavior;
+
+/**
+ * Injects components with CDI dependencies
+ * 
+ * @author igor
+ * 
+ */
+class BehaviorInjector extends AbstractInjector implements IBehaviorInstantiationListener
+{
+	/**
+	 * Constructor
+	 * 
+	 * @param container
+	 */
+	public BehaviorInjector(AbstractCdiContainer container)
+	{
+		super(container);
+	}
+
+	@Override
+	public void onInstantiation(Behavior behavior)
+	{
+		inject(behavior);
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/CdiConfiguration.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/CdiConfiguration.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/CdiConfiguration.java
new file mode 100644
index 0000000..56d7dd0
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/CdiConfiguration.java
@@ -0,0 +1,256 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+import java.util.Iterator;
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.Instance;
+import javax.enterprise.inject.Produces;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.CDI;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.request.cycle.RequestCycleListenerCollection;
+
+/**
+ * Configures CDI integration
+ * 
+ * @author igor
+ * 
+ */
+@ApplicationScoped
+public class CdiConfiguration
+{
+    
+	private IConversationPropagation propagation = ConversationPropagation.NONBOOKMARKABLE;
+
+	@Inject
+	BeanManager beanManager;
+        
+	@Inject
+	INonContextualManager nonContextualManager;
+
+	@Inject
+	AbstractCdiContainer container;
+
+	@Inject
+	Instance<ConversationPropagator> conversationPropagatorSource;
+
+	@Inject
+	Instance<ConversationExpiryChecker> conversationExpiryCheckerSource;
+
+	@Inject
+	Instance<DetachEventEmitter> detachEventEmitterSource;
+	
+	private boolean injectComponents = true;
+	private boolean injectApplication = true;
+	private boolean injectSession = true;
+	private boolean injectBehaviors = true;
+	private boolean autoConversationManagement = false;
+
+	/**
+	 * Constructor
+	 * 
+	 * @param beanManager
+	 */
+	public CdiConfiguration()
+	{				
+	}
+
+	/**
+	 * Gets the configured bean manager
+	 * 
+	 * @return bean manager or {@code null} if none
+	 */
+	public BeanManager getBeanManager()
+	{
+		return beanManager;
+	}
+
+	public @Produces @Propagation IConversationPropagation getPropagation()
+	{
+		return propagation;
+	}
+
+	/**
+	 * Checks if auto conversation management is enabled. See
+	 * {@link #setAutoConversationManagement(boolean)} for details.
+	 */
+	public @Produces @Auto boolean isAutoConversationManagement()
+	{
+		return autoConversationManagement;
+	}
+
+	/**
+	 * Toggles automatic conversation management feature.
+	 * 
+	 * Automatic conversation management controls the lifecycle of the conversation based on
+	 * presence of components implementing the {@link ConversationalComponent} interface. If such
+	 * components are found in the page a conversation is marked persistent, and if they are not the
+	 * conversation is marked transient. This greatly simplifies the management of conversation
+	 * lifecycle.
+	 * 
+	 * Sometimes it is necessary to manually control the application. For these cases, once a
+	 * conversation is started {@link AutoConversation} bean can be used to mark the conversation as
+	 * manually-managed.
+	 * 
+	 * @param enabled
+	 * 
+	 * @return {@code this} for easy chaining
+	 */
+	public CdiConfiguration setAutoConversationManagement(boolean enabled)
+	{
+		autoConversationManagement = enabled;
+		return this;
+	}
+
+	public CdiConfiguration setPropagation(IConversationPropagation propagation)
+	{
+		this.propagation = propagation;
+		return this;
+	}
+
+	public INonContextualManager getNonContextualManager()
+	{
+		return nonContextualManager;
+	}
+
+	public CdiConfiguration setNonContextualManager(INonContextualManager nonContextualManager)
+	{
+		this.nonContextualManager = nonContextualManager;
+		return this;
+	}
+
+	public boolean isInjectComponents()
+	{
+		return injectComponents;
+	}
+
+	public CdiConfiguration setInjectComponents(boolean injectComponents)
+	{
+		this.injectComponents = injectComponents;
+		return this;
+	}
+
+	public boolean isInjectApplication()
+	{
+		return injectApplication;
+	}
+
+	public CdiConfiguration setInjectApplication(boolean injectApplication)
+	{
+		this.injectApplication = injectApplication;
+		return this;
+	}
+
+	public boolean isInjectSession()
+	{
+		return injectSession;
+	}
+
+	public CdiConfiguration setInjectSession(boolean injectSession)
+	{
+		this.injectSession = injectSession;
+		return this;
+	}
+
+	public boolean isInjectBehaviors()
+	{
+		return injectBehaviors;
+	}
+
+	public CdiConfiguration setInjectBehaviors(boolean injectBehaviors)
+	{
+		this.injectBehaviors = injectBehaviors;
+		return this;
+	}
+
+	/**
+	 * Configures the specified application
+	 * 
+	 * @param application
+	 * @return
+	 */
+	public AbstractCdiContainer configure(Application application)
+	{		
+		
+		container.bind(application);
+
+		RequestCycleListenerCollection listeners = new RequestCycleListenerCollection();
+		application.getRequestCycleListeners().add(listeners);
+
+		// enable conversation propagation
+		if (getPropagation() != ConversationPropagation.NONE)
+		{                    
+			listeners.add(conversationPropagatorSource.get());
+			application.getComponentPreOnBeforeRenderListeners().add(
+				conversationExpiryCheckerSource.get());
+		}
+
+		// enable detach event
+		listeners.add(detachEventEmitterSource.get());
+
+
+		// inject application instance
+		if (isInjectApplication())
+		{
+			container.getNonContextualManager().postConstruct(application);
+		}
+
+		// enable injection of various framework components
+
+		if (isInjectSession())
+		{
+			application.getSessionListeners().add(new SessionInjector(container));
+		}
+
+		if (isInjectComponents())
+		{
+			application.getComponentInstantiationListeners().add(new ComponentInjector(container));
+		}
+
+		if (isInjectBehaviors())
+		{
+			application.getBehaviorInstantiationListeners().add(new BehaviorInjector(container));
+		}
+
+		// enable cleanup
+
+		application.getApplicationListeners().add(
+			new CdiShutdownCleaner(isInjectApplication()));
+
+		return container;
+	}
+        
+	public static CdiConfiguration get()
+	{
+		BeanManager beanManager = CDI.current().getBeanManager();            
+		Iterator<Bean< ? >> iter = beanManager.getBeans(CdiConfiguration.class).iterator();
+		if (!iter.hasNext())
+		{
+			throw new IllegalStateException("CDI BeanManager cannot find CdiConfiguration");
+		}
+		Bean<CdiConfiguration> bean = (Bean<CdiConfiguration>) iter.next();
+		CreationalContext<CdiConfiguration> ctx = beanManager.createCreationalContext(bean);
+		return (CdiConfiguration) beanManager.getReference(bean, CdiConfiguration.class, ctx);           
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/CdiShutdownCleaner.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/CdiShutdownCleaner.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/CdiShutdownCleaner.java
new file mode 100644
index 0000000..98a6e92
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/CdiShutdownCleaner.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+import javax.enterprise.inject.spi.BeanManager;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.IApplicationListener;
+import org.apache.wicket.util.lang.Args;
+
+/**
+ * Listens to application shutdown and cleans up
+ * 
+ * @author igor
+ */
+class CdiShutdownCleaner implements IApplicationListener
+{
+	
+	private final boolean preDestroyApplication;
+
+	public CdiShutdownCleaner(boolean preDestroyApplication)
+	{		
+		this.preDestroyApplication = preDestroyApplication;
+	}
+
+	@Override
+	public void onAfterInitialized(Application application)
+	{
+		// noop
+	}
+
+	@Override
+	public void onBeforeDestroyed(Application application)
+	{
+		if (preDestroyApplication)
+		{
+			NonContextual.of(application.getClass()).preDestroy(application);
+		}
+		NonContextual.undeploy();
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ComponentInjector.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ComponentInjector.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ComponentInjector.java
new file mode 100644
index 0000000..ce4eee2
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ComponentInjector.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+import java.lang.reflect.Modifier;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.application.IComponentInstantiationListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Injects components with CDI dependencies
+ * 
+ * @author igor
+ * 
+ */
+class ComponentInjector extends AbstractInjector implements IComponentInstantiationListener
+{
+	private static final Logger LOG = LoggerFactory.getLogger(ComponentInjector.class);
+
+	/**
+	 * Constructor
+	 * 
+	 * @param container
+	 */
+	public ComponentInjector(AbstractCdiContainer container)
+	{
+		super(container);
+	}
+
+	@Override
+	public void onInstantiation(Component component)
+	{
+		Class<? extends Component> componentClass = component.getClass();
+
+		if (componentClass.isAnonymousClass() ||
+				(componentClass.isMemberClass() && Modifier.isStatic(componentClass.getModifiers()) == false))
+		{
+			LOG.debug("Skipping non-static inner class '{}' ", componentClass);
+		}
+		else
+		{
+			inject(component);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationExpiredException.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationExpiredException.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationExpiredException.java
new file mode 100644
index 0000000..cee637c
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationExpiredException.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+import org.apache.wicket.Page;
+import org.apache.wicket.request.IRequestHandler;
+
+public class ConversationExpiredException extends RuntimeException
+{
+	private String cid;
+	private Page page;
+	private IRequestHandler handler;
+
+	public ConversationExpiredException(Throwable cause, String cid, Page page,
+		IRequestHandler handler)
+	{
+		super(cause);
+		this.cid = cid;
+		this.page = page;
+		this.handler = handler;
+	}
+
+	public String getCid()
+	{
+		return cid;
+	}
+
+	public Page getPage()
+	{
+		return page;
+	}
+
+	public IRequestHandler getHandler()
+	{
+		return handler;
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationExpiryChecker.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationExpiryChecker.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationExpiryChecker.java
new file mode 100644
index 0000000..aff4627
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationExpiryChecker.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+import java.io.Serializable;
+import javax.enterprise.context.Conversation;
+import javax.enterprise.context.ConversationScoped;
+import javax.inject.Inject;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.Page;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.application.IComponentOnBeforeRenderListener;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.util.lang.Objects;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Checks for conversation expiration during page render and throws a
+ * {@link ConversationExpiredException} when an expired conversation is detected.
+ * 
+ * For example a link that calls {@link Conversation#end()} but does not redirect to a
+ * non-conversation-dependent page will be caught by this listener.
+ * 
+ * @author igor
+ * 
+ */
+@ConversationScoped
+public class ConversationExpiryChecker implements IComponentOnBeforeRenderListener, Serializable
+{
+	private static final long serialVersionUID = 1L;
+	private static final Logger logger = LoggerFactory.getLogger(ConversationExpiryChecker.class);
+	
+	@Inject 
+	AbstractCdiContainer  container;
+
+	@Inject
+	private Conversation conversation;
+
+	public ConversationExpiryChecker()
+	{
+		
+	}
+
+	@Override
+	public void onBeforeRender(Component component)
+	{
+		if (component instanceof Page || RequestCycle.get().find(AjaxRequestTarget.class) != null)
+		{
+			Page page = component.getPage();
+			String cid = container.getConversationMarker(page);
+			if (cid != null && !Objects.isEqual(conversation.getId(), cid))
+			{
+				logger.info("Conversation {} has expired for {}", cid, page);
+				throw new ConversationExpiredException(null, cid, page, RequestCycle.get()
+					.getActiveRequestHandler());
+			}
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationIdMetaKey.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationIdMetaKey.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationIdMetaKey.java
new file mode 100644
index 0000000..72a3d1f
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationIdMetaKey.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+import org.apache.wicket.MetaDataKey;
+
+final class ConversationIdMetaKey extends MetaDataKey<String>
+{
+	static final ConversationIdMetaKey INSTANCE = new ConversationIdMetaKey();
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationPropagation.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationPropagation.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationPropagation.java
new file mode 100644
index 0000000..e937506
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationPropagation.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+import javax.enterprise.context.ConversationScoped;
+import org.apache.wicket.Page;
+import org.apache.wicket.request.IRequestHandler;
+
+/**
+ * Various modes of propagating persistent conversations across requests.
+ * 
+ * @see ConversationScoped
+ * 
+ * @author igor
+ */
+public enum ConversationPropagation implements IConversationPropagation {
+	/** No conversational propagation takes place */
+	NONE {
+		@Override
+		public boolean propagatesViaPage(Page page, IRequestHandler handler)
+		{
+			return false;
+		}
+
+		@Override
+		public boolean propagatesViaParameters(IRequestHandler handler)
+		{
+			return false;
+		}
+	},
+	/**
+	 * Pesistent conversations are propagated between non-bookmarkable pages only
+	 */
+	NONBOOKMARKABLE {
+		@Override
+		public boolean propagatesViaPage(Page page, IRequestHandler handler)
+		{
+			return true;
+		}
+
+		@Override
+		public boolean propagatesViaParameters(IRequestHandler handler)
+		{
+			return false;
+		}
+	},
+	/**
+	 * Persistent conversations are propagated between bookmarkable and non-bookmarkable pages
+	 */
+	ALL {
+		@Override
+		public boolean propagatesViaPage(Page page, IRequestHandler handler)
+		{
+			return true;
+		}
+
+		@Override
+		public boolean propagatesViaParameters(IRequestHandler handler)
+		{
+			return true;
+		}
+	};
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationPropagator.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationPropagator.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationPropagator.java
new file mode 100644
index 0000000..6003328
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationPropagator.java
@@ -0,0 +1,447 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+import java.io.Serializable;
+import javax.enterprise.context.Conversation;
+import javax.enterprise.context.ConversationScoped;
+import javax.enterprise.context.NonexistentConversationException;
+import javax.enterprise.inject.Instance;
+import javax.inject.Inject;
+import org.apache.wicket.Application;
+import org.apache.wicket.Component;
+import org.apache.wicket.MetaDataKey;
+import org.apache.wicket.Page;
+import org.apache.wicket.core.request.handler.BufferedResponseRequestHandler;
+import org.apache.wicket.core.request.handler.IPageClassRequestHandler;
+import org.apache.wicket.core.request.handler.IPageRequestHandler;
+import org.apache.wicket.core.request.mapper.StalePageException;
+import org.apache.wicket.request.IRequestHandler;
+import org.apache.wicket.request.IRequestHandlerDelegate;
+import org.apache.wicket.request.Url;
+import org.apache.wicket.request.component.IRequestablePage;
+import org.apache.wicket.request.cycle.AbstractRequestCycleListener;
+import org.apache.wicket.request.cycle.IRequestCycleListener;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.request.handler.resource.ResourceReferenceRequestHandler;
+import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.wicket.request.resource.PackageResourceReference;
+import org.apache.wicket.util.lang.Objects;
+import org.apache.wicket.util.visit.IVisit;
+import org.apache.wicket.util.visit.IVisitor;
+import org.apache.wicket.util.visit.Visits;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A request cycle listener that takes care of propagating persistent conversations.
+ * 
+ * @see ConversationScoped
+ * 
+ * @author igor
+ */
+@ConversationScoped
+public class ConversationPropagator extends AbstractRequestCycleListener implements Serializable
+{
+	private static final long serialVersionUID = 1L;
+	private static final Logger logger = LoggerFactory.getLogger(ConversationPropagator.class);
+
+	private static final MetaDataKey<String> CID_KEY = ConversationIdMetaKey.INSTANCE;
+
+	private static final MetaDataKey<Boolean> CONVERSATION_STARTED_KEY = new MetaDataKey<Boolean>()
+	{
+	};
+
+	static final String CID_ATTR = "cid";
+       
+	@Inject
+	AbstractCdiContainer container;
+
+	/** propagation mode to use */
+	@Propagation
+	@Inject
+	Instance<IConversationPropagation> propagationSource;
+	
+	@Auto
+	@Inject
+	private boolean auto;
+
+	@Inject
+	Conversation conversation_;
+
+	@Inject
+	AutoConversation autoConversation;
+
+	/**
+	 * Constructor
+	 * 
+	 * @param container
+	 * @param propagation
+	 */
+	public ConversationPropagator()
+	{
+	}
+
+        
+	private Conversation getConversation(RequestCycle cycle)
+	{
+		return Boolean.TRUE.equals(cycle.getMetaData(CONVERSATION_STARTED_KEY)) ? conversation_
+			: null;
+	}
+
+	@Override
+	public void onRequestHandlerResolved(RequestCycle cycle, IRequestHandler handler)
+	{
+		String cid = cycle.getRequest().getRequestParameters().getParameterValue(CID_ATTR).toString();
+		Page page = getPage(handler);
+
+		if (cid == null && page != null)
+		{
+			cid = page.getMetaData(CID_KEY);
+		}
+
+		Conversation current = getConversation(cycle);
+		if (current != null && !Objects.isEqual(current.getId(), cid))
+		{
+			logger.info("Conversation {} has expired for {}", cid, page);
+			throw new ConversationExpiredException(null, cid, page, handler);
+		}
+
+		activateConversationIfNeeded(cycle, handler, cid);
+	}
+
+	@Override
+	public IRequestHandler onException(RequestCycle cycle, Exception ex)
+	{
+		// if we are handling a stale page exception then use its conversation since we are most
+		// likely about to rerender it.
+
+		if (ex instanceof StalePageException)
+		{
+			IRequestablePage requestable = ((StalePageException)ex).getPage();
+			if (requestable instanceof Page)
+			{
+				String cid = container.getConversationMarker((Page)requestable);
+				if (cid != null)
+				{
+					try
+					{
+						activateConversationIfNeeded(cycle, null, cid);
+						return null;
+					}
+					catch (ConversationExpiredException e)
+					{
+						// ignore, we will start a new one below
+					}
+				}
+			}
+		}
+
+		activateConversationIfNeeded(cycle, null, null);
+		return null;
+	}
+
+	private void activateConversationIfNeeded(RequestCycle cycle, IRequestHandler handler,
+		String cid)
+	{
+		Conversation current = getConversation(cycle);
+
+		if (current != null || !activateForHandler(handler))
+		{
+			return;
+		}
+
+		logger.debug("Activating conversation {}", cid);
+
+		try
+		{
+			container.activateConversationalContext(cycle, cid);
+			fireOnAfterConversationStarted(cycle);
+		}
+		catch (NonexistentConversationException e)
+		{
+			logger.info("Unable to restore conversation with id {}", cid, e.getMessage());
+			logger.debug("Unable to restore conversation", e);
+			fireOnAfterConversationStarted(cycle);
+			throw new ConversationExpiredException(e, cid, getPage(handler), handler);
+		}
+
+		cycle.setMetaData(CONVERSATION_STARTED_KEY, true);
+	}
+
+	private void fireOnAfterConversationStarted(RequestCycle cycle)
+	{
+		for (IRequestCycleListener listener : Application.get().getRequestCycleListeners())
+		{
+			if (listener instanceof ICdiAwareRequestCycleListener)
+			{
+				((ICdiAwareRequestCycleListener)listener).onAfterConversationActivated(cycle);
+			}
+		}
+	}
+
+	@Override
+	public void onRequestHandlerExecuted(RequestCycle cycle, IRequestHandler handler)
+	{
+		Conversation conversation = getConversation(cycle);
+
+		if (conversation == null)
+		{
+			return;
+		}
+
+		Page page = getPage(handler);
+
+		if (page == null)
+		{
+			return;
+		}
+
+		// apply auto semantics
+
+		autoEndIfNecessary(page, handler, conversation);
+		autoBeginIfNecessary(page, handler, conversation);
+
+		if (propagationSource.get().propagatesViaPage(page, handler))
+		{
+			// propagate a conversation across non-bookmarkable page instances
+			setConversationOnPage(conversation, page);
+		}
+	}
+
+	@Override
+	public void onRequestHandlerScheduled(RequestCycle cycle, IRequestHandler handler)
+	{
+		// propagate current non-transient conversation to the newly scheduled page
+
+		Conversation conversation = getConversation(cycle);
+
+		if (conversation == null || conversation.isTransient())
+		{
+			return;
+		}
+
+		Page page = getPage(handler);
+		if (page != null)
+		{
+			if (propagationSource.get().propagatesViaPage(page, handler))
+			{
+				// propagate a conversation across non-bookmarkable page instances
+				setConversationOnPage(conversation, page);
+			}
+		}
+
+		if (propagationSource.get().propagatesViaParameters(handler))
+		{
+			// propagate cid to a scheduled bookmarkable page
+
+			logger.debug(
+				"Propagating non-transient conversation {} via page parameters of handler {}",
+				conversation.getId(), handler);
+
+			PageParameters parameters = getPageParameters(handler);
+			if (parameters != null)
+			{
+				parameters.set(CID_ATTR, conversation.getId());
+			}
+		}
+	}
+
+	protected void setConversationOnPage(Conversation conversation, Page page)
+	{
+		if (conversation == null || conversation.isTransient())
+		{
+			logger.debug("Detaching transient conversation {} via meta of page instance {}",
+				(conversation == null ? "null" : conversation.getId()), page);
+
+			page.setMetaData(CID_KEY, null);
+		}
+		else
+		{
+
+			logger.debug("Propagating non-transient conversation {} via meta of page instance {}",
+				conversation.getId(), page);
+
+			page.setMetaData(CID_KEY, conversation.getId());
+		}
+	}
+
+	@Override
+	public void onUrlMapped(RequestCycle cycle, IRequestHandler handler, Url url)
+	{
+		// no need to propagate the conversation to packaged resources, they should never change
+		if (handler instanceof ResourceReferenceRequestHandler)
+		{
+			if (((ResourceReferenceRequestHandler)handler).getResourceReference() instanceof PackageResourceReference)
+			{
+				return;
+			}
+		}
+
+		Conversation conversation = getConversation(cycle);
+
+		if (conversation == null || conversation.isTransient())
+		{
+			return;
+		}
+
+		if (propagationSource.get().propagatesViaParameters(handler))
+		{
+			// propagate cid to bookmarkable pages via urls
+
+			logger.debug("Propagating non-transient conversation {} via url", conversation.getId());
+
+			url.setQueryParameter(CID_ATTR, conversation.getId());
+		}
+	}
+
+	@Override
+	public void onDetach(RequestCycle cycle)
+	{
+		Conversation conversation = getConversation(cycle);
+		if (conversation != null)
+		{
+			logger.debug("Deactivating conversation {}", conversation.getId());
+
+			for (IRequestCycleListener listener : Application.get().getRequestCycleListeners())
+			{
+				if (listener instanceof ICdiAwareRequestCycleListener)
+				{
+					((ICdiAwareRequestCycleListener)listener).onBeforeConversationDeactivated(cycle);
+				}
+			}
+			container.deactivateConversationalContext(cycle);
+
+			cycle.setMetaData(CONVERSATION_STARTED_KEY, null);
+		}
+	}
+
+	/**
+	 * Determines whether or not a conversation should be activated fro the specified handler. This
+	 * method is used to filter out conversation activation for utility handlers such as the
+	 * {@link BufferedResponseRequestHandler}
+	 * 
+	 * @param handler
+	 * @return {@code true} iff a conversation should be activated
+	 */
+	protected boolean activateForHandler(IRequestHandler handler)
+	{
+		if (handler != null)
+		{
+			if (handler instanceof BufferedResponseRequestHandler)
+			{
+				// we do not care about pages that are being rendered from a buffer
+				return false;
+			}
+		}
+		return true;
+	}
+
+	protected void autoBeginIfNecessary(Page page, IRequestHandler handler,
+		Conversation conversation)
+	{
+		if (!auto || conversation == null || !conversation.isTransient() || page == null ||
+			!propagationSource.get().propagatesViaPage(page, handler) || !hasConversationalComponent(page))
+		{
+			return;
+		}
+
+		// auto activate conversation
+
+		conversation.begin();
+		autoConversation.setAutomatic(true);
+
+		logger.debug("Auto-began conversation {} for page {}", conversation.getId(), page);
+	}
+
+	protected void autoEndIfNecessary(Page page, IRequestHandler handler, Conversation conversation)
+	{
+		if (!auto || conversation == null || conversation.isTransient() || page == null ||
+			!propagationSource.get().propagatesViaPage(page, handler) || hasConversationalComponent(page) ||
+			autoConversation.isAutomatic() == false)
+		{
+			return;
+		}
+
+		// auto de-activate conversation
+
+		String cid = conversation.getId();
+
+		autoConversation.setAutomatic(false);
+		conversation.end();
+
+		logger.debug("Auto-ended conversation {} for page {}", cid, page);
+	}
+
+
+	protected boolean hasConversationalComponent(Page page)
+	{
+		Boolean hasConversational = Visits.visit(page, new IVisitor<Component, Boolean>()
+		{
+			@Override
+			public void component(Component object, IVisit<Boolean> visit)
+			{
+				if (object instanceof ConversationalComponent)
+				{
+					visit.stop(true);
+				}
+			}
+		});
+
+		return hasConversational == null ? false : hasConversational;
+	}
+
+	/**
+	 * Resolves a page instance from the request handler iff the page instance is already created
+	 * 
+	 * @param handler
+	 * @return page or {@code null} if none
+	 */
+	public static Page getPage(IRequestHandler handler)
+	{
+		while (handler instanceof IRequestHandlerDelegate)
+		{
+			handler = ((IRequestHandlerDelegate)handler).getDelegateHandler();
+		}
+
+		if (handler instanceof IPageRequestHandler)
+		{
+			IPageRequestHandler pageHandler = (IPageRequestHandler)handler;
+			if (pageHandler.isPageInstanceCreated())
+			{
+				return (Page)pageHandler.getPage();
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Resolves page parameters from a request handler
+	 * 
+	 * @param handler
+	 * @return page parameters or {@code null} if none
+	 */
+	protected PageParameters getPageParameters(IRequestHandler handler)
+	{
+		if (handler instanceof IPageClassRequestHandler)
+		{
+			IPageClassRequestHandler pageHandler = (IPageClassRequestHandler)handler;
+			return pageHandler.getPageParameters();
+		}
+		return null;
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationalComponent.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationalComponent.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationalComponent.java
new file mode 100644
index 0000000..e041a87
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ConversationalComponent.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+/**
+ * Marks a component that requires a conversation. This marker is used by the automatic conversation
+ * management feature ({@link CdiConfiguration#setAutoConversationManagement(boolean)}) to
+ * automatically begin and end conversations based on the presence of these components in the
+ * component hierarchy of pages (can be applied to the page itself).
+ * 
+ * @author igor
+ */
+public interface ConversationalComponent
+{
+
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/DetachEvent.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/DetachEvent.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/DetachEvent.java
new file mode 100644
index 0000000..ac99ec3
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/DetachEvent.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+/**
+ * Fired when request cycle is detached
+ * 
+ * @author igor
+ * 
+ */
+public class DetachEvent
+{
+
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/DetachEventEmitter.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/DetachEventEmitter.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/DetachEventEmitter.java
new file mode 100644
index 0000000..e60ec2e
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/DetachEventEmitter.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+import java.io.Serializable;
+import javax.enterprise.context.SessionScoped;
+import javax.enterprise.event.Event;
+import javax.inject.Inject;
+
+import org.apache.wicket.MetaDataKey;
+import org.apache.wicket.request.IRequestHandler;
+import org.apache.wicket.request.cycle.AbstractRequestCycleListener;
+import org.apache.wicket.request.cycle.RequestCycle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Request cycle listener that fires the {@link DetachEvent} event
+ * 
+ * @author igor
+ * 
+ */
+@SessionScoped
+public class DetachEventEmitter extends AbstractRequestCycleListener implements Serializable
+{
+	private static final long serialVersionUID = 1L;
+	private static final Logger logger = LoggerFactory.getLogger(DetachEventEmitter.class);
+
+	private static final MetaDataKey<Boolean> DETACH_SCHEDULED_KEY = new MetaDataKey<Boolean>()
+	{
+	};
+
+	@Inject
+	Event<DetachEvent> detachEvent;
+
+	@Inject
+	AbstractCdiContainer container;
+	/**
+	 * Constructor
+	 * 
+	 * @param container
+	 */
+	public DetachEventEmitter()
+	{		
+	}
+
+	@Override
+	public void onRequestHandlerResolved(RequestCycle cycle, IRequestHandler handler)
+	{
+		// this is a wicket request, schedule detach event to be fired
+
+		cycle.setMetaData(DETACH_SCHEDULED_KEY, true);
+	}
+
+	@Override
+	public void onDetach(RequestCycle cycle)
+	{
+		if (Boolean.TRUE.equals(cycle.getMetaData(DETACH_SCHEDULED_KEY)))
+		{
+			logger.debug("Firing Detach event {}", cycle.getRequest().getUrl());
+
+			detachEvent.fire(new DetachEvent());
+			
+			cycle.setMetaData(DETACH_SCHEDULED_KEY, null);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ICdiAwareRequestCycleListener.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ICdiAwareRequestCycleListener.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ICdiAwareRequestCycleListener.java
new file mode 100644
index 0000000..c8cb1ca
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/ICdiAwareRequestCycleListener.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+import org.apache.wicket.request.cycle.IRequestCycleListener;
+import org.apache.wicket.request.cycle.RequestCycle;
+
+public interface ICdiAwareRequestCycleListener extends IRequestCycleListener
+{
+	/**
+	 * Called right after a conversation context for this request is activated
+	 * 
+	 * @param cycle
+	 *            request cycle
+	 */
+	void onAfterConversationActivated(RequestCycle cycle);
+
+	/**
+	 * Called right before the current conversation context is deactivated
+	 * 
+	 * @param cycle
+	 *            request cycle
+	 */
+	void onBeforeConversationDeactivated(RequestCycle cycle);
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/IConversationPropagation.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/IConversationPropagation.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/IConversationPropagation.java
new file mode 100644
index 0000000..154b077
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/IConversationPropagation.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+import org.apache.wicket.Page;
+import org.apache.wicket.request.IRequestHandler;
+
+/**
+ * A strategy that specifies how conversations should be propagated between pages/resources.
+ * {@link ConversationPropagation} provides sensible default implementations of this interface.
+ * 
+ * @author papegaaij
+ */
+public interface IConversationPropagation
+{
+	/**
+	 * Indicates if the conversation should be propagated via page metadata (on an instance) for the
+	 * given page and request handler.
+	 * 
+	 * @param page
+	 *            The page on which the tag will be set.
+	 * @param handler
+	 *            The current request handler
+	 * @return true if the conversation should be propagated to the given page instance.
+	 */
+	public boolean propagatesViaPage(Page page, IRequestHandler handler);
+
+	/**
+	 * Indicates if the conversation should be propagated via url-parameters for the given request
+	 * handler. This can either be a get parameter in a rendered url, or via page parameters.
+	 * 
+	 * @param handler
+	 *            The current request handler
+	 * @return true if the conversation should be propagated for the given request handler.
+	 */
+	public boolean propagatesViaParameters(IRequestHandler handler);
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/INonContextualManager.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/INonContextualManager.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/INonContextualManager.java
new file mode 100644
index 0000000..ab95807
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/INonContextualManager.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+import org.apache.wicket.Component;
+
+/**
+ * Manages lifecycle of non-contextual objects like {@link Component} instances, etc
+ * 
+ * @author igor
+ * 
+ */
+public interface INonContextualManager
+{
+	/**
+	 * Inject a noncontextual instance
+	 * 
+	 * @param <T>
+	 * @param instance
+	 */
+	<T> void inject(T instance);
+	
+	/**
+	 * Inject a noncontextual instance and invokes any {@link PostConstruct} callbacks
+	 * 
+	 * @param <T>
+	 * @param instance
+	 */
+	<T> void postConstruct(T instance);
+
+	/**
+	 * Invokes any {@link PreDestroy} callbacks and cleans up
+	 * 
+	 * @param <T>
+	 * @param instance
+	 */
+	<T> void preDestroy(T instance);
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/NonContextual.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/NonContextual.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/NonContextual.java
new file mode 100644
index 0000000..135075a
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/NonContextual.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.CDI;
+import javax.enterprise.inject.spi.InjectionTarget;
+
+import org.apache.wicket.util.collections.ClassMetaCache;
+
+/**
+ * Manages lifecycle of non-contextual (non-CDI-managed) objects
+ * 
+ * @author igor
+ * 
+ * @param <T>
+ */
+public class NonContextual<T>
+{
+	private static final Object lock = new Object();
+	private static volatile Map<BeanManager, ClassMetaCache<NonContextual<?>>> cache = Collections.emptyMap();
+
+	final InjectionTarget<T> it;
+	
+	/**
+	 * Undeploys specified bean manager from cache
+	 * 
+	 * @param beanManager
+	 */
+	public static void undeploy()
+	{
+		if (cache.containsKey(CDI.current().getBeanManager()))
+		{
+			synchronized (lock)
+			{
+				// copy-on-write the cache
+				Map<BeanManager, ClassMetaCache<NonContextual<?>>> newCache = new WeakHashMap<BeanManager, ClassMetaCache<NonContextual<?>>>(
+					cache);
+				newCache.remove(CDI.current().getBeanManager());
+				cache = Collections.unmodifiableMap(newCache);
+			}
+		}
+	}
+
+	/**
+	 * Factory method for creating noncontextual instances
+	 * 
+	 * @param <T>
+	 * @param clazz
+	 * @param manager
+	 * @return
+	 */
+	public static <T> NonContextual<T> of(Class<? extends T> clazz)
+	{
+		ClassMetaCache<NonContextual<?>> meta = getCache();
+
+		@SuppressWarnings("unchecked")
+		NonContextual<T> nc = (NonContextual<T>)meta.get(clazz);
+
+		if (nc == null)
+		{
+			nc = new NonContextual<T>(clazz);
+			meta.put(clazz, nc);
+		}
+		return nc;
+	}
+
+	private static ClassMetaCache<NonContextual<?>> getCache()
+	{
+		ClassMetaCache<NonContextual<?>> meta = cache.get(CDI.current().getBeanManager());
+		if (meta == null)
+		{
+			synchronized (lock)
+			{
+                                BeanManager manager = CDI.current().getBeanManager(); 
+				meta = cache.get(manager);
+				if (meta == null)
+				{
+					meta = new ClassMetaCache<NonContextual<?>>();
+
+					// copy-on-write the cache
+					Map<BeanManager, ClassMetaCache<NonContextual<?>>> newCache = new WeakHashMap<BeanManager, ClassMetaCache<NonContextual<?>>>(
+						cache);
+					newCache.put(manager, meta);
+					cache = Collections.unmodifiableMap(newCache);
+				}
+			}
+		}
+		return meta;
+	}
+
+	@SuppressWarnings("unchecked")
+	private NonContextual(Class<? extends T> clazz)
+	{
+		BeanManager manager = CDI.current().getBeanManager();
+		AnnotatedType<? extends T> type = manager.createAnnotatedType(clazz);
+		this.it = (InjectionTarget<T>)manager.createInjectionTarget(type);
+	}
+
+	/**
+	 * Injects the instance and calls any {@link PostConstruct} methods
+	 * 
+	 * @param instance
+	 */
+	public void postConstruct(T instance)
+	{
+		CreationalContext<T> cc = CDI.current().getBeanManager().createCreationalContext(null);
+		it.inject(instance, cc);
+		it.postConstruct(instance);
+	}
+	
+	/**
+	 * Injects the instance
+	 * 
+	 * @param instance
+	 */
+	public void inject(T instance)
+	{
+		CreationalContext<T> cc = CDI.current().getBeanManager().createCreationalContext(null);
+		it.inject(instance, cc);
+	}
+
+	/**
+	 * Calls any {@link PreDestroy} methods and destroys any injected dependencies that need to be
+	 * destroyed.
+	 * 
+	 * @param instance
+	 */
+	public void preDestroy(T instance)
+	{
+		it.preDestroy(instance);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/NonContextualManager.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/NonContextualManager.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/NonContextualManager.java
new file mode 100644
index 0000000..9289f9d
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/NonContextualManager.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.enterprise.context.ApplicationScoped;
+
+import org.apache.wicket.util.lang.Args;
+
+/**
+ * Default implementation of {@link INonContextualManager} using {@link NonContextual} helper
+ * 
+ * @author igor
+ * 
+ */
+@ApplicationScoped
+class NonContextualManager implements INonContextualManager
+{
+	
+	/**
+	 * Constructor
+	 */
+	public NonContextualManager()
+	{		
+	}
+
+	/**
+	 * Performs dependency injection on the noncontextual instance
+	 */
+	@Override
+	public <T> void inject(T instance)
+	{
+		Args.notNull(instance, "instance");
+		NonContextual.of(instance.getClass()).inject(instance);
+	}
+
+	/**
+	 * Performs dependency injection on the noncontextual instance and invokes any
+	 * {@link PostConstruct} callbacks
+	 */
+	@Override
+	public <T> void postConstruct(T instance)
+	{
+		Args.notNull(instance, "instance");
+		NonContextual.of(instance.getClass()).postConstruct(instance);
+	}
+
+	/**
+	 * Invokes any {@link PreDestroy} callbacks and cleans up any injected dependencies
+	 */
+	@Override
+	public <T> void preDestroy(T instance)
+	{
+		Args.notNull(instance, "instance");
+		NonContextual.of(instance.getClass()).preDestroy(instance);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/Propagation.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/Propagation.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/Propagation.java
new file mode 100644
index 0000000..0fb1c30
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/Propagation.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import javax.inject.Qualifier;
+
+/**
+ * Qualifier used to inject the Propagation Method 
+ * 
+ * @author jsarman
+ * 
+ */
+@Qualifier
+@Target( { ElementType.TYPE,ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Propagation
+{
+
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/SessionInjector.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/SessionInjector.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/SessionInjector.java
new file mode 100644
index 0000000..2b75baf
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/java/org/apache/wicket/cdi/SessionInjector.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+import org.apache.wicket.ISessionListener;
+import org.apache.wicket.Session;
+
+/**
+ * Injects components with CDI dependencies
+ * 
+ * @author igor
+ * 
+ */
+class SessionInjector extends AbstractInjector implements ISessionListener
+{
+	/**
+	 * Constructor
+	 * 
+	 * @param container
+	 */
+	public SessionInjector(AbstractCdiContainer container)
+	{
+		super(container);
+	}
+
+	@Override
+	public void onCreated(Session session)
+	{
+		postConstruct(session);
+	}
+
+	@Override
+	public void onUnbound(String sessionId)
+	{
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/resources/META-INF/beans.xml
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/resources/META-INF/beans.xml b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/wicket/blob/befbf9c7/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/test/java/org/apache/wicket/cdi/ApacheLicenceHeaderTest.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/test/java/org/apache/wicket/cdi/ApacheLicenceHeaderTest.java b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/test/java/org/apache/wicket/cdi/ApacheLicenceHeaderTest.java
new file mode 100644
index 0000000..92efb73
--- /dev/null
+++ b/wicket-experimental/wicket-cdi-1.1/wicket-cdi-1.1-core/src/test/java/org/apache/wicket/cdi/ApacheLicenceHeaderTest.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.wicket.cdi;
+
+import java.util.Arrays;
+
+import org.apache.wicket.util.license.ApacheLicenseHeaderTestCase;
+
+/**
+ * Test that the license headers are in place in this project. The tests are run from
+ * {@link ApacheLicenseHeaderTestCase}, but you can add project specific tests here if needed.
+ * 
+ * @author Frank Bille Jensen (frankbille)
+ */
+public class ApacheLicenceHeaderTest extends ApacheLicenseHeaderTestCase
+{
+	/**
+	 * Construct.
+	 */
+	public ApacheLicenceHeaderTest()
+	{
+		xmlIgnore.add(".settings");
+		xmlIgnore.add("src/main/resources/META-INF/beans.xml");
+		xmlPrologIgnore = Arrays.asList("src");
+	}
+}