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");
+ }
+}