- 4.0.0
+
+ 4.0.0
+
org.javaee7
- javaee7-samples
+ samples-parent
1.0-SNAPSHOT
- ../pom.xml
-
- org.javaee7.ejb
- ejb-samples
- 1.0-SNAPSHOT
+
+ ejb
pom
- Java EE 7 EJB Samples
+
+ Java EE 7 Sample: ejb
embeddable
lifecycle
+ remote
singleton
stateful
stateless
timer
async-ejb
+
+
+
+ org.javaee7
+ test-utils
+ ${project.version}
+ test
+
+
diff --git a/ejb/remote/pom.xml b/ejb/remote/pom.xml
new file mode 100644
index 000000000..c17c33b37
--- /dev/null
+++ b/ejb/remote/pom.xml
@@ -0,0 +1,20 @@
+
+ 4.0.0
+
+
+ org.javaee7
+ ejb
+ 1.0-SNAPSHOT
+
+
+ ejb-remote
+ pom
+
+ Java EE 7 Sample: ejb - remote
+
+
+ vendor
+ roles-allowed
+
+
+
diff --git a/ejb/remote/roles-allowed-ssl/pom.xml b/ejb/remote/roles-allowed-ssl/pom.xml
new file mode 100644
index 000000000..446ccc584
--- /dev/null
+++ b/ejb/remote/roles-allowed-ssl/pom.xml
@@ -0,0 +1,51 @@
+
+ 4.0.0
+
+
+ org.javaee7
+ ejb-remote
+ 1.0-SNAPSHOT
+
+
+ ejb-remote-roles-allowed-ssl
+ jar
+
+ Java EE 7 Sample: ejb - remote - Roles Allowed
+
+
+
+ payara-ci-managed
+
+
+ org.javaee7.ejb.remote.vendor
+ ejb.remote.vendor.payara-glassfish
+ 1.0-SNAPSHOT
+
+
+
+
+
+ payara-remote
+
+
+ org.javaee7.ejb.remote.vendor
+ ejb.remote.vendor.payara-glassfish
+ 1.0-SNAPSHOT
+
+
+
+
+
+ glassfish-remote
+
+
+ org.javaee7.ejb.remote.vendor
+ ejb.remote.vendor.payara-glassfish
+ 1.0-SNAPSHOT
+
+
+
+
+
+
+
diff --git a/ejb/remote/roles-allowed-ssl/src/main/java/org/javaee7/ejb/remote/ssl/Bean.java b/ejb/remote/roles-allowed-ssl/src/main/java/org/javaee7/ejb/remote/ssl/Bean.java
new file mode 100644
index 000000000..f9d17c74d
--- /dev/null
+++ b/ejb/remote/roles-allowed-ssl/src/main/java/org/javaee7/ejb/remote/ssl/Bean.java
@@ -0,0 +1,20 @@
+/** Copyright Payara Services Limited **/
+package org.javaee7.ejb.remote.ssl;
+
+import java.io.Serializable;
+
+import javax.annotation.security.RolesAllowed;
+import javax.ejb.Stateless;
+
+@Stateless
+public class Bean implements BeanRemote, Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ @RolesAllowed("g1")
+ public String method() {
+ return "method";
+ }
+
+}
diff --git a/ejb/remote/roles-allowed-ssl/src/main/java/org/javaee7/ejb/remote/ssl/BeanRemote.java b/ejb/remote/roles-allowed-ssl/src/main/java/org/javaee7/ejb/remote/ssl/BeanRemote.java
new file mode 100644
index 000000000..62b4e21b9
--- /dev/null
+++ b/ejb/remote/roles-allowed-ssl/src/main/java/org/javaee7/ejb/remote/ssl/BeanRemote.java
@@ -0,0 +1,9 @@
+/** Copyright Payara Services Limited **/
+package org.javaee7.ejb.remote.ssl;
+
+import javax.ejb.Remote;
+
+@Remote
+public interface BeanRemote {
+ String method();
+}
diff --git a/ejb/remote/roles-allowed-ssl/src/main/resources/META-INF/application.xml b/ejb/remote/roles-allowed-ssl/src/main/resources/META-INF/application.xml
new file mode 100644
index 000000000..d90462368
--- /dev/null
+++ b/ejb/remote/roles-allowed-ssl/src/main/resources/META-INF/application.xml
@@ -0,0 +1,20 @@
+
+
+
+
+ myapp
+
+
+ myEJB.jar
+
+
+
+
+ test.war
+ /test
+
+
+
+
diff --git a/ejb/remote/roles-allowed-ssl/src/main/resources/META-INF/glassfish-ejb-jar.xml b/ejb/remote/roles-allowed-ssl/src/main/resources/META-INF/glassfish-ejb-jar.xml
new file mode 100644
index 000000000..6c114b352
--- /dev/null
+++ b/ejb/remote/roles-allowed-ssl/src/main/resources/META-INF/glassfish-ejb-jar.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+ Bean
+
+
+ REQUIRED
+ REQUIRED
+ SUPPORTED
+ SUPPORTED
+
+
+ USERNAME_PASSWORD
+ default
+ true
+
+
+ REQUIRED
+
+
+
+
+
diff --git a/ejb/remote/roles-allowed-ssl/src/test/java/org/javaee7/ejb/remote/ssl/RemoteBeanTest.java b/ejb/remote/roles-allowed-ssl/src/test/java/org/javaee7/ejb/remote/ssl/RemoteBeanTest.java
new file mode 100644
index 000000000..8773c5803
--- /dev/null
+++ b/ejb/remote/roles-allowed-ssl/src/test/java/org/javaee7/ejb/remote/ssl/RemoteBeanTest.java
@@ -0,0 +1,141 @@
+/** Copyright Payara Services Limited **/
+package org.javaee7.ejb.remote.ssl;
+
+import static javax.naming.Context.SECURITY_PROTOCOL;
+import static org.javaee7.ServerOperations.addUsersToContainerIdentityStore;
+import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
+import static org.jboss.shrinkwrap.api.asset.EmptyAsset.INSTANCE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeTrue;
+import static org.omnifaces.utils.security.Certificates.createTempJKSTrustStore;
+import static org.omnifaces.utils.security.Certificates.getCertificateChainFromServer;
+import static org.omnifaces.utils.security.Certificates.getHostFromCertificate;
+import static org.omnifaces.utils.security.Certificates.setSystemTrustStore;
+
+import java.net.URL;
+import java.security.cert.X509Certificate;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+
+import org.javaee7.RemoteEJBContextFactory;
+import org.javaee7.RemoteEJBContextProvider;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.container.test.api.RunAsClient;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.spec.EnterpriseArchive;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * This class demonstrates and tests how to request an EJB bean from a remote server.
+ *
+ *
+ * {@link RemoteEJBContextProvider} is used, which is a test artifact abstracting the different
+ * ways this is done for different servers.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class RemoteBeanTest {
+
+ @ArquillianResource
+ private URL base;
+
+ private RemoteEJBContextProvider remoteEJBContextProvider;
+
+ @Deployment
+ public static Archive deployment() {
+ try {
+ // Add user u1 with password p1 and group g1 to the container's native identity store
+ addUsersToContainerIdentityStore();
+
+ Archive archive =
+ // EAR module
+ create(EnterpriseArchive.class, "my.ear")
+ .setApplicationXML("META-INF/application.xml")
+
+ // EJB module
+ .addAsModule(
+ create(JavaArchive.class, "myEJB.jar")
+ .addClasses(Bean.class, BeanRemote.class)
+ .addAsResource("META-INF/glassfish-ejb-jar.xml")
+ .addAsManifestResource(INSTANCE, "beans.xml")
+ )
+
+ // Web module
+ .addAsModule(
+ create(WebArchive.class, "test.war")
+ );
+
+ System.out.println("\n**** Deploying archive: " + archive.toString(true) + " \n");
+
+ return archive;
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ }
+ }
+
+ @Before
+ public void before() {
+ remoteEJBContextProvider = RemoteEJBContextFactory.getProvider();
+ assumeTrue(
+ "No RemoteEJBContextProvider available in current profile",
+ remoteEJBContextProvider != null);
+ }
+
+ @After
+ public void after() {
+ remoteEJBContextProvider.releaseContext();
+ }
+
+ @Test
+ @RunAsClient
+ public void callProtectedRemoteBean() throws NamingException {
+
+ // Obtain the JNDI naming context in a vendor specific way.
+ Context ejbRemoteContext = remoteEJBContextProvider.getContextWithCredentialsSet("u1", "p1");
+
+ ejbRemoteContext.addToEnvironment(SECURITY_PROTOCOL, "ssl");
+
+ System.out.println("\n**** Quering server for its certificate at " + base.getHost() + ":" + "3920" + "\n");
+
+ // Get the certificate from the server, using the EJB SSL port
+ X509Certificate[] serverCertificateChain = getCertificateChainFromServer(base.getHost(), 3920);
+
+ for (X509Certificate certificate : serverCertificateChain) {
+ System.out.println("\n**** Server presented certificate:" + certificate + " \n");
+ }
+
+ // Create a trust store on disk containing the servers's certificates
+ String trustStorePath = createTempJKSTrustStore(serverCertificateChain);
+
+ System.out.println("\n**** Temp trust store with server certificates created at: " + trustStorePath + " \n");
+
+ // Set the newly created trust store as the system wide trust store
+ setSystemTrustStore(trustStorePath);
+
+ // Get the host name from the certificate the server presented, and use that for the host
+ // to ultimately do our SSL request to.
+ String host = getHostFromCertificate(serverCertificateChain);
+ ejbRemoteContext.addToEnvironment("org.omg.CORBA.ORBInitialHost", host);
+
+ System.out.println("\n**** Obtained host \"" + host + "\" from server certificate and will use that for request \n");
+
+ // Do the actual request to the server for our remote EJB
+ BeanRemote beanRemote = (BeanRemote) ejbRemoteContext.lookup("java:global/my/myEJB/Bean");
+
+ System.out.println("\n**** Remote EJB obtained via SSL: " + beanRemote + " \n");
+
+ assertEquals("method", beanRemote.method());
+ }
+
+}
\ No newline at end of file
diff --git a/ejb/remote/roles-allowed-ssl/src/test/resources/addUsersPayara.txt b/ejb/remote/roles-allowed-ssl/src/test/resources/addUsersPayara.txt
new file mode 100644
index 000000000..037cdbd6f
--- /dev/null
+++ b/ejb/remote/roles-allowed-ssl/src/test/resources/addUsersPayara.txt
@@ -0,0 +1 @@
+create-file-user --groups g1 --passwordfile ${project.build.directory}/test-classes/password.txt u1
\ No newline at end of file
diff --git a/ejb/remote/roles-allowed-ssl/src/test/resources/password.txt b/ejb/remote/roles-allowed-ssl/src/test/resources/password.txt
new file mode 100644
index 000000000..c00bb4cac
--- /dev/null
+++ b/ejb/remote/roles-allowed-ssl/src/test/resources/password.txt
@@ -0,0 +1 @@
+AS_ADMIN_USERPASSWORD=p1
diff --git a/ejb/remote/roles-allowed/pom.xml b/ejb/remote/roles-allowed/pom.xml
new file mode 100644
index 000000000..9d4c87aef
--- /dev/null
+++ b/ejb/remote/roles-allowed/pom.xml
@@ -0,0 +1,51 @@
+
+ 4.0.0
+
+
+ org.javaee7
+ ejb-remote
+ 1.0-SNAPSHOT
+
+
+ ejb-remote-roles-allowed
+ war
+
+ Java EE 7 Sample: ejb - remote - Roles Allowed
+
+
+
+ payara-ci-managed
+
+
+ org.javaee7.ejb.remote.vendor
+ ejb.remote.vendor.payara-glassfish
+ 1.0-SNAPSHOT
+
+
+
+
+
+ payara-remote
+
+
+ org.javaee7.ejb.remote.vendor
+ ejb.remote.vendor.payara-glassfish
+ 1.0-SNAPSHOT
+
+
+
+
+
+ glassfish-remote
+
+
+ org.javaee7.ejb.remote.vendor
+ ejb.remote.vendor.payara-glassfish
+ 1.0-SNAPSHOT
+
+
+
+
+
+
+
diff --git a/ejb/remote/roles-allowed/src/main/java/org/javaee7/ejb/remote/remote/Bean.java b/ejb/remote/roles-allowed/src/main/java/org/javaee7/ejb/remote/remote/Bean.java
new file mode 100644
index 000000000..97d9003f5
--- /dev/null
+++ b/ejb/remote/roles-allowed/src/main/java/org/javaee7/ejb/remote/remote/Bean.java
@@ -0,0 +1,20 @@
+/** Copyright Payara Services Limited **/
+package org.javaee7.ejb.remote.remote;
+
+import java.io.Serializable;
+
+import javax.annotation.security.RolesAllowed;
+import javax.ejb.Stateless;
+
+@Stateless
+public class Bean implements BeanRemote, Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ @RolesAllowed("g1")
+ public String method() {
+ return "method";
+ }
+
+}
diff --git a/ejb/remote/roles-allowed/src/main/java/org/javaee7/ejb/remote/remote/BeanRemote.java b/ejb/remote/roles-allowed/src/main/java/org/javaee7/ejb/remote/remote/BeanRemote.java
new file mode 100644
index 000000000..94432c4a3
--- /dev/null
+++ b/ejb/remote/roles-allowed/src/main/java/org/javaee7/ejb/remote/remote/BeanRemote.java
@@ -0,0 +1,9 @@
+/** Copyright Payara Services Limited **/
+package org.javaee7.ejb.remote.remote;
+
+import javax.ejb.Remote;
+
+@Remote
+public interface BeanRemote {
+ String method();
+}
diff --git a/ejb/remote/roles-allowed/src/test/java/org/javaee7/ejb/remote/RemoteBeanTest.java b/ejb/remote/roles-allowed/src/test/java/org/javaee7/ejb/remote/RemoteBeanTest.java
new file mode 100644
index 000000000..477ce5435
--- /dev/null
+++ b/ejb/remote/roles-allowed/src/test/java/org/javaee7/ejb/remote/RemoteBeanTest.java
@@ -0,0 +1,78 @@
+/** Copyright Payara Services Limited **/
+package org.javaee7.ejb.remote;
+
+import static org.javaee7.ServerOperations.addUsersToContainerIdentityStore;
+import static org.jboss.shrinkwrap.api.asset.EmptyAsset.INSTANCE;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assume.assumeTrue;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+
+import org.javaee7.RemoteEJBContextFactory;
+import org.javaee7.RemoteEJBContextProvider;
+import org.javaee7.ejb.remote.remote.Bean;
+import org.javaee7.ejb.remote.remote.BeanRemote;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.container.test.api.RunAsClient;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * This class demonstrates and tests how to request an EJB bean from a remote server.
+ *
+ *
+ * {@link RemoteEJBContextProvider} is used, which is a test artifact abstracting the different
+ * ways this is done for different servers.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class RemoteBeanTest {
+
+ private RemoteEJBContextProvider remoteEJBContextProvider;
+
+ @Deployment
+ public static Archive> deployment() {
+
+ // Add user u1 with password p1 and group g1 to the container's native identity store
+ addUsersToContainerIdentityStore();
+
+ return ShrinkWrap.create(JavaArchive.class)
+ .addClasses(Bean.class, BeanRemote.class)
+ .addAsManifestResource(INSTANCE, "beans.xml");
+ }
+
+ @Before
+ public void before() {
+ remoteEJBContextProvider = RemoteEJBContextFactory.getProvider();
+ assumeTrue(
+ "No RemoteEJBContextProvider available in current profile",
+ remoteEJBContextProvider != null);
+ }
+
+ @After
+ public void after() {
+ remoteEJBContextProvider.releaseContext();
+ }
+
+ @Test
+ @RunAsClient
+ public void callProtectedRemoteBean() throws NamingException {
+
+ // Obtain the JNDI naming context in a vendor specific way.
+ Context ejbRemoteContext = remoteEJBContextProvider.getContextWithCredentialsSet("u1", "p1");
+
+ BeanRemote beanRemote = (BeanRemote) ejbRemoteContext.lookup("java:global/test/Bean");
+
+ assertEquals("method", beanRemote.method());
+ }
+
+}
\ No newline at end of file
diff --git a/ejb/remote/roles-allowed/src/test/resources/addUsersPayara.txt b/ejb/remote/roles-allowed/src/test/resources/addUsersPayara.txt
new file mode 100644
index 000000000..037cdbd6f
--- /dev/null
+++ b/ejb/remote/roles-allowed/src/test/resources/addUsersPayara.txt
@@ -0,0 +1 @@
+create-file-user --groups g1 --passwordfile ${project.build.directory}/test-classes/password.txt u1
\ No newline at end of file
diff --git a/ejb/remote/roles-allowed/src/test/resources/password.txt b/ejb/remote/roles-allowed/src/test/resources/password.txt
new file mode 100644
index 000000000..c00bb4cac
--- /dev/null
+++ b/ejb/remote/roles-allowed/src/test/resources/password.txt
@@ -0,0 +1 @@
+AS_ADMIN_USERPASSWORD=p1
diff --git a/ejb/remote/vendor/README.md b/ejb/remote/vendor/README.md
new file mode 100644
index 000000000..fb90f61af
--- /dev/null
+++ b/ejb/remote/vendor/README.md
@@ -0,0 +1,12 @@
+# Java EE 7 Samples: EJB - Remote - Vendor #
+
+This module contains vendor specific implementations to obtain the JNDI context from where remote EJB beans can be requested
+from with a username/password credential.
+
+## Implementations ##
+
+ - payara-glassfish - An implementation that works for both Payara and GlassFish
+
+
+
+
diff --git a/ejb/remote/vendor/payara-glassfish/README.md b/ejb/remote/vendor/payara-glassfish/README.md
new file mode 100644
index 000000000..b1a3a57bb
--- /dev/null
+++ b/ejb/remote/vendor/payara-glassfish/README.md
@@ -0,0 +1,9 @@
+# Java EE 7 Samples: EJB - Remote - Vendor - Payara and GlassFish #
+
+This modules contains a class that returns a JNDI context suitable for remote lookups against the default URL
+for a remote Payara or GlassFish server (localhost). It sets the provided credentials
+in a Payara/GlassFish specific way and puts the required client jar on the classpath.
+
+
+
+
diff --git a/ejb/remote/vendor/payara-glassfish/pom.xml b/ejb/remote/vendor/payara-glassfish/pom.xml
new file mode 100644
index 000000000..7ddb5b747
--- /dev/null
+++ b/ejb/remote/vendor/payara-glassfish/pom.xml
@@ -0,0 +1,31 @@
+
+
+
+
+ 4.0.0
+
+
+ org.javaee7
+ ejb-remote-vendor
+ 1.0-SNAPSHOT
+
+
+ org.javaee7.ejb.remote.vendor
+ ejb.remote.vendor.payara-glassfish
+ 1.0-SNAPSHOT
+
+ Java EE 7 Sample: ejb - remote - vendor - Payara and GlassFish Remote EJB Provider
+
+
+
+ org.javaee7
+ test-utils
+ 1.0-SNAPSHOT
+
+
+ org.glassfish.main.appclient
+ gf-client
+ ${glassfish.client.version}
+
+
+
diff --git a/ejb/remote/vendor/payara-glassfish/src/main/java/org/javaee7/PayaraEJBContextProvider.java b/ejb/remote/vendor/payara-glassfish/src/main/java/org/javaee7/PayaraEJBContextProvider.java
new file mode 100644
index 000000000..0703f5f25
--- /dev/null
+++ b/ejb/remote/vendor/payara-glassfish/src/main/java/org/javaee7/PayaraEJBContextProvider.java
@@ -0,0 +1,46 @@
+/** Copyright Payara Services Limited **/
+package org.javaee7;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.security.auth.Subject;
+
+import com.sun.enterprise.security.auth.login.common.PasswordCredential;
+import com.sun.enterprise.security.common.ClientSecurityContext;
+
+/**
+ * This class returns a JNDI context suitable for remote lookups against the default URL
+ * for a remote Payara or GlassFish server (localhost). It sets the provided credentials
+ * in a Payara/GlassFish specific way.
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class PayaraEJBContextProvider implements RemoteEJBContextProvider {
+
+ @Override
+ public Context getContextWithCredentialsSet(String username, String password) {
+
+ // Create a new subject with a password credential
+ Subject subject = new Subject();
+ subject.getPrivateCredentials().add(new PasswordCredential(username, password.toCharArray(), "default"));
+
+ // Store this subject into a global variable where the CORBA/IIOP code will pick it up.
+ ClientSecurityContext.setCurrent(new ClientSecurityContext(username, subject));
+
+ // Note: no need for setting "java.naming.factory.initial", since this is already defined
+ // by jndi.properties in the glassfish-naming.jar on the classpath.
+ try {
+ return new InitialContext();
+ } catch (NamingException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public void releaseContext() {
+ ClientSecurityContext.setCurrent(null);
+ }
+
+}
diff --git a/ejb/remote/vendor/payara-glassfish/src/main/resources/META-INF/services/org.javaee7.RemoteEJBContextProvider b/ejb/remote/vendor/payara-glassfish/src/main/resources/META-INF/services/org.javaee7.RemoteEJBContextProvider
new file mode 100644
index 000000000..29c9e6aed
--- /dev/null
+++ b/ejb/remote/vendor/payara-glassfish/src/main/resources/META-INF/services/org.javaee7.RemoteEJBContextProvider
@@ -0,0 +1 @@
+org.javaee7.PayaraEJBContextProvider
\ No newline at end of file
diff --git a/ejb/remote/vendor/pom.xml b/ejb/remote/vendor/pom.xml
new file mode 100644
index 000000000..7e08be2fc
--- /dev/null
+++ b/ejb/remote/vendor/pom.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+ 4.0.0
+
+
+ org.javaee7
+ ejb-remote
+ 1.0-SNAPSHOT
+
+
+ ejb-remote-vendor
+ pom
+
+ Java EE 7 Sample: ejb - remote - vendor
+
+
+
+ payara-ci-managed
+
+ payara-glassfish
+
+
+
+
+ payara-remote
+
+ payara-glassfish
+
+
+
+
+ glassfish-remote
+
+ payara-glassfish
+
+
+
+
+
diff --git a/ejb/singleton/pom.xml b/ejb/singleton/pom.xml
index 0205fd8f6..d864de0a2 100644
--- a/ejb/singleton/pom.xml
+++ b/ejb/singleton/pom.xml
@@ -1,15 +1,16 @@
-
+
+
4.0.0
+
- org.javaee7.ejb
- ejb-samples
+ org.javaee7
+ ejb
1.0-SNAPSHOT
../pom.xml
-
- org.javaee7.ejb
- singleton
+ org.javaee7
+ ejb-singleton
1.0-SNAPSHOT
war
+ Java EE 7 Sample: ejb - singleton
diff --git a/ejb/singleton/src/main/java/org/javaee7/ejb/stateless/MySingleton.java b/ejb/singleton/src/main/java/org/javaee7/ejb/singleton/MySingleton.java
similarity index 96%
rename from ejb/singleton/src/main/java/org/javaee7/ejb/stateless/MySingleton.java
rename to ejb/singleton/src/main/java/org/javaee7/ejb/singleton/MySingleton.java
index 5f808288b..d3368524d 100644
--- a/ejb/singleton/src/main/java/org/javaee7/ejb/stateless/MySingleton.java
+++ b/ejb/singleton/src/main/java/org/javaee7/ejb/singleton/MySingleton.java
@@ -37,7 +37,7 @@
* only if the new code is made subject to such option by the copyright
* holder.
*/
-package org.javaee7.ejb.stateless;
+package org.javaee7.ejb.singleton;
import java.util.Date;
import javax.annotation.PostConstruct;
@@ -60,10 +60,9 @@ private void postConstruct() {
builder = new StringBuilder();
}
-
@Lock(LockType.READ)
public String readSomething() {
- return "current timestamp: "+ new Date();
+ return "current timestamp: " + new Date();
}
@Lock(LockType.WRITE)
diff --git a/ejb/singleton/src/main/java/org/javaee7/ejb/stateless/MySingletonBeanManagedConcurrency.java b/ejb/singleton/src/main/java/org/javaee7/ejb/singleton/MySingletonBeanManagedConcurrency.java
similarity index 96%
rename from ejb/singleton/src/main/java/org/javaee7/ejb/stateless/MySingletonBeanManagedConcurrency.java
rename to ejb/singleton/src/main/java/org/javaee7/ejb/singleton/MySingletonBeanManagedConcurrency.java
index bbefed45b..7782a2bc3 100644
--- a/ejb/singleton/src/main/java/org/javaee7/ejb/stateless/MySingletonBeanManagedConcurrency.java
+++ b/ejb/singleton/src/main/java/org/javaee7/ejb/singleton/MySingletonBeanManagedConcurrency.java
@@ -37,7 +37,7 @@
* only if the new code is made subject to such option by the copyright
* holder.
*/
-package org.javaee7.ejb.stateless;
+package org.javaee7.ejb.singleton;
import java.util.Date;
import javax.annotation.PostConstruct;
@@ -50,7 +50,7 @@
@Startup
@Singleton
public class MySingletonBeanManagedConcurrency {
-
+
volatile StringBuilder builder;
@PostConstruct
@@ -60,7 +60,7 @@ private void postConstruct() {
}
public String readSomething() {
- return "current timestamp: "+ new Date();
+ return "current timestamp: " + new Date();
}
public String writeSomething(String something) {
diff --git a/ejb/singleton/src/main/java/org/javaee7/ejb/singleton/TestServlet.java b/ejb/singleton/src/main/java/org/javaee7/ejb/singleton/TestServlet.java
new file mode 100644
index 000000000..7cca1c6f7
--- /dev/null
+++ b/ejb/singleton/src/main/java/org/javaee7/ejb/singleton/TestServlet.java
@@ -0,0 +1,132 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can
+ * obtain a copy of the License at
+ * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+package org.javaee7.ejb.singleton;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import javax.inject.Inject;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * @author Arun Gupta
+ */
+@WebServlet(urlPatterns = { "/TestServlet" })
+public class TestServlet extends HttpServlet {
+
+ @Inject
+ MySingleton bean;
+ @Inject
+ MySingletonBeanManagedConcurrency bean2;
+
+ /**
+ * Processes requests for both HTTP GET and POST
+ * methods.
+ *
+ * @param request servlet request
+ * @param response servlet response
+ * @throws ServletException if a servlet-specific error occurs
+ * @throws IOException if an I/O error occurs
+ */
+ protected void processRequest(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ response.setContentType("text/html;charset=UTF-8");
+ try (PrintWriter out = response.getWriter()) {
+ out.println("");
+ out.println("");
+ out.println("");
+ out.println("Singleton Bean ");
+ out.println("");
+ out.println("");
+ out.println("Singleton Bean ");
+ out.println("Container-managed Concurrency ");
+ out.println(bean.readSomething() + " ");
+ out.println(bean.writeSomething("Duke") + " ");
+ out.println("Bean-managed Concurrency ");
+ out.println(bean2.readSomething() + " ");
+ out.println(bean2.writeSomething("Duke"));
+ out.println("");
+ out.println("");
+ }
+ }
+
+ //
+ /**
+ * Handles the HTTP GET method.
+ *
+ * @param request servlet request
+ * @param response servlet response
+ * @throws ServletException if a servlet-specific error occurs
+ * @throws IOException if an I/O error occurs
+ */
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ processRequest(request, response);
+ }
+
+ /**
+ * Handles the HTTP POST method.
+ *
+ * @param request servlet request
+ * @param response servlet response
+ * @throws ServletException if a servlet-specific error occurs
+ * @throws IOException if an I/O error occurs
+ */
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ processRequest(request, response);
+ }
+
+ /**
+ * Returns a short description of the servlet.
+ *
+ * @return a String containing servlet description
+ */
+ @Override
+ public String getServletInfo() {
+ return "Short description";
+ }//
+
+}
diff --git a/ejb/singleton/src/main/java/org/javaee7/ejb/stateless/TestServlet.java b/ejb/singleton/src/main/java/org/javaee7/ejb/stateless/TestServlet.java
deleted file mode 100644
index c63c95312..000000000
--- a/ejb/singleton/src/main/java/org/javaee7/ejb/stateless/TestServlet.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.ejb.stateless;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import javax.inject.Inject;
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * @author Arun Gupta
- */
-@WebServlet(urlPatterns = {"/TestServlet"})
-public class TestServlet extends HttpServlet {
-
- @Inject
- MySingleton bean;
- @Inject
- MySingletonBeanManagedConcurrency bean2;
-
- /**
- * Processes requests for both HTTP GET and POST
- * methods.
- *
- * @param request servlet request
- * @param response servlet response
- * @throws ServletException if a servlet-specific error occurs
- * @throws IOException if an I/O error occurs
- */
- protected void processRequest(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- response.setContentType("text/html;charset=UTF-8");
- try (PrintWriter out = response.getWriter()) {
- out.println("");
- out.println("");
- out.println("");
- out.println("Singleton Bean ");
- out.println("");
- out.println("");
- out.println("Singleton Bean ");
- out.println("Container-managed Concurrency ");
- out.println(bean.readSomething() + " ");
- out.println(bean.writeSomething("Duke") + " ");
- out.println("Bean-managed Concurrency ");
- out.println(bean2.readSomething() + " ");
- out.println(bean2.writeSomething("Duke"));
- out.println("");
- out.println("");
- }
- }
-
- //
- /**
- * Handles the HTTP GET method.
- *
- * @param request servlet request
- * @param response servlet response
- * @throws ServletException if a servlet-specific error occurs
- * @throws IOException if an I/O error occurs
- */
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- processRequest(request, response);
- }
-
- /**
- * Handles the HTTP POST method.
- *
- * @param request servlet request
- * @param response servlet response
- * @throws ServletException if a servlet-specific error occurs
- * @throws IOException if an I/O error occurs
- */
- @Override
- protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- processRequest(request, response);
- }
-
- /**
- * Returns a short description of the servlet.
- *
- * @return a String containing servlet description
- */
- @Override
- public String getServletInfo() {
- return "Short description";
- }//
-
-}
diff --git a/ejb/stateful/pom.xml b/ejb/stateful/pom.xml
index a9ab9be11..e772d02b3 100644
--- a/ejb/stateful/pom.xml
+++ b/ejb/stateful/pom.xml
@@ -1,15 +1,35 @@
-
- 4.0.0
+
+ 4.0.0
+
- org.javaee7.ejb
- ejb-samples
+ org.javaee7
+ ejb
1.0-SNAPSHOT
- ../pom.xml
-
- org.javaee7.ejb
- stateful
+
+ org.javaee7
+ ejb-stateful
1.0-SNAPSHOT
+
war
+ Java EE 7 Sample: ejb - stateful
+
+
+
+ payara-micro-managed
+
+
+
+ maven-surefire-plugin
+
+
+ true
+
+
+
+
+
+
+
+
diff --git a/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/Cart.java b/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/Cart.java
deleted file mode 100644
index d42042e73..000000000
--- a/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/Cart.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.ejb.stateful;
-
-import java.util.ArrayList;
-import java.util.List;
-import javax.ejb.Remove;
-import javax.ejb.Stateful;
-
-/**
- * @author Arun Gupta
- */
-@Stateful
-public class Cart {
-
- List items;
-
- public Cart() {
- items = new ArrayList<>();
- }
-
- public void addItem(String item) {
- items.add(item);
- }
-
- public void removeItem(String item) {
- items.remove(item);
- }
-
- public void purchase() {
- //. . .
- }
-
- public List getItems() {
- return items;
- }
-
- @Remove
- public void remove() {
- items = null;
- }
-}
diff --git a/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/remote/CartBean.java b/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/CartBean.java
similarity index 93%
rename from ejb/stateful/src/main/java/org/javaee7/ejb/stateful/remote/CartBean.java
rename to ejb/stateful/src/main/java/org/javaee7/ejb/stateful/CartBean.java
index c8b738b81..13af263af 100644
--- a/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/remote/CartBean.java
+++ b/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/CartBean.java
@@ -37,7 +37,7 @@
* only if the new code is made subject to such option by the copyright
* holder.
*/
-package org.javaee7.ejb.stateful.remote;
+package org.javaee7.ejb.stateful;
import java.util.ArrayList;
import java.util.List;
@@ -48,7 +48,7 @@
* @author Arun Gupta
*/
@Stateful
-public class CartBean implements Cart {
+public class CartBean {
List items;
@@ -56,22 +56,18 @@ public CartBean() {
items = new ArrayList<>();
}
- @Override
public void addItem(String item) {
items.add(item);
}
- @Override
public void removeItem(String item) {
items.remove(item);
}
- @Override
- public void purchase() {
+ public void purchase() {
//. . .
}
-
- @Override
+
public List getItems() {
return items;
}
diff --git a/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/ReentrantStatefulBean.java b/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/ReentrantStatefulBean.java
new file mode 100644
index 000000000..cc9bbf6e3
--- /dev/null
+++ b/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/ReentrantStatefulBean.java
@@ -0,0 +1,26 @@
+package org.javaee7.ejb.stateful;
+
+import javax.annotation.Resource;
+import javax.ejb.SessionContext;
+import javax.ejb.Stateful;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@Stateful
+public class ReentrantStatefulBean {
+
+ @Resource
+ private SessionContext sessionConext;
+
+ public void initialMethod() {
+ sessionConext.getBusinessObject(ReentrantStatefulBean.class).reentrantMehthod();
+ }
+
+ public void reentrantMehthod() {
+
+ }
+
+}
diff --git a/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/TestServlet.java b/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/TestServlet.java
deleted file mode 100644
index 4fdcaca71..000000000
--- a/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/TestServlet.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.ejb.stateful;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import javax.inject.Inject;
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * @author Arun Gupta
- */
-@WebServlet(urlPatterns = {"/TestServlet"})
-public class TestServlet extends HttpServlet {
- @Inject Cart bean;;
-
- /**
- * Processes requests for both HTTP GET and POST
- * methods.
- *
- * @param request servlet request
- * @param response servlet response
- * @throws ServletException if a servlet-specific error occurs
- * @throws IOException if an I/O error occurs
- */
- protected void processRequest(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- response.setContentType("text/html;charset=UTF-8");
- try (PrintWriter out = response.getWriter()) {
- out.println("");
- out.println("");
- out.println("");
- out.println("Adding/Removing items from Stateful Bean (No Interface) ");
- out.println("");
- out.println("");
- out.println("Adding/Removing items from Stateful Bean (No Interface) ");
- out.println("Adding items ");
- bean.addItem("apple");
- bean.addItem("banana");
- bean.addItem("mango");
- bean.addItem("kiwi");
- bean.addItem("passion fruit");
- out.println("added");
- out.println("Listing items ");
- out.println(bean.getItems());
- out.println("Removing item ");
- bean.removeItem("banana");
- out.println("removed");
- out.println("Listing items ");
- out.println(bean.getItems());
- out.println("");
- out.println("");
- }
- }
-
- //
- /**
- * Handles the HTTP GET method.
- *
- * @param request servlet request
- * @param response servlet response
- * @throws ServletException if a servlet-specific error occurs
- * @throws IOException if an I/O error occurs
- */
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- processRequest(request, response);
- }
-
- /**
- * Handles the HTTP POST method.
- *
- * @param request servlet request
- * @param response servlet response
- * @throws ServletException if a servlet-specific error occurs
- * @throws IOException if an I/O error occurs
- */
- @Override
- protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- processRequest(request, response);
- }
-
- /**
- * Returns a short description of the servlet.
- *
- * @return a String containing servlet description
- */
- @Override
- public String getServletInfo() {
- return "Short description";
- }//
-
-}
diff --git a/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/remote/Cart.java b/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/remote/Cart.java
index 44eb1912c..ebecd12b5 100644
--- a/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/remote/Cart.java
+++ b/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/remote/Cart.java
@@ -40,12 +40,12 @@
package org.javaee7.ejb.stateful.remote;
import java.util.List;
-import javax.ejb.Remote;
+import javax.ejb.Local;
/**
* @author Arun Gupta
*/
-@Remote
+@Local
public interface Cart {
public void addItem(String item);
@@ -53,7 +53,7 @@ public interface Cart {
public void removeItem(String item);
public void purchase();
-
+
public List getItems();
}
diff --git a/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/remote/CartBeanWithInterface.java b/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/remote/CartBeanWithInterface.java
new file mode 100644
index 000000000..a896e4fc4
--- /dev/null
+++ b/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/remote/CartBeanWithInterface.java
@@ -0,0 +1,83 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can
+ * obtain a copy of the License at
+ * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+package org.javaee7.ejb.stateful.remote;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.ejb.Remove;
+import javax.ejb.Stateful;
+
+/**
+ * @author Arun Gupta
+ */
+@Stateful
+public class CartBeanWithInterface implements Cart {
+
+ List items;
+
+ public CartBeanWithInterface() {
+ items = new ArrayList<>();
+ }
+
+ @Override
+ public void addItem(String item) {
+ items.add(item);
+ }
+
+ @Override
+ public void removeItem(String item) {
+ items.remove(item);
+ }
+
+ @Override
+ public void purchase() {
+ //. . .
+ }
+
+ @Override
+ public List getItems() {
+ return items;
+ }
+
+ @Remove
+ public void remove() {
+ items = null;
+ }
+}
diff --git a/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/remote/TestServlet.java b/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/remote/TestServlet.java
index 0b4c310ad..e7c1c3ffb 100644
--- a/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/remote/TestServlet.java
+++ b/ejb/stateful/src/main/java/org/javaee7/ejb/stateful/remote/TestServlet.java
@@ -41,6 +41,7 @@
import java.io.IOException;
import java.io.PrintWriter;
+
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
@@ -51,11 +52,14 @@
/**
* @author Arun Gupta
*/
-@WebServlet(urlPatterns = {"/TestServletWithInterface"})
+@WebServlet(urlPatterns = { "/TestServletWithInterface" })
public class TestServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
// Cannot be injected using @Inject
- @EJB Cart bean;
+ @EJB
+ Cart bean;
/**
* Processes requests for both HTTP GET and POST
@@ -66,14 +70,14 @@ public class TestServlet extends HttpServlet {
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
- protected void processRequest(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
+ protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
+
try (PrintWriter out = response.getWriter()) {
out.println("");
out.println("");
out.println("");
- out.println("Adding/Removing items from Stateful Bean (with Interface) ");
+ out.println("Adding/Removing items from Stateful Bean (with Interface) ");
out.println("");
out.println("");
out.println("Adding/Removing items from Stateful Bean (with Interface) ");
@@ -107,7 +111,7 @@ protected void processRequest(HttpServletRequest request, HttpServletResponse re
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
+ throws ServletException, IOException {
processRequest(request, response);
}
@@ -121,7 +125,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response)
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
+ throws ServletException, IOException {
processRequest(request, response);
}
diff --git a/ejb/stateful/src/main/webapp/index.jsp b/ejb/stateful/src/main/webapp/index.jsp
deleted file mode 100644
index ee2c4087a..000000000
--- a/ejb/stateful/src/main/webapp/index.jsp
+++ /dev/null
@@ -1,57 +0,0 @@
-
-<%@page contentType="text/html" pageEncoding="UTF-8"%>
-
-
-
-
-
- EJB : Stateful
-
-
- EJB : Stateful
-
- Call beans no-interface
- and with-interface.
-
-
diff --git a/ejb/stateful/src/test/java/org/javaee7/ejb/stateful/CartBeanStatefulnessTest.java b/ejb/stateful/src/test/java/org/javaee7/ejb/stateful/CartBeanStatefulnessTest.java
new file mode 100644
index 000000000..3ba77534f
--- /dev/null
+++ b/ejb/stateful/src/test/java/org/javaee7/ejb/stateful/CartBeanStatefulnessTest.java
@@ -0,0 +1,70 @@
+package org.javaee7.ejb.stateful;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.junit.InSequence;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.ejb.EJB;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.hamcrest.MatcherAssert.*;
+
+/**
+ * @author Jakub Marchwicki
+ */
+@RunWith(Arquillian.class)
+public class CartBeanStatefulnessTest {
+
+ final private String item_to_add = "apple";
+
+ @EJB
+ private CartBean bean1;
+
+ @EJB
+ private CartBean bean2;
+
+ @Deployment
+ public static Archive> deployment() {
+ return ShrinkWrap.create(JavaArchive.class, "test.jar")
+ .addClass(CartBean.class)
+ .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
+ }
+
+ /**
+ * JSR 318: Enterprise JavaBeans, Version 3.1
+ * 3.4.7.1 Session Object Identity / Stateful Session Beans
+ *
+ * A stateful session object has a unique identity that is assigned by
+ * the container at the time the object is created. A client of the stateful
+ * session bean business interface can determine if two business interface
+ * or no-interface view references refer to the same session object
+ * by use of the equals method
+ */
+ @Test
+ @InSequence(1)
+ public void should_not_be_identical_beans() {
+ assertThat("Expect different instances", bean1, is(not(bean2)));
+ }
+
+ @Test
+ @InSequence(2)
+ public void should_add_items_to_first_cart() {
+ // when
+ bean1.addItem(item_to_add);
+
+ // then
+ assertThat(bean1.getItems(), hasItem(item_to_add));
+ }
+
+ @Test
+ @InSequence(3)
+ public void should_not_contain_any_items_in_second_cart() {
+ assertThat(bean2.getItems().isEmpty(), is(true));
+ }
+}
\ No newline at end of file
diff --git a/ejb/stateful/src/test/java/org/javaee7/ejb/stateful/CartBeanTest.java b/ejb/stateful/src/test/java/org/javaee7/ejb/stateful/CartBeanTest.java
new file mode 100644
index 000000000..3bce4b240
--- /dev/null
+++ b/ejb/stateful/src/test/java/org/javaee7/ejb/stateful/CartBeanTest.java
@@ -0,0 +1,108 @@
+package org.javaee7.ejb.stateful;
+
+import static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.jboss.shrinkwrap.api.asset.EmptyAsset.INSTANCE;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * @author Rafał Roppel
+ */
+@RunWith(Arquillian.class)
+public class CartBeanTest {
+
+ @Inject
+ private CartBean sut;
+
+ @Deployment
+ public static Archive> deployment() {
+ return ShrinkWrap.create(JavaArchive.class)
+ .addClass(CartBean.class)
+ .addAsManifestResource(INSTANCE, "beans.xml");
+ }
+
+ /**
+ * Test of addItem method, of class CartBean
+ *
+ * @throws Exception
+ */
+ @Test
+ public void shouldAddOneItem() throws Exception {
+ // given
+
+ // when
+ sut.addItem("apple");
+
+ // then
+ assertThat(sut.getItems(), hasItem("apple"));
+ }
+
+ /**
+ * Test of addItem method, of class CartBean
+ *
+ * @throws Exception
+ */
+ @Test
+ public void shouldAddManyItems() throws Exception {
+ // given
+ final List items = Arrays.asList("apple", "banana", "mango", "kiwi", "passion fruit");
+
+ // when
+ for (final String item : items) {
+ sut.addItem(item);
+ }
+
+ // then
+ assertThat(sut.getItems(), is(items));
+ }
+
+ /**
+ * Test of removeItem method, of class CartBean
+ *
+ * @throws Exception
+ */
+ @Test
+ public void shouldRemoveOneItem() throws Exception {
+ // given
+ final List items = Arrays.asList("apple", "banana", "mango", "kiwi", "passion fruit");
+ for (final String item : items) {
+ sut.addItem(item);
+ }
+
+ // when
+ sut.removeItem("banana");
+
+ // then
+ assertThat(sut.getItems(), not(hasItem("banana")));
+ }
+
+ /**
+ * Test of getItems method, of class CartBean
+ *
+ * @throws Exception
+ */
+ @Test
+ public void shouldBeEmpty() throws Exception {
+ // given
+
+ // when
+ final List actual = sut.getItems();
+
+ // then
+ assertThat(actual.isEmpty(), is(true));
+ }
+}
\ No newline at end of file
diff --git a/ejb/stateful/src/test/java/org/javaee7/ejb/stateful/CartBeanWithInterfaceTest.java b/ejb/stateful/src/test/java/org/javaee7/ejb/stateful/CartBeanWithInterfaceTest.java
new file mode 100644
index 000000000..d699db4d4
--- /dev/null
+++ b/ejb/stateful/src/test/java/org/javaee7/ejb/stateful/CartBeanWithInterfaceTest.java
@@ -0,0 +1,111 @@
+package org.javaee7.ejb.stateful;
+
+import static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.jboss.shrinkwrap.api.asset.EmptyAsset.INSTANCE;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.ejb.EJB;
+
+import org.javaee7.ejb.stateful.remote.Cart;
+import org.javaee7.ejb.stateful.remote.CartBeanWithInterface;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * @author rafos
+ */
+@RunWith(Arquillian.class)
+public class CartBeanWithInterfaceTest {
+
+ @EJB
+ private Cart sut;
+
+ @Deployment
+ public static Archive> deployment() {
+ return ShrinkWrap.create(JavaArchive.class)
+ .addClass(Cart.class)
+ .addClass(CartBeanWithInterface.class)
+ .addAsManifestResource(INSTANCE, "beans.xml");
+ }
+
+ /**
+ * Test of addItem method, of class CartBean
+ *
+ * @throws Exception
+ */
+ @Test
+ public void shouldAddOneItem() throws Exception {
+ // given
+
+ // when
+ sut.addItem("apple");
+
+ // then
+ assertThat(sut.getItems(), hasItem("apple"));
+ }
+
+ /**
+ * Test of addItem method, of class CartBean
+ *
+ * @throws Exception
+ */
+ @Test
+ public void shouldAddManyItems() throws Exception {
+ // given
+ final List items = Arrays.asList("apple", "banana", "mango", "kiwi", "passion fruit");
+
+ // when
+ for (final String item : items) {
+ sut.addItem(item);
+ }
+
+ // then
+ assertThat(sut.getItems(), is(items));
+ }
+
+ /**
+ * Test of removeItem method, of class CartBean
+ *
+ * @throws Exception
+ */
+ @Test
+ public void shouldRemoveOneItem() throws Exception {
+ // given
+ final List items = Arrays.asList("apple", "banana", "mango", "kiwi", "passion fruit");
+ for (final String item : items) {
+ sut.addItem(item);
+ }
+
+ // when
+ sut.removeItem("banana");
+
+ // then
+ assertThat(sut.getItems(), not(hasItem("banana")));
+ }
+
+ /**
+ * Test of getItems method, of class CartBean
+ *
+ * @throws Exception
+ */
+ @Test
+ public void shouldBeEmpty() throws Exception {
+ // given
+
+ // when
+ final List actual = sut.getItems();
+
+ // then
+ assertThat(actual.isEmpty(), is(true));
+ }
+}
\ No newline at end of file
diff --git a/ejb/stateful/src/test/java/org/javaee7/ejb/stateful/ReentrantCallTest.java b/ejb/stateful/src/test/java/org/javaee7/ejb/stateful/ReentrantCallTest.java
new file mode 100644
index 000000000..8145d98b4
--- /dev/null
+++ b/ejb/stateful/src/test/java/org/javaee7/ejb/stateful/ReentrantCallTest.java
@@ -0,0 +1,39 @@
+package org.javaee7.ejb.stateful;
+
+import javax.inject.Inject;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * This tests that a stateful bean is capable of calling a method via
+ * a business proxy on itself.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class ReentrantCallTest {
+
+ @Inject
+ private ReentrantStatefulBean reentrantStatefulBean;
+
+ @Deployment
+ public static Archive> deployment() {
+ return ShrinkWrap.create(WebArchive.class)
+ .addClass(ReentrantStatefulBean.class);
+ }
+
+ @Test
+ public void doReentrantCall() {
+ // initialMethod() will internally call another method on itself.
+ // This should not throw an exception. See e.g. https://issues.apache.org/jira/browse/OPENEJB-1099
+ reentrantStatefulBean.initialMethod();
+ }
+
+}
\ No newline at end of file
diff --git a/ejb/stateless/pom.xml b/ejb/stateless/pom.xml
index bacd9f650..4ba53a455 100644
--- a/ejb/stateless/pom.xml
+++ b/ejb/stateless/pom.xml
@@ -1,15 +1,16 @@
-
+
+
4.0.0
+
- org.javaee7.ejb
- ejb-samples
+ org.javaee7
+ ejb
1.0-SNAPSHOT
../pom.xml
-
- org.javaee7.ejb
- stateless
+ org.javaee7
+ ejb-stateless
1.0-SNAPSHOT
war
+ Java EE 7 Sample: ejb - stateless
diff --git a/ejb/stateless/src/main/java/org/javaee7/ejb/stateless/AccountSessionBean.java b/ejb/stateless/src/main/java/org/javaee7/ejb/stateless/AccountSessionBean.java
index fe5c05b0b..49c344ec0 100644
--- a/ejb/stateless/src/main/java/org/javaee7/ejb/stateless/AccountSessionBean.java
+++ b/ejb/stateless/src/main/java/org/javaee7/ejb/stateless/AccountSessionBean.java
@@ -47,11 +47,19 @@
@Stateless
public class AccountSessionBean {
+ private float amount = 0;
+
public String withdraw(float amount) {
+ this.amount -= amount;
return "Withdrawn: " + amount;
}
- public String deposit(float amount) {
+ public String deposit(float amount) {
+ this.amount += amount;
return "Deposited: " + amount;
}
+
+ public float getAmount() {
+ return this.amount;
+ }
}
diff --git a/ejb/stateless/src/main/java/org/javaee7/ejb/stateless/TestServlet.java b/ejb/stateless/src/main/java/org/javaee7/ejb/stateless/TestServlet.java
deleted file mode 100644
index 5c834f9f7..000000000
--- a/ejb/stateless/src/main/java/org/javaee7/ejb/stateless/TestServlet.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.ejb.stateless;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import javax.inject.Inject;
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * @author Arun Gupta
- */
-@WebServlet(urlPatterns = {"/TestServlet"})
-public class TestServlet extends HttpServlet {
- @Inject AccountSessionBean bean;;
-
- /**
- * Processes requests for both HTTP GET and POST
- * methods.
- *
- * @param request servlet request
- * @param response servlet response
- * @throws ServletException if a servlet-specific error occurs
- * @throws IOException if an I/O error occurs
- */
- protected void processRequest(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- response.setContentType("text/html;charset=UTF-8");
- try (PrintWriter out = response.getWriter()) {
- out.println("");
- out.println("");
- out.println("");
- out.println("Stateless Bean (No Interface) ");
- out.println("");
- out.println("");
- out.println("Stateless Bean (No Interface) ");
- out.println("Withdraw and Deposit ");
- out.println(bean.deposit((float)5.0));
- out.println(bean.withdraw((float)5.0));
- out.println("");
- out.println("");
- }
- }
-
- //
- /**
- * Handles the HTTP GET method.
- *
- * @param request servlet request
- * @param response servlet response
- * @throws ServletException if a servlet-specific error occurs
- * @throws IOException if an I/O error occurs
- */
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- processRequest(request, response);
- }
-
- /**
- * Handles the HTTP POST method.
- *
- * @param request servlet request
- * @param response servlet response
- * @throws ServletException if a servlet-specific error occurs
- * @throws IOException if an I/O error occurs
- */
- @Override
- protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- processRequest(request, response);
- }
-
- /**
- * Returns a short description of the servlet.
- *
- * @return a String containing servlet description
- */
- @Override
- public String getServletInfo() {
- return "Short description";
- }//
-
-}
diff --git a/ejb/stateless/src/main/java/org/javaee7/ejb/stateless/remote/Account.java b/ejb/stateless/src/main/java/org/javaee7/ejb/stateless/remote/Account.java
index bcb236e2f..969daff56 100644
--- a/ejb/stateless/src/main/java/org/javaee7/ejb/stateless/remote/Account.java
+++ b/ejb/stateless/src/main/java/org/javaee7/ejb/stateless/remote/Account.java
@@ -39,12 +39,12 @@
*/
package org.javaee7.ejb.stateless.remote;
-import javax.ejb.Remote;
+import javax.ejb.Local;
/**
* @author Arun Gupta
*/
-@Remote
+@Local
public interface Account {
public String withdraw(float amount);
diff --git a/ejb/stateless/src/main/java/org/javaee7/ejb/stateless/remote/AccountSessionBeanWithInterface.java b/ejb/stateless/src/main/java/org/javaee7/ejb/stateless/remote/AccountSessionBeanWithInterface.java
index 5d40bd854..01c0628a5 100644
--- a/ejb/stateless/src/main/java/org/javaee7/ejb/stateless/remote/AccountSessionBeanWithInterface.java
+++ b/ejb/stateless/src/main/java/org/javaee7/ejb/stateless/remote/AccountSessionBeanWithInterface.java
@@ -53,7 +53,7 @@ public String withdraw(float amount) {
}
@Override
- public String deposit(float amount) {
+ public String deposit(float amount) {
return "Deposited: " + amount;
}
}
diff --git a/ejb/stateless/src/main/java/org/javaee7/ejb/stateless/remote/TestServlet.java b/ejb/stateless/src/main/java/org/javaee7/ejb/stateless/remote/TestServlet.java
index 00f6efea9..e02988a5a 100644
--- a/ejb/stateless/src/main/java/org/javaee7/ejb/stateless/remote/TestServlet.java
+++ b/ejb/stateless/src/main/java/org/javaee7/ejb/stateless/remote/TestServlet.java
@@ -51,7 +51,7 @@
/**
* @author Arun Gupta
*/
-@WebServlet(urlPatterns = {"/TestServletWithInterface"})
+@WebServlet(urlPatterns = { "/TestServletWithInterface" })
public class TestServlet extends HttpServlet {
// Cannot be injected using @Inject
@@ -68,7 +68,7 @@ public class TestServlet extends HttpServlet {
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
+ throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("");
@@ -96,7 +96,7 @@ protected void processRequest(HttpServletRequest request, HttpServletResponse re
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
+ throws ServletException, IOException {
processRequest(request, response);
}
@@ -110,7 +110,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response)
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
+ throws ServletException, IOException {
processRequest(request, response);
}
diff --git a/ejb/stateless/src/main/webapp/index.jsp b/ejb/stateless/src/main/webapp/index.jsp
deleted file mode 100644
index ee2c4087a..000000000
--- a/ejb/stateless/src/main/webapp/index.jsp
+++ /dev/null
@@ -1,57 +0,0 @@
-
-<%@page contentType="text/html" pageEncoding="UTF-8"%>
-
-
-
-
-
- EJB : Stateful
-
-
- EJB : Stateful
-
- Call beans no-interface
- and with-interface.
-
-
diff --git a/ejb/stateless/src/test/java/org/javaee7/ejb/stateless/AccountSessionBeanTest.java b/ejb/stateless/src/test/java/org/javaee7/ejb/stateless/AccountSessionBeanTest.java
index 44dd68560..c9327444d 100644
--- a/ejb/stateless/src/test/java/org/javaee7/ejb/stateless/AccountSessionBeanTest.java
+++ b/ejb/stateless/src/test/java/org/javaee7/ejb/stateless/AccountSessionBeanTest.java
@@ -1,52 +1,70 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-
package org.javaee7.ejb.stateless;
-import javax.ejb.EJB;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ShrinkWrap;
-import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.Test;
-import static org.junit.Assert.*;
+import org.junit.runner.RunWith;
+
+import javax.inject.Inject;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
/**
* @author Arun Gupta
+ * @author Rafał Roppel
*/
+@RunWith(Arquillian.class)
public class AccountSessionBeanTest {
- @EJB AccountSessionBean bean;
-
+
+ @Inject
+ private AccountSessionBean sut;
+
/**
* Arquillian specific method for creating a file which can be deployed
* while executing the test.
*
* @return a war file
*/
- public static WebArchive createDeployment() {
- WebArchive war = ShrinkWrap.create(WebArchive.class).
- addClass(AccountSessionBean.class);
- System.out.println(war.toString(true));
- return war;
+ @Deployment
+ public static Archive> deployment() {
+ return ShrinkWrap.create(JavaArchive.class)
+ .addClass(AccountSessionBean.class)
+ .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}
-
+
/**
* Test of withdraw method, of class AccountSessionBean.
*/
-// @Test
- public void testWithdraw() {
- String result = bean.withdraw((float)5.0);
- assertEquals("Withdrawn: 5.0", result);
+ @Test
+ public void shouldWithdrawGivenAmount() {
+ // given
+ final float amount = 5.0F;
+
+ // when
+ final String actual = sut.withdraw(amount);
+
+ // then
+ assertThat(actual, is(equalTo("Withdrawn: " + amount)));
}
/**
* Test of deposit method, of class AccountSessionBean.
*/
-// @Test
- public void testDeposit() {
- String result = bean.withdraw((float)10.0);
- assertEquals("Deposited: 10.0", result);
+ @Test
+ public void shouldDepositGivenAmount() {
+ // given
+ final float amount = 10.0F;
+
+ // when
+ final String actual = sut.deposit(amount);
+
+ // then
+ assertThat(actual, is(equalTo("Deposited: " + amount)));
}
-
-}
+}
\ No newline at end of file
diff --git a/ejb/stateless/src/test/java/org/javaee7/ejb/stateless/AccountSessionBeanWithInterfaceTest.java b/ejb/stateless/src/test/java/org/javaee7/ejb/stateless/AccountSessionBeanWithInterfaceTest.java
index 4c925ebcd..ea0012fa2 100644
--- a/ejb/stateless/src/test/java/org/javaee7/ejb/stateless/AccountSessionBeanWithInterfaceTest.java
+++ b/ejb/stateless/src/test/java/org/javaee7/ejb/stateless/AccountSessionBeanWithInterfaceTest.java
@@ -1,25 +1,31 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
package org.javaee7.ejb.stateless;
-import javax.ejb.EJB;
import org.javaee7.ejb.stateless.remote.Account;
+import org.javaee7.ejb.stateless.remote.AccountSessionBeanWithInterface;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ShrinkWrap;
-import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.Test;
-import static org.junit.Assert.*;
+import org.junit.runner.RunWith;
+
+import javax.ejb.EJB;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
/**
* @author Arun Gupta
+ * @author Rafał Roppel
*/
-//@RunWith(Arquillian.class)
+@RunWith(Arquillian.class)
public class AccountSessionBeanWithInterfaceTest {
@EJB
- Account bean;
+ private Account sut;
/**
* Arquillian specific method for creating a file which can be deployed
@@ -27,31 +33,41 @@ public class AccountSessionBeanWithInterfaceTest {
*
* @return a war file
*/
-// @Deployment
-// @TargetsContainer("wildfly-arquillian")
- public static WebArchive createDeployment() {
- WebArchive war = ShrinkWrap.create(WebArchive.class).
- addClass(AccountSessionBean.class);
- System.out.println(war.toString(true));
- return war;
+ @Deployment
+ public static Archive> deployment() {
+ return ShrinkWrap.create(JavaArchive.class)
+ .addClass(AccountSessionBeanWithInterface.class)
+ .addClass(Account.class)
+ .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}
/**
* Test of withdraw method, of class AccountSessionBean.
*/
-// @Test
- public void testWithdraw() {
- String result = bean.withdraw((float) 5.0);
- assertEquals("Withdrawn: 5.0", result);
+ @Test
+ public void shouldWithdrawGivenAmount() {
+ // given
+ final float amount = 5.0F;
+
+ // when
+ final String actual = sut.withdraw(amount);
+
+ // then
+ assertThat(actual, is(equalTo("Withdrawn: " + amount)));
}
/**
* Test of deposit method, of class AccountSessionBean.
*/
-// @Test
- public void testDeposit() {
- String result = bean.withdraw((float) 10.0);
- assertEquals("Deposited: 10.0", result);
- }
+ @Test
+ public void shouldDepositGivenAmount() {
+ // given
+ final float amount = 10.0F;
-}
+ // when
+ final String actual = sut.deposit(amount);
+
+ // then
+ assertThat(actual, is(equalTo("Deposited: " + amount)));
+ }
+}
\ No newline at end of file
diff --git a/ejb/stateless/src/test/java/org/javaee7/ejb/stateless/AccountSessionStatelessnessTest.java b/ejb/stateless/src/test/java/org/javaee7/ejb/stateless/AccountSessionStatelessnessTest.java
new file mode 100644
index 000000000..416b70ca4
--- /dev/null
+++ b/ejb/stateless/src/test/java/org/javaee7/ejb/stateless/AccountSessionStatelessnessTest.java
@@ -0,0 +1,49 @@
+package org.javaee7.ejb.stateless;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.ejb.EJB;
+
+import static org.hamcrest.MatcherAssert.*;
+import static org.hamcrest.Matchers.*;
+
+/**
+ * @author Jakub Marchwicki
+ */
+@RunWith(Arquillian.class)
+public class AccountSessionStatelessnessTest {
+
+ @EJB
+ AccountSessionBean account1;
+
+ @EJB
+ AccountSessionBean account2;
+
+ @Deployment
+ public static Archive> deployment() {
+ return ShrinkWrap.create(JavaArchive.class, "test.jar")
+ .addClass(AccountSessionBean.class)
+ .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
+ }
+
+ /**
+ * JSR 318: Enterprise JavaBeans, Version 3.1
+ * 3.4.7.2 Session Object Identity / Stateless Session Beans
+ *
+ * All business object references of the same interface type for the same
+ * stateless session bean have the same object identity, which is assigned
+ * by the container. All references to the no-interface view of the same
+ * stateless session bean have the same object identity.
+ */
+ @Test
+ public void should_be_identical_beans() {
+ assertThat("Expect same instances", account1, is(account2));
+ }
+}
diff --git a/ejb/timer/pom.xml b/ejb/timer/pom.xml
index f9f34fe63..c98aaefb2 100644
--- a/ejb/timer/pom.xml
+++ b/ejb/timer/pom.xml
@@ -1,15 +1,33 @@
-
+
+
4.0.0
+
- org.javaee7.ejb
- ejb-samples
+ org.javaee7
+ ejb
1.0-SNAPSHOT
- ../pom.xml
-
- org.javaee7.ejb
- timer
- 1.0-SNAPSHOT
+
+ ejb-timer
war
+ Java EE 7 Sample: ejb - timer
+
+
+
+ payara-micro-managed
+
+
+
+ maven-surefire-plugin
+
+
+ true
+
+
+
+
+
+
+
+
diff --git a/ejb/timer/src/main/java/org/javaee7/ejb/timer/AutomaticTimerBean.java b/ejb/timer/src/main/java/org/javaee7/ejb/timer/AutomaticTimerBean.java
new file mode 100644
index 000000000..88a9da361
--- /dev/null
+++ b/ejb/timer/src/main/java/org/javaee7/ejb/timer/AutomaticTimerBean.java
@@ -0,0 +1,34 @@
+package org.javaee7.ejb.timer;
+
+import javax.annotation.Resource;
+import javax.ejb.Schedule;
+import javax.ejb.SessionContext;
+import javax.ejb.Singleton;
+import javax.ejb.Startup;
+import javax.ejb.Timer;
+import javax.enterprise.event.Event;
+import javax.inject.Inject;
+import java.util.Collection;
+
+/**
+ * @author Arun Gupta
+ */
+@Startup
+@Singleton
+public class AutomaticTimerBean {
+
+ @Resource
+ SessionContext ctx;
+
+ @Inject
+ Event pingEvent;
+
+ @Schedule(hour = "*", minute = "*", second = "*/5", info = "Every 5 second timer")
+ public void printDate() {
+ Collection timers = ctx.getTimerService().getAllTimers();
+ for (Timer t : timers) {
+ pingEvent.fire(new Ping(t.getInfo().toString()));
+ }
+ }
+
+}
diff --git a/ejb/timer/src/main/java/org/javaee7/ejb/timer/MultipleScheduleTimerBean.java b/ejb/timer/src/main/java/org/javaee7/ejb/timer/MultipleScheduleTimerBean.java
new file mode 100644
index 000000000..a109c2466
--- /dev/null
+++ b/ejb/timer/src/main/java/org/javaee7/ejb/timer/MultipleScheduleTimerBean.java
@@ -0,0 +1,33 @@
+package org.javaee7.ejb.timer;
+
+import javax.ejb.Schedule;
+import javax.ejb.Singleton;
+import javax.ejb.Startup;
+import javax.ejb.Timer;
+import javax.enterprise.event.Event;
+import javax.inject.Inject;
+
+/**
+ * @author Jacek Jackowiak
+ */
+@Startup
+@Singleton
+public class MultipleScheduleTimerBean {
+
+ @Inject
+ Event pingEvent;
+
+ @Schedule(hour = "*", minute = "*", second = "*/5", info = "Every 5 second timer")
+ public void fastAutomaticallyScheduled(Timer timer) {
+ fireEvent(timer);
+ }
+
+ @Schedule(hour = "*", minute = "*", second = "*/10", info = "Every 10 second timer")
+ public void slowlyAutomaticallyScheduled(Timer timer) {
+ fireEvent(timer);
+ }
+
+ private void fireEvent(Timer timer) {
+ pingEvent.fire(new Ping(timer.getInfo().toString()));
+ }
+}
diff --git a/ejb/timer/src/main/java/org/javaee7/ejb/timer/Ping.java b/ejb/timer/src/main/java/org/javaee7/ejb/timer/Ping.java
new file mode 100644
index 000000000..1fa8003a6
--- /dev/null
+++ b/ejb/timer/src/main/java/org/javaee7/ejb/timer/Ping.java
@@ -0,0 +1,27 @@
+package org.javaee7.ejb.timer;
+
+public class Ping {
+
+ private String timeInfo;
+ private long time = System.currentTimeMillis();
+
+ public Ping(String s) {
+ this.timeInfo = s;
+ }
+
+ public long getTime() {
+ return time;
+ }
+
+ public String getTimeInfo() {
+ return timeInfo;
+ }
+
+ @Override
+ public String toString() {
+ return "Ping {" +
+ "timeInfo='" + timeInfo + '\'' +
+ ", time=" + time +
+ '}';
+ }
+}
diff --git a/ejb/timer/src/main/java/org/javaee7/ejb/timer/PingsListener.java b/ejb/timer/src/main/java/org/javaee7/ejb/timer/PingsListener.java
new file mode 100644
index 000000000..efbe19365
--- /dev/null
+++ b/ejb/timer/src/main/java/org/javaee7/ejb/timer/PingsListener.java
@@ -0,0 +1,23 @@
+package org.javaee7.ejb.timer;
+
+import javax.ejb.Singleton;
+import javax.ejb.Startup;
+import javax.enterprise.event.Observes;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+@Startup
+@Singleton
+public class PingsListener {
+
+ final List pings = new CopyOnWriteArrayList<>();
+
+ public void listen(@Observes Ping ping) {
+ System.out.println("ping = " + ping);
+ pings.add(ping);
+ }
+
+ public List getPings() {
+ return pings;
+ }
+}
diff --git a/ejb/timer/src/main/java/org/javaee7/ejb/timer/ProgrammaticTimerBean.java b/ejb/timer/src/main/java/org/javaee7/ejb/timer/ProgrammaticTimerBean.java
new file mode 100644
index 000000000..0eb5e57ef
--- /dev/null
+++ b/ejb/timer/src/main/java/org/javaee7/ejb/timer/ProgrammaticTimerBean.java
@@ -0,0 +1,39 @@
+package org.javaee7.ejb.timer;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import javax.ejb.*;
+import javax.enterprise.event.Event;
+import javax.inject.Inject;
+
+/**
+ * author: Jacek Jackowiak
+ */
+@Startup
+@Singleton
+public class ProgrammaticTimerBean {
+
+ @Inject
+ Event pingEvent;
+
+ @Resource
+ TimerService timerService;
+
+ @PostConstruct
+ public void initialize() {
+ ScheduleExpression scheduleExpression = new ScheduleExpression()
+ .hour("*")
+ .minute("*")
+ .second("*/5");
+
+ TimerConfig timerConfig = new TimerConfig();
+ timerConfig.setInfo("Every 5 second timer");
+
+ timerService.createCalendarTimer(scheduleExpression, timerConfig);
+ }
+
+ @Timeout
+ public void programmaticTimout(Timer timer) {
+ pingEvent.fire(new Ping(timer.getInfo().toString()));
+ }
+}
diff --git a/ejb/timer/src/main/java/org/javaee7/ejb/timer/SchedulesTimerBean.java b/ejb/timer/src/main/java/org/javaee7/ejb/timer/SchedulesTimerBean.java
new file mode 100644
index 000000000..826fc626b
--- /dev/null
+++ b/ejb/timer/src/main/java/org/javaee7/ejb/timer/SchedulesTimerBean.java
@@ -0,0 +1,25 @@
+package org.javaee7.ejb.timer;
+
+import javax.ejb.*;
+import javax.enterprise.event.Event;
+import javax.inject.Inject;
+
+/**
+ * @author Jacek Jackowiak
+ */
+@Startup
+@Singleton
+public class SchedulesTimerBean {
+
+ @Inject
+ Event pingEvent;
+
+ @Schedules({
+ @Schedule(hour = "*", minute = "*", second = "*/5", info = "Every 5 second timer"),
+ @Schedule(hour = "*", minute = "*", second = "*/10", info = "Every 10 second timer")
+ })
+ public void automaticallyScheduled(Timer timer) {
+ pingEvent.fire(new Ping(timer.getInfo().toString()));
+ }
+
+}
diff --git a/ejb/timer/src/main/java/org/javaee7/ejb/timer/TimerSessionBean.java b/ejb/timer/src/main/java/org/javaee7/ejb/timer/TimerSessionBean.java
deleted file mode 100644
index 9d49cd66c..000000000
--- a/ejb/timer/src/main/java/org/javaee7/ejb/timer/TimerSessionBean.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.ejb.timer;
-
-import java.util.Collection;
-import java.util.Date;
-import javax.annotation.Resource;
-import javax.ejb.Schedule;
-import javax.ejb.SessionContext;
-import javax.ejb.Singleton;
-import javax.ejb.Startup;
-import javax.ejb.Timer;
-
-/**
- * @author Arun Gupta
- */
-@Startup
-@Singleton
-public class TimerSessionBean {
-
- @Resource SessionContext ctx;
-
- @Schedule(hour="*", minute="*", second="*/5", info = "Every 5 second timer")
- public void printDate() {
- System.out.println(new Date());
- Collection timers = ctx.getTimerService().getAllTimers();
- for (Timer t : timers) {
- System.out.println("Timer info: " + t.getInfo());
- }
- }
-
-}
diff --git a/ejb/timer/src/main/webapp/WEB-INF/jboss-deployment-structure.xml b/ejb/timer/src/main/webapp/WEB-INF/jboss-deployment-structure.xml
new file mode 100644
index 000000000..6d8132afe
--- /dev/null
+++ b/ejb/timer/src/main/webapp/WEB-INF/jboss-deployment-structure.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/ejb/timer/src/main/webapp/index.jsp b/ejb/timer/src/main/webapp/index.jsp
deleted file mode 100644
index aabe08c32..000000000
--- a/ejb/timer/src/main/webapp/index.jsp
+++ /dev/null
@@ -1,56 +0,0 @@
-
-<%@page contentType="text/html" pageEncoding="UTF-8"%>
-
-
-
-
-
- EJB Timers
-
-
- EJB Timers
-
- Timer activated, printing every 5 seconds, check server.log.
-
-
diff --git a/ejb/timer/src/test/java/org/javaee7/ejb/timer/AutomaticTimerBeanTest.java b/ejb/timer/src/test/java/org/javaee7/ejb/timer/AutomaticTimerBeanTest.java
new file mode 100644
index 000000000..5d89a49e4
--- /dev/null
+++ b/ejb/timer/src/test/java/org/javaee7/ejb/timer/AutomaticTimerBeanTest.java
@@ -0,0 +1,56 @@
+package org.javaee7.ejb.timer;
+
+import static com.jayway.awaitility.Awaitility.await;
+import static com.jayway.awaitility.Awaitility.to;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.hamcrest.Matchers.is;
+import static org.javaee7.ejb.timer.WithinWindowMatcher.withinWindow;
+
+import java.io.File;
+
+import javax.inject.Inject;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.resolver.api.maven.Maven;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * author: Jakub Marchwicki
+ */
+@RunWith(Arquillian.class)
+public class AutomaticTimerBeanTest {
+
+ private static final long TIMEOUT = 5000l;
+ private static final long TOLERANCE = 1000l;
+
+ @Inject
+ private PingsListener pings;
+
+ @Deployment
+ public static WebArchive deploy() {
+ return ShrinkWrap.create(WebArchive.class)
+ .addAsLibraries(Maven.resolver().loadPomFromFile("pom.xml")
+ .resolve("com.jayway.awaitility:awaitility")
+ .withTransitivity().asFile())
+ .addClasses(WithinWindowMatcher.class, Ping.class, PingsListener.class, AutomaticTimerBean.class)
+ .addAsWebInfResource(new File("src/main/webapp/WEB-INF/jboss-deployment-structure.xml"));
+ }
+
+ @Test
+ public void should_receive_two_pings() {
+ await().untilCall(to(pings.getPings()).size(), greaterThanOrEqualTo(2));
+
+ Ping firstPing = pings.getPings().get(0);
+ Ping secondPing = pings.getPings().get(1);
+
+ long delay = secondPing.getTime() - firstPing.getTime();
+ System.out.println("Actual timeout = " + delay);
+
+ assertThat(delay, is(withinWindow(TIMEOUT, TOLERANCE)));
+ }
+}
diff --git a/ejb/timer/src/test/java/org/javaee7/ejb/timer/MultipleScheduleTimerBeanTest.java b/ejb/timer/src/test/java/org/javaee7/ejb/timer/MultipleScheduleTimerBeanTest.java
new file mode 100644
index 000000000..2adbff5af
--- /dev/null
+++ b/ejb/timer/src/test/java/org/javaee7/ejb/timer/MultipleScheduleTimerBeanTest.java
@@ -0,0 +1,64 @@
+package org.javaee7.ejb.timer;
+
+import static com.jayway.awaitility.Awaitility.await;
+import static com.jayway.awaitility.Awaitility.to;
+import static java.lang.Math.min;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.hamcrest.Matchers.is;
+import static org.javaee7.ejb.timer.WithinWindowMatcher.withinWindow;
+import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
+
+import java.io.File;
+
+import javax.inject.Inject;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.resolver.api.maven.Maven;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * author: Jacek Jackowiak
+ */
+@RunWith(Arquillian.class)
+public class MultipleScheduleTimerBeanTest {
+
+ private static final long TIMEOUT = 0l;
+ private static final long TOLERANCE = 4000l;
+
+ @Inject
+ private PingsListener pings;
+
+ @Deployment
+ public static WebArchive deploy() {
+ return create(WebArchive.class)
+ .addAsLibraries(Maven.resolver().loadPomFromFile("pom.xml")
+ .resolve("com.jayway.awaitility:awaitility")
+ .withTransitivity().asFile())
+ .addClasses(WithinWindowMatcher.class, Ping.class, PingsListener.class, MultipleScheduleTimerBean.class)
+ .addAsWebInfResource(new File("src/main/webapp/WEB-INF/jboss-deployment-structure.xml"));
+ }
+
+ @Test
+ public void should_receive_three_pings() {
+ await().untilCall(to(pings.getPings()).size(), greaterThanOrEqualTo(3));
+
+ Ping firstPing = pings.getPings().get(0);
+ Ping secondPing = pings.getPings().get(1);
+ Ping thirdPing = pings.getPings().get(2);
+
+ long timeBetweenFirstAndSecondPing = secondPing.getTime() - firstPing.getTime();
+ System.out.println("Actual timeout = " + timeBetweenFirstAndSecondPing);
+
+ long timeBetweenSecondAndThirdPing = thirdPing.getTime() - secondPing.getTime();
+ System.out.println("Actual timeout = " + timeBetweenSecondAndThirdPing);
+
+ long smallerDelay = min(timeBetweenFirstAndSecondPing, timeBetweenSecondAndThirdPing);
+
+ // Note; this is quite sensitive to slow CI systems.
+ assertThat(smallerDelay, is(withinWindow(TIMEOUT, TOLERANCE)));
+ }
+}
diff --git a/ejb/timer/src/test/java/org/javaee7/ejb/timer/ProgrammaticTimerBeanTest.java b/ejb/timer/src/test/java/org/javaee7/ejb/timer/ProgrammaticTimerBeanTest.java
new file mode 100644
index 000000000..d039f6bf1
--- /dev/null
+++ b/ejb/timer/src/test/java/org/javaee7/ejb/timer/ProgrammaticTimerBeanTest.java
@@ -0,0 +1,64 @@
+package org.javaee7.ejb.timer;
+
+import static com.jayway.awaitility.Awaitility.await;
+import static com.jayway.awaitility.Awaitility.to;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.hamcrest.Matchers.is;
+import static org.javaee7.ejb.timer.WithinWindowMatcher.withinWindow;
+import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
+
+import java.io.File;
+
+import javax.inject.Inject;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.resolver.api.maven.Maven;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * author: Jacek Jackowiak
+ */
+@RunWith(Arquillian.class)
+public class ProgrammaticTimerBeanTest {
+
+ private static final long TIMEOUT = 5000l;
+ private static final long TOLERANCE = 1000l;
+
+ @Inject
+ private PingsListener pings;
+
+ @Deployment
+ public static WebArchive deploy() {
+ return create(WebArchive.class)
+ .addAsLibraries(
+ Maven.resolver().loadPomFromFile("pom.xml")
+ .resolve("com.jayway.awaitility:awaitility")
+ .withTransitivity().asFile())
+ .addClasses(
+ WithinWindowMatcher.class,
+ Ping.class,
+ PingsListener.class,
+ ProgrammaticTimerBean.class)
+ .addAsWebInfResource(new File("src/main/webapp/WEB-INF/jboss-deployment-structure.xml"));
+
+ }
+
+ @Test
+ public void should_receive_two_pings() {
+ await()
+ .untilCall(
+ to(pings.getPings()).size(), greaterThanOrEqualTo(2));
+
+ Ping firstPing = pings.getPings().get(0);
+ Ping secondPing = pings.getPings().get(1);
+
+ long delay = secondPing.getTime() - firstPing.getTime();
+ System.out.println("Actual timeout = " + delay);
+
+ assertThat(delay, is(withinWindow(TIMEOUT, TOLERANCE)));
+ }
+}
\ No newline at end of file
diff --git a/ejb/timer/src/test/java/org/javaee7/ejb/timer/SchedulesTimerBeanTest.java b/ejb/timer/src/test/java/org/javaee7/ejb/timer/SchedulesTimerBeanTest.java
new file mode 100644
index 000000000..125515db4
--- /dev/null
+++ b/ejb/timer/src/test/java/org/javaee7/ejb/timer/SchedulesTimerBeanTest.java
@@ -0,0 +1,63 @@
+package org.javaee7.ejb.timer;
+
+import static com.jayway.awaitility.Awaitility.await;
+import static com.jayway.awaitility.Awaitility.to;
+import static java.lang.Math.min;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.hamcrest.Matchers.is;
+import static org.javaee7.ejb.timer.WithinWindowMatcher.withinWindow;
+import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
+
+import java.io.File;
+
+import javax.inject.Inject;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.resolver.api.maven.Maven;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * author: Jacek Jackowiak
+ */
+@RunWith(Arquillian.class)
+public class SchedulesTimerBeanTest {
+
+ private static final long TIMEOUT = 0l;
+ private static final long TOLERANCE = 1000l;
+
+ @Inject
+ private PingsListener pings;
+
+ @Deployment
+ public static WebArchive deploy() {
+ return create(WebArchive.class)
+ .addAsLibraries(Maven.resolver().loadPomFromFile("pom.xml")
+ .resolve("com.jayway.awaitility:awaitility")
+ .withTransitivity().asFile())
+ .addClasses(WithinWindowMatcher.class, Ping.class, PingsListener.class, SchedulesTimerBean.class)
+ .addAsWebInfResource(new File("src/main/webapp/WEB-INF/jboss-deployment-structure.xml"));
+ }
+
+ @Test
+ public void should_receive_three_pings() {
+ await().untilCall(to(pings.getPings()).size(), greaterThanOrEqualTo(3));
+
+ Ping firstPing = pings.getPings().get(0);
+ Ping secondPing = pings.getPings().get(1);
+ Ping thirdPing = pings.getPings().get(2);
+
+ long delay = secondPing.getTime() - firstPing.getTime();
+ System.out.println("Actual timeout = " + delay);
+
+ long delay2 = thirdPing.getTime() - secondPing.getTime();
+ System.out.println("Actual timeout = " + delay2);
+
+ long smallerDelay = min(delay, delay2);
+
+ assertThat(smallerDelay, is(withinWindow(TIMEOUT, TOLERANCE)));
+ }
+}
diff --git a/ejb/timer/src/test/java/org/javaee7/ejb/timer/WithinWindowMatcher.java b/ejb/timer/src/test/java/org/javaee7/ejb/timer/WithinWindowMatcher.java
new file mode 100644
index 000000000..c20105e9e
--- /dev/null
+++ b/ejb/timer/src/test/java/org/javaee7/ejb/timer/WithinWindowMatcher.java
@@ -0,0 +1,30 @@
+package org.javaee7.ejb.timer;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+
+class WithinWindowMatcher extends BaseMatcher {
+
+ private final long timeout;
+ private final long tolerance;
+
+ public WithinWindowMatcher(long timeout, long tolerance) {
+ this.timeout = timeout;
+ this.tolerance = tolerance;
+ }
+
+ @Override
+ public boolean matches(Object item) {
+ final Long actual = (Long) item;
+ return Math.abs(actual - timeout) < tolerance;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ }
+
+ public static Matcher withinWindow(long timeout, long tolerance) {
+ return new WithinWindowMatcher(timeout, tolerance);
+ }
+}
diff --git a/el/README.md b/el/README.md
new file mode 100644
index 000000000..6972a6f2d
--- /dev/null
+++ b/el/README.md
@@ -0,0 +1,13 @@
+# Java EE 7 Samples: EL 3.0 #
+
+The [JSR 341](https://jcp.org/en/jsr/detail?id=341) is an update to Expression Language 2.2, currently part of JSR 245, JavaServer Page (JSP) 2.2.
+
+## Samples ##
+
+ - standalone
+
+## How to run
+
+More information on how to run can be found at:
+
+
diff --git a/el/pom.xml b/el/pom.xml
index 8ec44494e..2cd702e23 100644
--- a/el/pom.xml
+++ b/el/pom.xml
@@ -1,20 +1,27 @@
-
- 4.0.0
+
+ 4.0.0
+
org.javaee7
- javaee7-samples
+ samples-parent
1.0-SNAPSHOT
- ../pom.xml
-
- org.javaee7.el
- el-samples
- 1.0-SNAPSHOT
+
+ el
pom
- Java EE 7 Expression Language Samples
+
+ Java EE 7 Sample: el
standalone
+
+
+
+ org.javaee7
+ test-utils
+ ${project.version}
+ test
+
+
diff --git a/el/standalone/pom.xml b/el/standalone/pom.xml
index 574d40fb8..e2911c32f 100644
--- a/el/standalone/pom.xml
+++ b/el/standalone/pom.xml
@@ -1,15 +1,16 @@
-
+
+
4.0.0
+
- org.javaee7.el
- el-samples
+ org.javaee7
+ el
1.0-SNAPSHOT
../pom.xml
-
- org.javaee7.el
- standalone
+ org.javaee7
+ el-standalone
1.0-SNAPSHOT
war
+ Java EE 7 Sample: el - standalone
diff --git a/el/standalone/src/test/java/org/javaee7/el/standalone/ELResolverTest.java b/el/standalone/src/test/java/org/javaee7/el/standalone/ELResolverTest.java
index f36e524f7..35c005587 100644
--- a/el/standalone/src/test/java/org/javaee7/el/standalone/ELResolverTest.java
+++ b/el/standalone/src/test/java/org/javaee7/el/standalone/ELResolverTest.java
@@ -13,7 +13,6 @@
import static org.junit.Assert.assertEquals;
-
/**
* @author Alexis Hassler
*/
@@ -24,6 +23,7 @@ public class ELResolverTest {
public static Archive> deploy() {
return ShrinkWrap.create(JavaArchive.class);
}
+
private ELProcessor elProcessor;
@Before
diff --git a/el/standalone/src/test/resources/arquillian.xml b/el/standalone/src/test/resources/arquillian.xml
deleted file mode 100644
index 04fcc49bc..000000000
--- a/el/standalone/src/test/resources/arquillian.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
- ${serverRoot:target/wildfly-8.0.0.Beta1}
- ${serverProfile:standalone-full.xml}
-
-
-
-
diff --git a/extra/nosql/cassandra/pom.xml b/extra/nosql/cassandra/pom.xml
deleted file mode 100644
index cf5864490..000000000
--- a/extra/nosql/cassandra/pom.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
- 4.0.0
-
- org.javaee7.extra.nosql
- extra-nosql-samples
- 1.0-SNAPSHOT
- ../pom.xml
-
-
- org.javaee7.extra.nosql
- cassandra
- 1.0-SNAPSHOT
- war
-
-
-
- com.datastax.cassandra
- cassandra-driver-core
- 2.0.0-beta2
-
-
-
diff --git a/extra/nosql/cassandra/src/main/java/org/javaee7/extra/nosql/cassandra/Person.java b/extra/nosql/cassandra/src/main/java/org/javaee7/extra/nosql/cassandra/Person.java
deleted file mode 100644
index eb527a41e..000000000
--- a/extra/nosql/cassandra/src/main/java/org/javaee7/extra/nosql/cassandra/Person.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.nosql.cassandra;
-
-import java.util.StringTokenizer;
-import javax.enterprise.context.ApplicationScoped;
-import javax.inject.Named;
-import javax.validation.constraints.Size;
-
-/**
- * @author Arun Gupta
- */
-@Named
-@ApplicationScoped
-public class Person {
-
- @Size(min = 1, max = 20)
- private String name;
-
- private int age;
-
- public Person() {
- }
-
- public Person(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
-
- @Override
- public String toString() {
- return name + ", " + age;
- }
-
- public static Person fromString(String string) {
- StringTokenizer tokens = new StringTokenizer(string, ",");
- return new Person(tokens.nextToken(), Integer.parseInt(tokens.nextToken().trim()));
- }
-}
diff --git a/extra/nosql/cassandra/src/main/java/org/javaee7/extra/nosql/cassandra/PersonSessionBean.java b/extra/nosql/cassandra/src/main/java/org/javaee7/extra/nosql/cassandra/PersonSessionBean.java
deleted file mode 100644
index 5cf4c67d2..000000000
--- a/extra/nosql/cassandra/src/main/java/org/javaee7/extra/nosql/cassandra/PersonSessionBean.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.nosql.cassandra;
-
-import com.datastax.driver.core.Cluster;
-import com.datastax.driver.core.Host;
-import com.datastax.driver.core.Metadata;
-import com.datastax.driver.core.PreparedStatement;
-import com.datastax.driver.core.ResultSet;
-import com.datastax.driver.core.Row;
-import com.datastax.driver.core.Session;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import javax.ejb.Singleton;
-import javax.inject.Inject;
-import javax.inject.Named;
-
-/**
- * @author Arun Gupta
- */
-@Named
-@Singleton
-public class PersonSessionBean {
-
- @Inject
- Person person;
-
- private Cluster cluster;
- private Session session;
-
- private PreparedStatement selectAllPersons;
- private PreparedStatement insertPerson;
-
- @PostConstruct
- private void initDB() {
- cluster = Cluster.builder()
- .addContactPoint("localhost")
- // .withSSL() // Uncomment if using client to node encryption
- .build();
- Metadata metadata = cluster.getMetadata();
- System.out.printf("Connected to cluster: %s\n", metadata.getClusterName());
- for (Host host : metadata.getAllHosts()) {
- System.out.printf("Datacenter: %s; Host: %s; Rack: %s\n",
- host.getDatacenter(), host.getAddress(), host.getRack());
- }
- session = cluster.connect();
- session.execute("CREATE KEYSPACE IF NOT EXISTS test WITH replication "
- + "= {'class':'SimpleStrategy', 'replication_factor':1};");
-
- session.execute(
- "CREATE TABLE IF NOT EXISTS test.person ("
- + "name text PRIMARY KEY,"
- + "age int"
- + ");");
-
- selectAllPersons = session.prepare("SELECT * FROM test.person");
- insertPerson = session.prepare(
- "INSERT INTO test.person (name, age) VALUES (?, ?);"
- );
- }
-
- @PreDestroy
- private void stopDB() {
- cluster.shutdown();
- }
-
- public void createPerson() {
- session.execute(insertPerson.bind(person.getName(), person.getAge()));
- }
-
- public List getPersons() {
- List persons = new ArrayList<>();
- ResultSet results = session.execute(selectAllPersons.bind());
- for (Row row : results) {
- persons.add(new Person(row.getString("name"), row.getInt("age")));
- }
- return persons;
- }
-}
diff --git a/extra/nosql/cassandra/src/main/webapp/WEB-INF/beans.xml b/extra/nosql/cassandra/src/main/webapp/WEB-INF/beans.xml
deleted file mode 100644
index aa81c7c3c..000000000
--- a/extra/nosql/cassandra/src/main/webapp/WEB-INF/beans.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/extra/nosql/cassandra/src/main/webapp/WEB-INF/template.xhtml b/extra/nosql/cassandra/src/main/webapp/WEB-INF/template.xhtml
deleted file mode 100644
index 82f183175..000000000
--- a/extra/nosql/cassandra/src/main/webapp/WEB-INF/template.xhtml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
- Cassandra using Java EE 7
-
-
-
-
-
- Cassandra using Java EE 7
-
-
-
- Content
-
-
-
-
-
diff --git a/extra/nosql/cassandra/src/main/webapp/index.xhtml b/extra/nosql/cassandra/src/main/webapp/index.xhtml
deleted file mode 100644
index f9d6dd768..000000000
--- a/extra/nosql/cassandra/src/main/webapp/index.xhtml
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Name:
- Age:
-
-
-
-
- Make sure to download latest Cassandra server and untar.
- Follow the instructions in the bundled README.txt to start the server:
-
- sudo mkdir -p /var/log/cassandra
- sudo chown -R `whoami` /var/log/cassandra
- sudo mkdir -p /var/lib/cassandra
- sudo chown -R `whoami` /var/lib/cassandra
- bin/cassandra -f
-
- Look for message as:
-
-INFO 16:39:08,258 Binding thrift service to localhost/127.0.0.1:9160
-INFO 16:39:08,266 Using synchronous/threadpool thrift server on localhost : 9160
-INFO 16:39:08,293 Listening for thrift clients...
-
-
-
-
-
-
-
-
-
diff --git a/extra/nosql/cassandra/src/main/webapp/resources/css/cssLayout.css b/extra/nosql/cassandra/src/main/webapp/resources/css/cssLayout.css
deleted file mode 100644
index 8ee7cebe3..000000000
--- a/extra/nosql/cassandra/src/main/webapp/resources/css/cssLayout.css
+++ /dev/null
@@ -1,61 +0,0 @@
-
-#top {
- position: relative;
- background-color: #036fab;
- color: white;
- padding: 5px;
- margin: 0px 0px 10px 0px;
-}
-
-#bottom {
- position: relative;
- background-color: #c2dfef;
- padding: 5px;
- margin: 10px 0px 0px 0px;
-}
-
-#left {
- float: left;
- background-color: #ece3a5;
- padding: 5px;
- width: 150px;
-}
-
-#right {
- float: right;
- background-color: #ece3a5;
- padding: 5px;
- width: 150px;
-}
-
-.center_content {
- position: relative;
- background-color: #dddddd;
- padding: 5px;
-}
-
-.left_content {
- background-color: #dddddd;
- padding: 5px;
- margin-left: 170px;
-}
-
-.right_content {
- background-color: #dddddd;
- padding: 5px;
- margin: 0px 170px 0px 170px;
-}
-
-#top a:link, #top a:visited {
- color: white;
- font-weight : bold;
- text-decoration: none;
-}
-
-#top a:link:hover, #top a:visited:hover {
- color: black;
- font-weight : bold;
- text-decoration : underline;
-}
-
-
diff --git a/extra/nosql/cassandra/src/main/webapp/resources/css/default.css b/extra/nosql/cassandra/src/main/webapp/resources/css/default.css
deleted file mode 100644
index 6cbc3d18e..000000000
--- a/extra/nosql/cassandra/src/main/webapp/resources/css/default.css
+++ /dev/null
@@ -1,29 +0,0 @@
-body {
- background-color: #ffffff;
- font-size: 12px;
- font-family: Verdana, "Verdana CE", Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif;
- color: #000000;
- margin: 10px;
-}
-
-h1 {
- font-family: Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif;
- border-bottom: 1px solid #AFAFAF;
- font-size: 16px;
- font-weight: bold;
- margin: 0px;
- padding: 0px;
- color: #D20005;
-}
-
-a:link, a:visited {
- color: #045491;
- font-weight : bold;
- text-decoration: none;
-}
-
-a:link:hover, a:visited:hover {
- color: #045491;
- font-weight : bold;
- text-decoration : underline;
-}
diff --git a/extra/nosql/cassandra/src/main/webapp/show.xhtml b/extra/nosql/cassandra/src/main/webapp/show.xhtml
deleted file mode 100644
index 8f1d60f31..000000000
--- a/extra/nosql/cassandra/src/main/webapp/show.xhtml
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Name #{p.name}
- Age #{p.age}
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/extra/nosql/couchbase/pom.xml b/extra/nosql/couchbase/pom.xml
deleted file mode 100644
index 3e19cae10..000000000
--- a/extra/nosql/couchbase/pom.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
- 4.0.0
-
- org.javaee7.extra.nosql
- extra-nosql-samples
- 1.0-SNAPSHOT
- ../pom.xml
-
-
- org.javaee7.extra.nosql
- couchbase
- 1.0-SNAPSHOT
- war
-
-
-
- com.couchbase.client
- couchbase-client
- 1.2.0
-
-
-
diff --git a/extra/nosql/couchbase/src/main/java/org/javaee7/extra/nosql/couchbase/Person.java b/extra/nosql/couchbase/src/main/java/org/javaee7/extra/nosql/couchbase/Person.java
deleted file mode 100644
index fa3c3e477..000000000
--- a/extra/nosql/couchbase/src/main/java/org/javaee7/extra/nosql/couchbase/Person.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.nosql.couchbase;
-
-import java.io.Serializable;
-import javax.enterprise.context.ApplicationScoped;
-import javax.inject.Named;
-import javax.validation.constraints.Size;
-
-/**
- * @author Arun Gupta
- */
-@Named
-@ApplicationScoped
-public class Person implements Serializable {
-
- @Size(min = 1, max = 20)
- private String name;
-
- private int age;
-
- public Person() {
- }
-
- public Person(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
-
- @Override
- public String toString() {
- return name + ", " + age;
- }
-}
diff --git a/extra/nosql/couchbase/src/main/java/org/javaee7/extra/nosql/couchbase/PersonSessionBean.java b/extra/nosql/couchbase/src/main/java/org/javaee7/extra/nosql/couchbase/PersonSessionBean.java
deleted file mode 100644
index 1c591a168..000000000
--- a/extra/nosql/couchbase/src/main/java/org/javaee7/extra/nosql/couchbase/PersonSessionBean.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.nosql.couchbase;
-
-import com.couchbase.client.CouchbaseClient;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Singleton;
-
-/**
- * @author Arun Gupta
- */
-@Named
-@Singleton
-public class PersonSessionBean {
-
- @Inject
- Person person;
-
- CouchbaseClient client;
-
- Set set = new HashSet<>();
-
- @PostConstruct
- private void initDB() {
- try {
- // Get an instance of Couchbase
- List hosts = Arrays.asList(
- new URI("http://localhost:8091/pools")
- );
-
- // Get an instance of Couchbase
- // Name of the Bucket to connect to
- String bucket = "default";
-
- // Password of the bucket (empty) string if none
- String password = "";
-
- // Connect to the Cluster
- client = new CouchbaseClient(hosts, bucket, password);
- } catch (URISyntaxException | IOException ex) {
- Logger.getLogger(PersonSessionBean.class.getName()).log(Level.SEVERE, null, ex);
- }
- }
-
- @PreDestroy
- private void stopDB() {
- client.shutdown();
- }
-
- public void createPerson() {
- client.set(person.getName(), new Person(person.getName(), person.getAge()));
- set.add(person.getName());
- }
-
- public List getPersons() {
- List persons = new ArrayList();
- Map map = client.getBulk(set.iterator());
- for (String key : map.keySet()) {
- persons.add((Person)map.get(key));
- }
- return persons;
- }
-}
diff --git a/extra/nosql/couchbase/src/main/webapp/WEB-INF/beans.xml b/extra/nosql/couchbase/src/main/webapp/WEB-INF/beans.xml
deleted file mode 100644
index aa81c7c3c..000000000
--- a/extra/nosql/couchbase/src/main/webapp/WEB-INF/beans.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/extra/nosql/couchbase/src/main/webapp/WEB-INF/template.xhtml b/extra/nosql/couchbase/src/main/webapp/WEB-INF/template.xhtml
deleted file mode 100644
index 9eb7c0652..000000000
--- a/extra/nosql/couchbase/src/main/webapp/WEB-INF/template.xhtml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
- Couchbase using Java EE 7
-
-
-
-
-
- Couchbase using Java EE 7
-
-
-
- Content
-
-
-
-
-
diff --git a/extra/nosql/couchbase/src/main/webapp/index.xhtml b/extra/nosql/couchbase/src/main/webapp/index.xhtml
deleted file mode 100644
index daf471c32..000000000
--- a/extra/nosql/couchbase/src/main/webapp/index.xhtml
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Name:
- Age:
-
-
-
- Make sure to start Couchbase server . Confirm by visiting pools and look for output as:
-
-
-"pools": [
- {
- "name": "default",
- "uri": "/pools/default?uuid=21041e11772b15d7c64f3451e1293215",
- "streamingUri": "/poolsStreaming/default?uuid=21041e11772b15d7c64f3451e1293215"
- }
-],
-
-
-
-
-
-
-
diff --git a/extra/nosql/couchbase/src/main/webapp/resources/css/cssLayout.css b/extra/nosql/couchbase/src/main/webapp/resources/css/cssLayout.css
deleted file mode 100644
index 8ee7cebe3..000000000
--- a/extra/nosql/couchbase/src/main/webapp/resources/css/cssLayout.css
+++ /dev/null
@@ -1,61 +0,0 @@
-
-#top {
- position: relative;
- background-color: #036fab;
- color: white;
- padding: 5px;
- margin: 0px 0px 10px 0px;
-}
-
-#bottom {
- position: relative;
- background-color: #c2dfef;
- padding: 5px;
- margin: 10px 0px 0px 0px;
-}
-
-#left {
- float: left;
- background-color: #ece3a5;
- padding: 5px;
- width: 150px;
-}
-
-#right {
- float: right;
- background-color: #ece3a5;
- padding: 5px;
- width: 150px;
-}
-
-.center_content {
- position: relative;
- background-color: #dddddd;
- padding: 5px;
-}
-
-.left_content {
- background-color: #dddddd;
- padding: 5px;
- margin-left: 170px;
-}
-
-.right_content {
- background-color: #dddddd;
- padding: 5px;
- margin: 0px 170px 0px 170px;
-}
-
-#top a:link, #top a:visited {
- color: white;
- font-weight : bold;
- text-decoration: none;
-}
-
-#top a:link:hover, #top a:visited:hover {
- color: black;
- font-weight : bold;
- text-decoration : underline;
-}
-
-
diff --git a/extra/nosql/couchbase/src/main/webapp/resources/css/default.css b/extra/nosql/couchbase/src/main/webapp/resources/css/default.css
deleted file mode 100644
index 6cbc3d18e..000000000
--- a/extra/nosql/couchbase/src/main/webapp/resources/css/default.css
+++ /dev/null
@@ -1,29 +0,0 @@
-body {
- background-color: #ffffff;
- font-size: 12px;
- font-family: Verdana, "Verdana CE", Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif;
- color: #000000;
- margin: 10px;
-}
-
-h1 {
- font-family: Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif;
- border-bottom: 1px solid #AFAFAF;
- font-size: 16px;
- font-weight: bold;
- margin: 0px;
- padding: 0px;
- color: #D20005;
-}
-
-a:link, a:visited {
- color: #045491;
- font-weight : bold;
- text-decoration: none;
-}
-
-a:link:hover, a:visited:hover {
- color: #045491;
- font-weight : bold;
- text-decoration : underline;
-}
diff --git a/extra/nosql/couchbase/src/main/webapp/show.xhtml b/extra/nosql/couchbase/src/main/webapp/show.xhtml
deleted file mode 100644
index 8f1d60f31..000000000
--- a/extra/nosql/couchbase/src/main/webapp/show.xhtml
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Name #{p.name}
- Age #{p.age}
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/extra/nosql/hbase/pom.xml b/extra/nosql/hbase/pom.xml
deleted file mode 100644
index b9f745728..000000000
--- a/extra/nosql/hbase/pom.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
- 4.0.0
-
- org.javaee7.extra.nosql
- extra-nosql-samples
- 1.0-SNAPSHOT
- ../pom.xml
-
-
- org.javaee7.extra.nosql
- hbase
- 1.0-SNAPSHOT
- war
-
-
-
- org.apache.hadoop
- hadoop-core
- 0.20.2
-
-
- org.apache.hbase
- hbase
- 0.94.2
-
-
-
diff --git a/extra/nosql/hbase/src/main/java/org/javaee7/extra/nosql/hbase/Person.java b/extra/nosql/hbase/src/main/java/org/javaee7/extra/nosql/hbase/Person.java
deleted file mode 100644
index 0842f0198..000000000
--- a/extra/nosql/hbase/src/main/java/org/javaee7/extra/nosql/hbase/Person.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.nosql.hbase;
-
-import java.util.StringTokenizer;
-import javax.enterprise.context.ApplicationScoped;
-import javax.inject.Named;
-import javax.validation.constraints.Size;
-
-/**
- * @author Arun Gupta
- */
-@Named
-@ApplicationScoped
-public class Person {
-
- @Size(min = 1, max = 20)
- private String name;
-
- private int age;
-
- public Person() {
- }
-
- public Person(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
-
- @Override
- public String toString() {
- return name + ", " + age;
- }
-
- public static Person fromString(String string) {
- StringTokenizer tokens = new StringTokenizer(string, ",");
- return new Person(tokens.nextToken(), Integer.parseInt(tokens.nextToken().trim()));
- }
-}
diff --git a/extra/nosql/hbase/src/main/java/org/javaee7/extra/nosql/hbase/PersonSessionBean.java b/extra/nosql/hbase/src/main/java/org/javaee7/extra/nosql/hbase/PersonSessionBean.java
deleted file mode 100644
index 9c635d075..000000000
--- a/extra/nosql/hbase/src/main/java/org/javaee7/extra/nosql/hbase/PersonSessionBean.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.nosql.hbase;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import javax.ejb.Stateless;
-import javax.inject.Inject;
-import javax.inject.Named;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.hbase.HBaseConfiguration;
-import org.apache.hadoop.hbase.HTableDescriptor;
-import org.apache.hadoop.hbase.KeyValue;
-import org.apache.hadoop.hbase.client.HBaseAdmin;
-import org.apache.hadoop.hbase.client.HTable;
-import org.apache.hadoop.hbase.client.HTableInterface;
-import org.apache.hadoop.hbase.client.HTablePool;
-import org.apache.hadoop.hbase.client.Put;
-import org.apache.hadoop.hbase.client.Result;
-import org.apache.hadoop.hbase.client.ResultScanner;
-import org.apache.hadoop.hbase.client.Scan;
-import org.apache.hadoop.hbase.util.Bytes;
-
-/**
- * @author Arun Gupta
- */
-@Named
-@Stateless
-public class PersonSessionBean {
-
- @Inject
- Person person;
-
- Set set = new HashSet<>();
-
- private static final String personsColumnFamily = "person";
- private static final String personsTable = "persons";
- HTablePool pool;
-
- @PostConstruct
- private void initDB() {
- try {
- // By default, it's localhost, don't worry.
- Configuration config = HBaseConfiguration.create();
-
-// HTable table = new HTable(config, personsTable);
-
- HBaseAdmin admin = new HBaseAdmin(config);
- HTableDescriptor blogstable = new HTableDescriptor(personsTable);
- admin.createTable(blogstable);
-//
-// // Cannot edit a stucture on an active table.
-// admin.disableTable(personsTable);
-//
-// HColumnDescriptor userCol = new HColumnDescriptor("name");
-// admin.addColumn(personsTable, userCol);
-//
-// HColumnDescriptor ageCol = new HColumnDescriptor("age");
-// admin.addColumn(personsTable, ageCol);
-//
-// // For readin, it needs to be re-enabled.
-// admin.enableTable(personsTable);
- } catch (IOException ex) {
- Logger.getLogger(PersonSessionBean.class.getName()).log(Level.SEVERE, null, ex);
- }
- }
-
- @PreDestroy
- private void stopDB() {
- }
-
- public void createPerson() throws IOException {
- try (HTableInterface table = pool.getTable(personsTable)) {
-
- Put put = new Put(Bytes.toBytes(person.getName()), Calendar.getInstance().getTime().getTime());
- put.add(Bytes.toBytes(personsColumnFamily),
- Bytes.toBytes("name"),
- Calendar.getInstance().getTime().getTime(),
- Bytes.toBytes(person.getName()));
- put.add(Bytes.toBytes(personsColumnFamily),
- Bytes.toBytes("age"),
- Calendar.getInstance().getTime().getTime(),
- Bytes.toBytes(person.getAge()));
- table.put(put);
- }
- }
-
- public List getPersons() throws IOException {
- List persons = new ArrayList<>();
-
- try (HTableInterface table = pool.getTable(personsTable)) {
- Scan scan = new Scan();
- scan.addFamily(Bytes.toBytes(personsColumnFamily));
- try (ResultScanner resultScanner = table.getScanner(scan)) {
- for (Result result : resultScanner) {
- for (KeyValue kv : result.raw()) {
- Person p = new Person();
-// p.setTitle(Bytes.toString(kv.getQualifier()));
-// p.setBody(Bytes.toString(kv.getValue()));
-// p.setId(Bytes.toString(result.getRow()));
- persons.add(person);
- }
- }
- }
- }
-
- return persons;
- }
-}
diff --git a/extra/nosql/hbase/src/main/webapp/WEB-INF/beans.xml b/extra/nosql/hbase/src/main/webapp/WEB-INF/beans.xml
deleted file mode 100644
index aa81c7c3c..000000000
--- a/extra/nosql/hbase/src/main/webapp/WEB-INF/beans.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/extra/nosql/hbase/src/main/webapp/WEB-INF/template.xhtml b/extra/nosql/hbase/src/main/webapp/WEB-INF/template.xhtml
deleted file mode 100644
index 4afb9cea1..000000000
--- a/extra/nosql/hbase/src/main/webapp/WEB-INF/template.xhtml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
- HBase using Java EE 7
-
-
-
-
-
- HBase using Java EE 7
-
-
-
- Content
-
-
-
-
-
diff --git a/extra/nosql/hbase/src/main/webapp/WEB-INF/web.xml b/extra/nosql/hbase/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index c5e7c7381..000000000
--- a/extra/nosql/hbase/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
- javax.faces.PROJECT_STAGE
- Development
-
-
- Faces Servlet
- javax.faces.webapp.FacesServlet
- 1
-
-
- Faces Servlet
- /faces/*
-
-
-
- 30
-
-
-
- faces/index.xhtml
-
-
diff --git a/extra/nosql/hbase/src/main/webapp/index.xhtml b/extra/nosql/hbase/src/main/webapp/index.xhtml
deleted file mode 100644
index 1a192f7f7..000000000
--- a/extra/nosql/hbase/src/main/webapp/index.xhtml
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Name:
- Age:
-
-
-
-
-
- Download HBase stable and tar xzvf. Make sure the server version and the client API version in "pom.xml" (0.94.2) are alike.
- Start HBase: ./bin/start-hbase.sh
- Look for messages like:
- starting master, logging to /Users/arungup/tools/hbase/hbase-0.94.12/bin/../logs/hbase-arungup-master-arungup-mac.local.out
-
-
-
-
-
-
-
-
diff --git a/extra/nosql/hbase/src/main/webapp/resources/css/cssLayout.css b/extra/nosql/hbase/src/main/webapp/resources/css/cssLayout.css
deleted file mode 100644
index 8ee7cebe3..000000000
--- a/extra/nosql/hbase/src/main/webapp/resources/css/cssLayout.css
+++ /dev/null
@@ -1,61 +0,0 @@
-
-#top {
- position: relative;
- background-color: #036fab;
- color: white;
- padding: 5px;
- margin: 0px 0px 10px 0px;
-}
-
-#bottom {
- position: relative;
- background-color: #c2dfef;
- padding: 5px;
- margin: 10px 0px 0px 0px;
-}
-
-#left {
- float: left;
- background-color: #ece3a5;
- padding: 5px;
- width: 150px;
-}
-
-#right {
- float: right;
- background-color: #ece3a5;
- padding: 5px;
- width: 150px;
-}
-
-.center_content {
- position: relative;
- background-color: #dddddd;
- padding: 5px;
-}
-
-.left_content {
- background-color: #dddddd;
- padding: 5px;
- margin-left: 170px;
-}
-
-.right_content {
- background-color: #dddddd;
- padding: 5px;
- margin: 0px 170px 0px 170px;
-}
-
-#top a:link, #top a:visited {
- color: white;
- font-weight : bold;
- text-decoration: none;
-}
-
-#top a:link:hover, #top a:visited:hover {
- color: black;
- font-weight : bold;
- text-decoration : underline;
-}
-
-
diff --git a/extra/nosql/hbase/src/main/webapp/resources/css/default.css b/extra/nosql/hbase/src/main/webapp/resources/css/default.css
deleted file mode 100644
index 6cbc3d18e..000000000
--- a/extra/nosql/hbase/src/main/webapp/resources/css/default.css
+++ /dev/null
@@ -1,29 +0,0 @@
-body {
- background-color: #ffffff;
- font-size: 12px;
- font-family: Verdana, "Verdana CE", Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif;
- color: #000000;
- margin: 10px;
-}
-
-h1 {
- font-family: Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif;
- border-bottom: 1px solid #AFAFAF;
- font-size: 16px;
- font-weight: bold;
- margin: 0px;
- padding: 0px;
- color: #D20005;
-}
-
-a:link, a:visited {
- color: #045491;
- font-weight : bold;
- text-decoration: none;
-}
-
-a:link:hover, a:visited:hover {
- color: #045491;
- font-weight : bold;
- text-decoration : underline;
-}
diff --git a/extra/nosql/hbase/src/main/webapp/show.xhtml b/extra/nosql/hbase/src/main/webapp/show.xhtml
deleted file mode 100644
index 342b4446b..000000000
--- a/extra/nosql/hbase/src/main/webapp/show.xhtml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Name #{p.name}
- Age #{p.age}
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/extra/nosql/hibernate-ogm/pom.xml b/extra/nosql/hibernate-ogm/pom.xml
deleted file mode 100644
index 1b7613090..000000000
--- a/extra/nosql/hibernate-ogm/pom.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
- extra-nosql-samples
- org.javaee7.extra.nosql
- 1.0-SNAPSHOT
-
- 4.0.0
-
- hibernate-ogm
-
-
\ No newline at end of file
diff --git a/extra/nosql/hibernate-ogm/src/test/java/org/javaee7/extra/nosql/hibernateogm/EhcacheTest.java b/extra/nosql/hibernate-ogm/src/test/java/org/javaee7/extra/nosql/hibernateogm/EhcacheTest.java
deleted file mode 100644
index 638ec2e21..000000000
--- a/extra/nosql/hibernate-ogm/src/test/java/org/javaee7/extra/nosql/hibernateogm/EhcacheTest.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.javaee7.extra.nosql.hibernateogm;
-
-import org.javaee7.extra.nosql.hibernateogm.commons.AbstractOgmTest;
-import org.jboss.arquillian.container.test.api.Deployment;
-import org.jboss.arquillian.junit.Arquillian;
-import org.jboss.shrinkwrap.api.spec.WebArchive;
-import org.junit.runner.RunWith;
-
-/**
- * @author Guillaume Scheibel
- */
-@RunWith(Arquillian.class)
-public class EhcacheTest extends AbstractOgmTest {
-
- @Deployment
- public static WebArchive createDeployment() {
- return AbstractOgmTest.createDeployment( "ehcache" );
- }
-}
diff --git a/extra/nosql/hibernate-ogm/src/test/java/org/javaee7/extra/nosql/hibernateogm/commons/AbstractOgmTest.java b/extra/nosql/hibernate-ogm/src/test/java/org/javaee7/extra/nosql/hibernateogm/commons/AbstractOgmTest.java
deleted file mode 100644
index 3997cb928..000000000
--- a/extra/nosql/hibernate-ogm/src/test/java/org/javaee7/extra/nosql/hibernateogm/commons/AbstractOgmTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package org.javaee7.extra.nosql.hibernateogm.commons;
-
-import javax.inject.Inject;
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-import javax.transaction.UserTransaction;
-
-import org.jboss.shrinkwrap.api.ShrinkWrap;
-import org.jboss.shrinkwrap.api.asset.EmptyAsset;
-import org.jboss.shrinkwrap.api.spec.WebArchive;
-import org.junit.Test;
-
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.jboss.shrinkwrap.resolver.api.maven.Maven.resolver;
-import static org.junit.Assert.assertThat;
-
-/**
- * @author Guillaume Scheibel
- */
-public abstract class AbstractOgmTest {
- final static String OGM_VERSION = "4.0.0-SNAPSHOT";
- @PersistenceContext
- EntityManager entityManager;
- @Inject
- UserTransaction ut;
-
- public static WebArchive createDeployment(String ogmModuleName) {
- WebArchive webArchive = ShrinkWrap.create( WebArchive.class )
- .addClass( Person.class )
- .addClass( AbstractOgmTest.class )
- .addAsResource( ogmModuleName + "-persistence.xml", "META-INF/persistence.xml" )
- .addAsWebInfResource( EmptyAsset.INSTANCE, "beans.xml" )
- .addAsLibraries(
- resolver().resolve(
- "org.hibernate.ogm:hibernate-ogm-core:" + OGM_VERSION,
- "org.hibernate.ogm:hibernate-ogm-" + ogmModuleName + ":" + OGM_VERSION
- )
- .withTransitivity()
- .asFile()
- );
- return webArchive;
- }
-
- @Test
- public void insertEntityTest() throws Exception {
- final String name = "Guillaume";
- final Long id = 1L;
- ut.begin();
- Person guillaume = new Person( id, name );
- entityManager.persist( guillaume );
- ut.commit();
-
- Person person = entityManager.find( Person.class, id );
- assertThat( person, is( notNullValue() ) );
- assertThat( person.getId(), is( id ) );
- assertThat( person.getName(), is( equalTo( name ) ) );
- }
-}
diff --git a/extra/nosql/hibernate-ogm/src/test/java/org/javaee7/extra/nosql/hibernateogm/commons/Person.java b/extra/nosql/hibernate-ogm/src/test/java/org/javaee7/extra/nosql/hibernateogm/commons/Person.java
deleted file mode 100644
index f3ee3d9a6..000000000
--- a/extra/nosql/hibernate-ogm/src/test/java/org/javaee7/extra/nosql/hibernateogm/commons/Person.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package org.javaee7.extra.nosql.hibernateogm.commons;
-
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.validation.constraints.NotNull;
-
-@Entity
-public class Person {
-
- @Id
- private Long id = null;
- @NotNull
- private String name;
-
- public Person() {
- super();
- }
-
- public Person(Long id, String name) {
- this.id = id;
- this.name = name;
- }
-
- public Long getId() {
- return id;
- }
-
- public void setId(Long id) {
- this.id = id;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- @Override
- public String toString() {
- return "Person{" +
- "id=" + id +
- ", name='" + name + '\'' +
- '}';
- }
-
- @Override
- public boolean equals(Object o) {
- if ( this == o ) {
- return true;
- }
- if ( o == null || getClass() != o.getClass() ) {
- return false;
- }
-
- Person person = (Person) o;
-
- if ( id != null ? !id.equals( person.id ) : person.id != null ) {
- return false;
- }
- if ( name != null ? !name.equals( person.name ) : person.name != null ) {
- return false;
- }
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = id != null ? id.hashCode() : 0;
- result = 31 * result + ( name != null ? name.hashCode() : 0 );
- return result;
- }
-}
diff --git a/extra/nosql/hibernate-ogm/src/test/resources/arquillian.xml b/extra/nosql/hibernate-ogm/src/test/resources/arquillian.xml
deleted file mode 100644
index 7427c8ea8..000000000
--- a/extra/nosql/hibernate-ogm/src/test/resources/arquillian.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
- ${serverRoot:target/wildfly-8.0.0.Beta1}
- ${serverProfile:standalone-full.xml}
-
-
-
-
\ No newline at end of file
diff --git a/extra/nosql/hibernate-ogm/src/test/resources/ehcache-persistence.xml b/extra/nosql/hibernate-ogm/src/test/resources/ehcache-persistence.xml
deleted file mode 100644
index d92d6d2ed..000000000
--- a/extra/nosql/hibernate-ogm/src/test/resources/ehcache-persistence.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
- org.hibernate.ogm.jpa.HibernateOgmPersistence
- org.javaee7.extra.nosql.hibernateogm.commons.Person
-
-
-
-
-
\ No newline at end of file
diff --git a/extra/nosql/mongo/pom.xml b/extra/nosql/mongo/pom.xml
deleted file mode 100644
index 152582c7c..000000000
--- a/extra/nosql/mongo/pom.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
- 4.0.0
-
- org.javaee7.extra.nosql
- extra-nosql-samples
- 1.0-SNAPSHOT
- ../pom.xml
-
-
- org.javaee7.extra.nosql
- mongo
- 1.0-SNAPSHOT
- war
-
-
-
- org.mongodb
- mongo-java-driver
- 1.3
-
-
-
diff --git a/extra/nosql/mongo/src/main/java/org/javaee7/extra/nosql/mongo/Person.java b/extra/nosql/mongo/src/main/java/org/javaee7/extra/nosql/mongo/Person.java
deleted file mode 100644
index 52c203032..000000000
--- a/extra/nosql/mongo/src/main/java/org/javaee7/extra/nosql/mongo/Person.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.nosql.mongo;
-
-import com.mongodb.BasicDBObject;
-import com.mongodb.DBObject;
-import javax.enterprise.inject.Model;
-import javax.validation.constraints.Size;
-
-/**
- * @author Arun Gupta
- */
-@Model
-public class Person {
-
- @Size(min = 1, max = 20)
- private String name;
-
- private int age;
-
- public Person() {
- }
-
- public Person(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
-
- public BasicDBObject toDBObject() {
- BasicDBObject doc = new BasicDBObject();
-
- doc.put("name", name);
- doc.put("age", age);
-
- return doc;
- }
-
- public static Person fromDBObject(DBObject doc) {
- Person p = new Person();
-
- p.name = (String) doc.get("name");
- p.age = (int) doc.get("age");
-
- return p;
- }
-
- @Override
- public String toString() {
- return name + ", " + age;
- }
-}
diff --git a/extra/nosql/mongo/src/main/java/org/javaee7/extra/nosql/mongo/PersonSessionBean.java b/extra/nosql/mongo/src/main/java/org/javaee7/extra/nosql/mongo/PersonSessionBean.java
deleted file mode 100644
index 0532ed813..000000000
--- a/extra/nosql/mongo/src/main/java/org/javaee7/extra/nosql/mongo/PersonSessionBean.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.nosql.mongo;
-
-import com.mongodb.BasicDBObject;
-import com.mongodb.DB;
-import com.mongodb.DBCollection;
-import com.mongodb.DBCursor;
-import com.mongodb.DBObject;
-import com.mongodb.Mongo;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.annotation.PostConstruct;
-import javax.ejb.Stateless;
-import javax.inject.Inject;
-import javax.inject.Named;
-
-/**
- * @author Arun Gupta
- */
-@Named
-@Stateless
-public class PersonSessionBean {
-
- @Inject
- Person person;
-
- DBCollection personCollection;
-
- @PostConstruct
- private void initDB() {
- try {
- // Get an instance of Mongo
- Mongo m = new Mongo("localhost", 27017);
- DB db = m.getDB("personDB");
- personCollection = db.getCollection("persons");
- if (personCollection == null) {
- personCollection = db.createCollection("persons", null);
- }
- } catch (UnknownHostException ex) {
- Logger.getLogger(PersonSessionBean.class.getName()).log(Level.SEVERE, null, ex);
- }
- }
-
- public void createPerson() {
- BasicDBObject doc = person.toDBObject();
- personCollection.insert(doc);
- }
-
- public List getPersons() {
- List persons = new ArrayList();
- DBCursor cur = personCollection.find();
- System.out.println("getPersons: Found " + cur.length() + " person(s)");
- for (DBObject dbo : cur.toArray()) {
- persons.add(Person.fromDBObject(dbo));
- }
-
- return persons;
- }
-}
diff --git a/extra/nosql/mongo/src/main/webapp/WEB-INF/beans.xml b/extra/nosql/mongo/src/main/webapp/WEB-INF/beans.xml
deleted file mode 100644
index aa81c7c3c..000000000
--- a/extra/nosql/mongo/src/main/webapp/WEB-INF/beans.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/extra/nosql/mongo/src/main/webapp/WEB-INF/template.xhtml b/extra/nosql/mongo/src/main/webapp/WEB-INF/template.xhtml
deleted file mode 100644
index dd1a75ece..000000000
--- a/extra/nosql/mongo/src/main/webapp/WEB-INF/template.xhtml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
- Mongo using Java EE 7
-
-
-
-
-
- Mongo using Java EE 7
-
-
-
- Content
-
-
-
-
-
diff --git a/extra/nosql/mongo/src/main/webapp/WEB-INF/web.xml b/extra/nosql/mongo/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index c5e7c7381..000000000
--- a/extra/nosql/mongo/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
- javax.faces.PROJECT_STAGE
- Development
-
-
- Faces Servlet
- javax.faces.webapp.FacesServlet
- 1
-
-
- Faces Servlet
- /faces/*
-
-
-
- 30
-
-
-
- faces/index.xhtml
-
-
diff --git a/extra/nosql/mongo/src/main/webapp/index.xhtml b/extra/nosql/mongo/src/main/webapp/index.xhtml
deleted file mode 100644
index aaf6bc1f3..000000000
--- a/extra/nosql/mongo/src/main/webapp/index.xhtml
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Name:
- Age:
-
-
-
- Make sure to download Mongo. Follow the quick start to start the server:
-
- sudo mkdir -p /data/db
- sudo chown `id -u` /data/db
- ./bin/mongod
-
-
-
-
-
-
-
diff --git a/extra/nosql/mongo/src/main/webapp/resources/css/cssLayout.css b/extra/nosql/mongo/src/main/webapp/resources/css/cssLayout.css
deleted file mode 100644
index 8ee7cebe3..000000000
--- a/extra/nosql/mongo/src/main/webapp/resources/css/cssLayout.css
+++ /dev/null
@@ -1,61 +0,0 @@
-
-#top {
- position: relative;
- background-color: #036fab;
- color: white;
- padding: 5px;
- margin: 0px 0px 10px 0px;
-}
-
-#bottom {
- position: relative;
- background-color: #c2dfef;
- padding: 5px;
- margin: 10px 0px 0px 0px;
-}
-
-#left {
- float: left;
- background-color: #ece3a5;
- padding: 5px;
- width: 150px;
-}
-
-#right {
- float: right;
- background-color: #ece3a5;
- padding: 5px;
- width: 150px;
-}
-
-.center_content {
- position: relative;
- background-color: #dddddd;
- padding: 5px;
-}
-
-.left_content {
- background-color: #dddddd;
- padding: 5px;
- margin-left: 170px;
-}
-
-.right_content {
- background-color: #dddddd;
- padding: 5px;
- margin: 0px 170px 0px 170px;
-}
-
-#top a:link, #top a:visited {
- color: white;
- font-weight : bold;
- text-decoration: none;
-}
-
-#top a:link:hover, #top a:visited:hover {
- color: black;
- font-weight : bold;
- text-decoration : underline;
-}
-
-
diff --git a/extra/nosql/mongo/src/main/webapp/resources/css/default.css b/extra/nosql/mongo/src/main/webapp/resources/css/default.css
deleted file mode 100644
index 6cbc3d18e..000000000
--- a/extra/nosql/mongo/src/main/webapp/resources/css/default.css
+++ /dev/null
@@ -1,29 +0,0 @@
-body {
- background-color: #ffffff;
- font-size: 12px;
- font-family: Verdana, "Verdana CE", Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif;
- color: #000000;
- margin: 10px;
-}
-
-h1 {
- font-family: Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif;
- border-bottom: 1px solid #AFAFAF;
- font-size: 16px;
- font-weight: bold;
- margin: 0px;
- padding: 0px;
- color: #D20005;
-}
-
-a:link, a:visited {
- color: #045491;
- font-weight : bold;
- text-decoration: none;
-}
-
-a:link:hover, a:visited:hover {
- color: #045491;
- font-weight : bold;
- text-decoration : underline;
-}
diff --git a/extra/nosql/mongo/src/main/webapp/show.xhtml b/extra/nosql/mongo/src/main/webapp/show.xhtml
deleted file mode 100644
index 5ffc5aae0..000000000
--- a/extra/nosql/mongo/src/main/webapp/show.xhtml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Name #{p.name}
- Age #{p.age}
-
-
-
-
-
-
-
-
-
-
-
diff --git a/extra/nosql/neo4j/pom.xml b/extra/nosql/neo4j/pom.xml
deleted file mode 100644
index 3abd78f3d..000000000
--- a/extra/nosql/neo4j/pom.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
- 4.0.0
-
- org.javaee7.extra.nosql
- extra-nosql-samples
- 1.0-SNAPSHOT
- ../pom.xml
-
-
- org.javaee7.extra.nosql
- neo4j
- 1.0-SNAPSHOT
- war
-
-
-
- org.neo4j
- neo4j
- 2.0.0-M05
-
-
-
diff --git a/extra/nosql/neo4j/src/main/java/org/javaee7/extra/nosql/neo4j/BackingBean.java b/extra/nosql/neo4j/src/main/java/org/javaee7/extra/nosql/neo4j/BackingBean.java
deleted file mode 100644
index 2b13229f8..000000000
--- a/extra/nosql/neo4j/src/main/java/org/javaee7/extra/nosql/neo4j/BackingBean.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.nosql.neo4j;
-
-import javax.enterprise.context.ApplicationScoped;
-import javax.inject.Named;
-import javax.validation.constraints.Size;
-
-/**
- * @author Arun Gupta
- */
-@Named
-@ApplicationScoped
-public class BackingBean {
-
- @Size(min = 1, max = 20)
- private String name;
-
- private int age;
-
- private String name2;
-
- private int age2;
-
- private String relationship;
-
- public BackingBean() {
- }
-
- public BackingBean(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
-
- public String getName2() {
- return name2;
- }
-
- public void setName2(String name2) {
- this.name2 = name2;
- }
-
- public int getAge2() {
- return age2;
- }
-
- public void setAge2(int age2) {
- this.age2 = age2;
- }
-
- public String getRelationship() {
- return relationship;
- }
-
- public void setRelationship(String relationship) {
- this.relationship = relationship;
- }
-
- public String person1String() {
- return name + ", " + age;
- }
-
- public String person2String() {
- return name2 + ", " + age2;
- }
-}
diff --git a/extra/nosql/neo4j/src/main/java/org/javaee7/extra/nosql/neo4j/Person.java b/extra/nosql/neo4j/src/main/java/org/javaee7/extra/nosql/neo4j/Person.java
deleted file mode 100644
index cf4323903..000000000
--- a/extra/nosql/neo4j/src/main/java/org/javaee7/extra/nosql/neo4j/Person.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.nosql.neo4j;
-
-import java.util.StringTokenizer;
-import javax.validation.constraints.Size;
-
-/**
- * @author Arun Gupta
- */
-public class Person {
-
- @Size(min = 1, max = 20)
- private String name;
-
- private int age;
-
- public Person() {
- }
-
- public Person(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
-
- @Override
- public String toString() {
- return name + ", " + age;
- }
-
- public static final Person fromString(String string) {
- StringTokenizer tokens = new StringTokenizer(string, ",");
- Person p = new Person(tokens.nextToken(), Integer.parseInt(tokens.nextToken().trim()));
-
- return p;
- }
-}
diff --git a/extra/nosql/neo4j/src/main/java/org/javaee7/extra/nosql/neo4j/PersonSessionBean.java b/extra/nosql/neo4j/src/main/java/org/javaee7/extra/nosql/neo4j/PersonSessionBean.java
deleted file mode 100644
index 407917d58..000000000
--- a/extra/nosql/neo4j/src/main/java/org/javaee7/extra/nosql/neo4j/PersonSessionBean.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.nosql.neo4j;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Singleton;
-import org.neo4j.graphdb.GraphDatabaseService;
-import org.neo4j.graphdb.Node;
-import org.neo4j.graphdb.Relationship;
-import org.neo4j.graphdb.RelationshipType;
-import org.neo4j.graphdb.Transaction;
-import org.neo4j.graphdb.factory.GraphDatabaseFactory;
-
-/**
- * @author Arun Gupta
- */
-@Named
-@Singleton
-public class PersonSessionBean {
-
- @Inject
- BackingBean backingBean;
-
- GraphDatabaseService graphDb;
- Node firstNode;
- Node secondNode;
-
- private static enum RelTypes implements RelationshipType {
- SPOUSE, BROTHER, SISTER
- }
-
- Set set = new HashSet<>();
-
- @PostConstruct
- private void initDB() {
- try {
- Path tempDir = Files.createTempDirectory("test-neo4j");
- graphDb = new GraphDatabaseFactory().newEmbeddedDatabase(tempDir.toString());
- try (Transaction tx = graphDb.beginTx()) {
- firstNode = graphDb.createNode();
- secondNode = graphDb.createNode();
- tx.success();
- }
- } catch (IOException ex) {
- Logger.getLogger(PersonSessionBean.class.getName()).log(Level.SEVERE, null, ex);
- }
- }
-
- @PreDestroy
- private void stopDB() {
- graphDb.shutdown();
- }
-
- public void createPerson() {
- try (Transaction tx = graphDb.beginTx()) {
- firstNode.setProperty(backingBean.getName(), backingBean.person1String());
- secondNode.setProperty(backingBean.getName2(), backingBean.person2String());
- switch (backingBean.getRelationship()) {
- case "spouse":
- firstNode.createRelationshipTo(secondNode, RelTypes.SPOUSE);
- break;
- case "brother":
- firstNode.createRelationshipTo(secondNode, RelTypes.BROTHER);
- break;
- case "sister":
- firstNode.createRelationshipTo(secondNode, RelTypes.SISTER);
- break;
- }
- tx.success();
- }
- }
-
- public List getPersons() {
- List beans = new ArrayList();
- try (Transaction tx = graphDb.beginTx()) {
- for (String key : firstNode.getPropertyKeys()) {
- BackingBean bean = new BackingBean();
- Person p = Person.fromString((String) firstNode.getProperty(key));
- bean.setName(p.getName());
- bean.setAge(p.getAge());
- for (Relationship r : firstNode.getRelationships(RelTypes.SPOUSE, RelTypes.SISTER, RelTypes.BROTHER)) {
- if (r.isType(RelTypes.SPOUSE)) {
- bean.setRelationship("spouse");
- break;
- } else if (r.isType(RelTypes.SISTER)) {
- bean.setRelationship("sister");
- break;
- } else if (r.isType(RelTypes.BROTHER)) {
- bean.setRelationship("brother");
- break;
- }
- }
- beans.add(bean);
- }
- tx.success();
- }
- return beans;
- }
-}
diff --git a/extra/nosql/neo4j/src/main/webapp/WEB-INF/beans.xml b/extra/nosql/neo4j/src/main/webapp/WEB-INF/beans.xml
deleted file mode 100644
index aa81c7c3c..000000000
--- a/extra/nosql/neo4j/src/main/webapp/WEB-INF/beans.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/extra/nosql/neo4j/src/main/webapp/WEB-INF/template.xhtml b/extra/nosql/neo4j/src/main/webapp/WEB-INF/template.xhtml
deleted file mode 100644
index 9eb7c0652..000000000
--- a/extra/nosql/neo4j/src/main/webapp/WEB-INF/template.xhtml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
- Couchbase using Java EE 7
-
-
-
-
-
- Couchbase using Java EE 7
-
-
-
- Content
-
-
-
-
-
diff --git a/extra/nosql/neo4j/src/main/webapp/WEB-INF/web.xml b/extra/nosql/neo4j/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index c5e7c7381..000000000
--- a/extra/nosql/neo4j/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
- javax.faces.PROJECT_STAGE
- Development
-
-
- Faces Servlet
- javax.faces.webapp.FacesServlet
- 1
-
-
- Faces Servlet
- /faces/*
-
-
-
- 30
-
-
-
- faces/index.xhtml
-
-
diff --git a/extra/nosql/neo4j/src/main/webapp/index.xhtml b/extra/nosql/neo4j/src/main/webapp/index.xhtml
deleted file mode 100644
index 6995adb2a..000000000
--- a/extra/nosql/neo4j/src/main/webapp/index.xhtml
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Name:
- Age:
- Related as:
-
-
-
-
-
-
- Name2:
- Age2:
-
-
-
- Download Neo4j Community version . Untar and start the server as "bin/neo4j start".
-
-
-
-
-
-
diff --git a/extra/nosql/neo4j/src/main/webapp/resources/css/cssLayout.css b/extra/nosql/neo4j/src/main/webapp/resources/css/cssLayout.css
deleted file mode 100644
index 8ee7cebe3..000000000
--- a/extra/nosql/neo4j/src/main/webapp/resources/css/cssLayout.css
+++ /dev/null
@@ -1,61 +0,0 @@
-
-#top {
- position: relative;
- background-color: #036fab;
- color: white;
- padding: 5px;
- margin: 0px 0px 10px 0px;
-}
-
-#bottom {
- position: relative;
- background-color: #c2dfef;
- padding: 5px;
- margin: 10px 0px 0px 0px;
-}
-
-#left {
- float: left;
- background-color: #ece3a5;
- padding: 5px;
- width: 150px;
-}
-
-#right {
- float: right;
- background-color: #ece3a5;
- padding: 5px;
- width: 150px;
-}
-
-.center_content {
- position: relative;
- background-color: #dddddd;
- padding: 5px;
-}
-
-.left_content {
- background-color: #dddddd;
- padding: 5px;
- margin-left: 170px;
-}
-
-.right_content {
- background-color: #dddddd;
- padding: 5px;
- margin: 0px 170px 0px 170px;
-}
-
-#top a:link, #top a:visited {
- color: white;
- font-weight : bold;
- text-decoration: none;
-}
-
-#top a:link:hover, #top a:visited:hover {
- color: black;
- font-weight : bold;
- text-decoration : underline;
-}
-
-
diff --git a/extra/nosql/neo4j/src/main/webapp/resources/css/default.css b/extra/nosql/neo4j/src/main/webapp/resources/css/default.css
deleted file mode 100644
index 6cbc3d18e..000000000
--- a/extra/nosql/neo4j/src/main/webapp/resources/css/default.css
+++ /dev/null
@@ -1,29 +0,0 @@
-body {
- background-color: #ffffff;
- font-size: 12px;
- font-family: Verdana, "Verdana CE", Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif;
- color: #000000;
- margin: 10px;
-}
-
-h1 {
- font-family: Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif;
- border-bottom: 1px solid #AFAFAF;
- font-size: 16px;
- font-weight: bold;
- margin: 0px;
- padding: 0px;
- color: #D20005;
-}
-
-a:link, a:visited {
- color: #045491;
- font-weight : bold;
- text-decoration: none;
-}
-
-a:link:hover, a:visited:hover {
- color: #045491;
- font-weight : bold;
- text-decoration : underline;
-}
diff --git a/extra/nosql/neo4j/src/main/webapp/show.xhtml b/extra/nosql/neo4j/src/main/webapp/show.xhtml
deleted file mode 100644
index 48b1ea71c..000000000
--- a/extra/nosql/neo4j/src/main/webapp/show.xhtml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Name #{p.name}
- Age #{p.age}
- Relationship #{p.relationship}
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/extra/nosql/oracle/pom.xml b/extra/nosql/oracle/pom.xml
deleted file mode 100644
index 125b0685b..000000000
--- a/extra/nosql/oracle/pom.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
- 4.0.0
-
- org.javaee7.extra.nosql
- extra-nosql-samples
- 1.0-SNAPSHOT
- ../pom.xml
-
-
- org.javaee7.extra.nosql
- oracle
- 1.0-SNAPSHOT
- war
-
-
-
- com.oracle.nosql
- oracle-nosql
- 2.1.19
-
-
-
diff --git a/extra/nosql/oracle/src/main/java/org/javaee7/extra/nosql/oracle/Person.java b/extra/nosql/oracle/src/main/java/org/javaee7/extra/nosql/oracle/Person.java
deleted file mode 100644
index bec1295d5..000000000
--- a/extra/nosql/oracle/src/main/java/org/javaee7/extra/nosql/oracle/Person.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.nosql.oracle;
-
-import java.io.Serializable;
-import java.util.StringTokenizer;
-import javax.enterprise.context.ApplicationScoped;
-import javax.inject.Named;
-import javax.validation.constraints.Size;
-
-/**
- * @author Arun Gupta
- */
-@Named
-@ApplicationScoped
-public class Person implements Serializable {
-
- @Size(min = 1, max = 20)
- private String name;
-
- private int age;
-
- public Person() {
- }
-
- public Person(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
-
- @Override
- public String toString() {
- return name + ", " + age;
- }
-
- public static Person fromString(String string) {
- StringTokenizer tokens = new StringTokenizer(string, ",");
-
- return new Person(tokens.nextToken(), Integer.parseInt(tokens.nextToken().trim()));
- }
-
-}
diff --git a/extra/nosql/oracle/src/main/java/org/javaee7/extra/nosql/oracle/PersonSessionBean.java b/extra/nosql/oracle/src/main/java/org/javaee7/extra/nosql/oracle/PersonSessionBean.java
deleted file mode 100644
index bc1a17a53..000000000
--- a/extra/nosql/oracle/src/main/java/org/javaee7/extra/nosql/oracle/PersonSessionBean.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.nosql.oracle;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Singleton;
-import oracle.kv.KVStore;
-import oracle.kv.KVStoreConfig;
-import oracle.kv.KVStoreFactory;
-import oracle.kv.Key;
-import oracle.kv.Value;
-
-/**
- * @author Arun Gupta
- */
-@Named
-@Singleton
-public class PersonSessionBean {
-
- @Inject
- Person person;
-
- Set set = new HashSet<>();
-
- private KVStore store;
-
- @PostConstruct
- private void initDB() {
- // bootstrap
- store = KVStoreFactory.getStore(new KVStoreConfig("kvstore", "localhost:5000"));
- }
-
- @PreDestroy
- private void stopDB() {
- }
-
- public void createPerson() {
- store.put(Key.createKey(person.getName()), Value.createValue(new Person(person.getName(), person.getAge()).toString().getBytes()));
- set.add(person.getName());
- }
-
- public List getPersons() {
- List persons = new ArrayList();
- for (String key : set) {
- persons.add(Person.fromString(new String(store.get(Key.createKey(key)).getValue().getValue())));
- }
- return persons;
- }
-}
diff --git a/extra/nosql/oracle/src/main/webapp/WEB-INF/beans.xml b/extra/nosql/oracle/src/main/webapp/WEB-INF/beans.xml
deleted file mode 100644
index aa81c7c3c..000000000
--- a/extra/nosql/oracle/src/main/webapp/WEB-INF/beans.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/extra/nosql/oracle/src/main/webapp/WEB-INF/template.xhtml b/extra/nosql/oracle/src/main/webapp/WEB-INF/template.xhtml
deleted file mode 100644
index 3418cda01..000000000
--- a/extra/nosql/oracle/src/main/webapp/WEB-INF/template.xhtml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
- Oracle NoSQL using Java EE 7
-
-
-
-
-
- Oracle NoSQL using Java EE 7
-
-
-
- Content
-
-
-
-
-
diff --git a/extra/nosql/oracle/src/main/webapp/WEB-INF/web.xml b/extra/nosql/oracle/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index c5e7c7381..000000000
--- a/extra/nosql/oracle/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
- javax.faces.PROJECT_STAGE
- Development
-
-
- Faces Servlet
- javax.faces.webapp.FacesServlet
- 1
-
-
- Faces Servlet
- /faces/*
-
-
-
- 30
-
-
-
- faces/index.xhtml
-
-
diff --git a/extra/nosql/oracle/src/main/webapp/index.xhtml b/extra/nosql/oracle/src/main/webapp/index.xhtml
deleted file mode 100644
index 5e1c6d271..000000000
--- a/extra/nosql/oracle/src/main/webapp/index.xhtml
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Name:
- Age:
-
-
-
-
- Download Oracle NoSQL Community Edition and unzip.
- Install the NoSQL Client jar: mvn install:install-file -Dfile=/Users/arungup/tools/oracle/nosql/kv-2.1.19/lib/kvclient.jar -DgroupId=com.oracle.nosql -DartifactId=oracle-nosql -Dversion=2.1.19 -Dpackaging=jar
- Start the server as: java -jar lib/kvstore.jar kvlite to see the output as:
-Created new kvlite store with args:
--root ./kvroot -store kvstore -host arungup-mac.local -port 5000 -admin 5001
-
-
-
-
-
-
-
-
diff --git a/extra/nosql/oracle/src/main/webapp/resources/css/cssLayout.css b/extra/nosql/oracle/src/main/webapp/resources/css/cssLayout.css
deleted file mode 100644
index 8ee7cebe3..000000000
--- a/extra/nosql/oracle/src/main/webapp/resources/css/cssLayout.css
+++ /dev/null
@@ -1,61 +0,0 @@
-
-#top {
- position: relative;
- background-color: #036fab;
- color: white;
- padding: 5px;
- margin: 0px 0px 10px 0px;
-}
-
-#bottom {
- position: relative;
- background-color: #c2dfef;
- padding: 5px;
- margin: 10px 0px 0px 0px;
-}
-
-#left {
- float: left;
- background-color: #ece3a5;
- padding: 5px;
- width: 150px;
-}
-
-#right {
- float: right;
- background-color: #ece3a5;
- padding: 5px;
- width: 150px;
-}
-
-.center_content {
- position: relative;
- background-color: #dddddd;
- padding: 5px;
-}
-
-.left_content {
- background-color: #dddddd;
- padding: 5px;
- margin-left: 170px;
-}
-
-.right_content {
- background-color: #dddddd;
- padding: 5px;
- margin: 0px 170px 0px 170px;
-}
-
-#top a:link, #top a:visited {
- color: white;
- font-weight : bold;
- text-decoration: none;
-}
-
-#top a:link:hover, #top a:visited:hover {
- color: black;
- font-weight : bold;
- text-decoration : underline;
-}
-
-
diff --git a/extra/nosql/oracle/src/main/webapp/resources/css/default.css b/extra/nosql/oracle/src/main/webapp/resources/css/default.css
deleted file mode 100644
index 6cbc3d18e..000000000
--- a/extra/nosql/oracle/src/main/webapp/resources/css/default.css
+++ /dev/null
@@ -1,29 +0,0 @@
-body {
- background-color: #ffffff;
- font-size: 12px;
- font-family: Verdana, "Verdana CE", Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif;
- color: #000000;
- margin: 10px;
-}
-
-h1 {
- font-family: Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif;
- border-bottom: 1px solid #AFAFAF;
- font-size: 16px;
- font-weight: bold;
- margin: 0px;
- padding: 0px;
- color: #D20005;
-}
-
-a:link, a:visited {
- color: #045491;
- font-weight : bold;
- text-decoration: none;
-}
-
-a:link:hover, a:visited:hover {
- color: #045491;
- font-weight : bold;
- text-decoration : underline;
-}
diff --git a/extra/nosql/oracle/src/main/webapp/show.xhtml b/extra/nosql/oracle/src/main/webapp/show.xhtml
deleted file mode 100644
index 8f1d60f31..000000000
--- a/extra/nosql/oracle/src/main/webapp/show.xhtml
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Name #{p.name}
- Age #{p.age}
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/extra/nosql/pom.xml b/extra/nosql/pom.xml
deleted file mode 100644
index 59dadab39..000000000
--- a/extra/nosql/pom.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
- 4.0.0
-
- org.javaee7.extra
- extra-samples
- 1.0-SNAPSHOT
- ../pom.xml
-
-
- org.javaee7.extra.nosql
- extra-nosql-samples
- 1.0-SNAPSHOT
- pom
- Java EE 7 Extra NoSQL Samples
-
-
- mongo
- couchbase
- redis
- cassandra
- neo4j
- hbase
- voldemort
- riak
- hibernate-ogm
-
-
-
diff --git a/extra/nosql/redis/pom.xml b/extra/nosql/redis/pom.xml
deleted file mode 100644
index bb38e5f06..000000000
--- a/extra/nosql/redis/pom.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
- 4.0.0
-
- org.javaee7.extra.nosql
- extra-nosql-samples
- 1.0-SNAPSHOT
- ../pom.xml
-
-
- org.javaee7.extra.nosql
- redis
- 1.0-SNAPSHOT
- war
-
-
-
- redis.clients
- jedis
- 2.2.0
-
-
-
diff --git a/extra/nosql/redis/src/main/java/org/javaee7/extra/nosql/redis/Person.java b/extra/nosql/redis/src/main/java/org/javaee7/extra/nosql/redis/Person.java
deleted file mode 100644
index dfbee998a..000000000
--- a/extra/nosql/redis/src/main/java/org/javaee7/extra/nosql/redis/Person.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.nosql.redis;
-
-import java.util.StringTokenizer;
-import javax.enterprise.context.ApplicationScoped;
-import javax.inject.Named;
-import javax.validation.constraints.Size;
-
-/**
- * @author Arun Gupta
- */
-@Named
-@ApplicationScoped
-public class Person {
-
- @Size(min = 1, max = 20)
- private String name;
-
- private int age;
-
- public Person() {
- }
-
- public Person(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
-
- @Override
- public String toString() {
- return name + ", " + age;
- }
-
- public static Person fromString(String string) {
- StringTokenizer tokens = new StringTokenizer(string, ",");
- return new Person(tokens.nextToken(), Integer.parseInt(tokens.nextToken().trim()));
- }
-}
diff --git a/extra/nosql/redis/src/main/java/org/javaee7/extra/nosql/redis/PersonSessionBean.java b/extra/nosql/redis/src/main/java/org/javaee7/extra/nosql/redis/PersonSessionBean.java
deleted file mode 100644
index 5f6884bdf..000000000
--- a/extra/nosql/redis/src/main/java/org/javaee7/extra/nosql/redis/PersonSessionBean.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.nosql.redis;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import javax.ejb.Stateless;
-import javax.inject.Inject;
-import javax.inject.Named;
-import redis.clients.jedis.Jedis;
-
-/**
- * @author Arun Gupta
- */
-@Named
-@Stateless
-public class PersonSessionBean {
-
- @Inject
- Person person;
-
- Jedis jedis;
-
- Set set = new HashSet<>();
-
- @PostConstruct
- private void initDB() {
-// Start embedded Redis
- jedis = new Jedis("localhost", 6379);
- }
-
- @PreDestroy
- private void stopDB() {
- jedis.shutdown();
- }
-
- public void createPerson() {
- jedis.set(person.getName(), new Person(person.getName(), person.getAge()).toString());
- set.add(person.getName());
- }
-
- public List getPersons() {
- List persons = new ArrayList<>();
- for (String key : set) {
- persons.add(Person.fromString(jedis.get(key)));
- }
- return persons;
- }
-}
diff --git a/extra/nosql/redis/src/main/webapp/WEB-INF/beans.xml b/extra/nosql/redis/src/main/webapp/WEB-INF/beans.xml
deleted file mode 100644
index aa81c7c3c..000000000
--- a/extra/nosql/redis/src/main/webapp/WEB-INF/beans.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/extra/nosql/redis/src/main/webapp/WEB-INF/template.xhtml b/extra/nosql/redis/src/main/webapp/WEB-INF/template.xhtml
deleted file mode 100644
index c0d6c22b3..000000000
--- a/extra/nosql/redis/src/main/webapp/WEB-INF/template.xhtml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
- Redis using Java EE 7
-
-
-
-
-
- Redis using Java EE 7
-
-
-
- Content
-
-
-
-
-
diff --git a/extra/nosql/redis/src/main/webapp/WEB-INF/web.xml b/extra/nosql/redis/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index c5e7c7381..000000000
--- a/extra/nosql/redis/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
- javax.faces.PROJECT_STAGE
- Development
-
-
- Faces Servlet
- javax.faces.webapp.FacesServlet
- 1
-
-
- Faces Servlet
- /faces/*
-
-
-
- 30
-
-
-
- faces/index.xhtml
-
-
diff --git a/extra/nosql/redis/src/main/webapp/index.xhtml b/extra/nosql/redis/src/main/webapp/index.xhtml
deleted file mode 100644
index 0adf58b04..000000000
--- a/extra/nosql/redis/src/main/webapp/index.xhtml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Name:
- Age:
-
-
-
- Make sure to download latest stable release, compile, and run it . Look for a message like:
-
- * The server is now ready to accept connections on port 6379
-
-
-
-
-
-
diff --git a/extra/nosql/redis/src/main/webapp/resources/css/cssLayout.css b/extra/nosql/redis/src/main/webapp/resources/css/cssLayout.css
deleted file mode 100644
index 8ee7cebe3..000000000
--- a/extra/nosql/redis/src/main/webapp/resources/css/cssLayout.css
+++ /dev/null
@@ -1,61 +0,0 @@
-
-#top {
- position: relative;
- background-color: #036fab;
- color: white;
- padding: 5px;
- margin: 0px 0px 10px 0px;
-}
-
-#bottom {
- position: relative;
- background-color: #c2dfef;
- padding: 5px;
- margin: 10px 0px 0px 0px;
-}
-
-#left {
- float: left;
- background-color: #ece3a5;
- padding: 5px;
- width: 150px;
-}
-
-#right {
- float: right;
- background-color: #ece3a5;
- padding: 5px;
- width: 150px;
-}
-
-.center_content {
- position: relative;
- background-color: #dddddd;
- padding: 5px;
-}
-
-.left_content {
- background-color: #dddddd;
- padding: 5px;
- margin-left: 170px;
-}
-
-.right_content {
- background-color: #dddddd;
- padding: 5px;
- margin: 0px 170px 0px 170px;
-}
-
-#top a:link, #top a:visited {
- color: white;
- font-weight : bold;
- text-decoration: none;
-}
-
-#top a:link:hover, #top a:visited:hover {
- color: black;
- font-weight : bold;
- text-decoration : underline;
-}
-
-
diff --git a/extra/nosql/redis/src/main/webapp/resources/css/default.css b/extra/nosql/redis/src/main/webapp/resources/css/default.css
deleted file mode 100644
index 6cbc3d18e..000000000
--- a/extra/nosql/redis/src/main/webapp/resources/css/default.css
+++ /dev/null
@@ -1,29 +0,0 @@
-body {
- background-color: #ffffff;
- font-size: 12px;
- font-family: Verdana, "Verdana CE", Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif;
- color: #000000;
- margin: 10px;
-}
-
-h1 {
- font-family: Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif;
- border-bottom: 1px solid #AFAFAF;
- font-size: 16px;
- font-weight: bold;
- margin: 0px;
- padding: 0px;
- color: #D20005;
-}
-
-a:link, a:visited {
- color: #045491;
- font-weight : bold;
- text-decoration: none;
-}
-
-a:link:hover, a:visited:hover {
- color: #045491;
- font-weight : bold;
- text-decoration : underline;
-}
diff --git a/extra/nosql/redis/src/main/webapp/show.xhtml b/extra/nosql/redis/src/main/webapp/show.xhtml
deleted file mode 100644
index 342b4446b..000000000
--- a/extra/nosql/redis/src/main/webapp/show.xhtml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Name #{p.name}
- Age #{p.age}
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/extra/nosql/riak/pom.xml b/extra/nosql/riak/pom.xml
deleted file mode 100644
index 73eb681e1..000000000
--- a/extra/nosql/riak/pom.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
- 4.0.0
-
- org.javaee7.extra.nosql
- extra-nosql-samples
- 1.0-SNAPSHOT
- ../pom.xml
-
-
- org.javaee7.extra.nosql
- riak
- 1.0-SNAPSHOT
- war
-
-
-
- voldemort-repo
- http://repo.springsource.org/plugins-release/
-
-
-
-
-
- com.basho.riak
- riak-client
- 1.4.1
-
-
-
diff --git a/extra/nosql/riak/src/main/java/org/javaee7/extra/nosql/riak/Person.java b/extra/nosql/riak/src/main/java/org/javaee7/extra/nosql/riak/Person.java
deleted file mode 100644
index 154f2a246..000000000
--- a/extra/nosql/riak/src/main/java/org/javaee7/extra/nosql/riak/Person.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.nosql.riak;
-
-import java.io.Serializable;
-import java.util.StringTokenizer;
-import javax.enterprise.context.ApplicationScoped;
-import javax.inject.Named;
-import javax.validation.constraints.Size;
-
-/**
- * @author Arun Gupta
- */
-@Named
-@ApplicationScoped
-public class Person implements Serializable {
-
- @Size(min = 1, max = 20)
- private String name;
-
- private int age;
-
- public Person() {
- }
-
- public Person(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
-
- @Override
- public String toString() {
- return name + ", " + age;
- }
-
- public static Person fromString(String string) {
- StringTokenizer tokens = new StringTokenizer(string, ",");
-
- return new Person(tokens.nextToken(), Integer.parseInt(tokens.nextToken().trim()));
- }
-
-}
diff --git a/extra/nosql/riak/src/main/java/org/javaee7/extra/nosql/riak/PersonSessionBean.java b/extra/nosql/riak/src/main/java/org/javaee7/extra/nosql/riak/PersonSessionBean.java
deleted file mode 100644
index 85d04d6ad..000000000
--- a/extra/nosql/riak/src/main/java/org/javaee7/extra/nosql/riak/PersonSessionBean.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.nosql.riak;
-
-import com.basho.riak.client.IRiakClient;
-import com.basho.riak.client.RiakException;
-import com.basho.riak.client.RiakFactory;
-import com.basho.riak.client.RiakRetryFailedException;
-import com.basho.riak.client.bucket.Bucket;
-import com.basho.riak.client.cap.UnresolvedConflictException;
-import com.basho.riak.client.convert.ConversionException;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Singleton;
-
-/**
- * @author Arun Gupta
- */
-@Named
-@Singleton
-public class PersonSessionBean {
-
- @Inject
- Person person;
-
- Set set = new HashSet<>();
- Bucket myBucket;
-
- @PostConstruct
- private void initDB() {
- try {
- IRiakClient client = RiakFactory.pbcClient("localhost", 8087);
- myBucket = client.fetchBucket("test").execute();
- } catch (RiakException ex) {
- Logger.getLogger(PersonSessionBean.class.getName()).log(Level.SEVERE, null, ex);
- }
- }
-
- @PreDestroy
- private void stopDB() {
- }
-
- public void createPerson() {
- try {
- myBucket.store(person.getName(), new Person(person.getName(), person.getAge())).execute();
- set.add(person.getName());
- } catch (RiakRetryFailedException | UnresolvedConflictException | ConversionException ex) {
- Logger.getLogger(PersonSessionBean.class.getName()).log(Level.SEVERE, null, ex);
- }
- }
-
- public List getPersons() {
- List persons = new ArrayList();
- for (String key : set) {
- try {
- Person p = myBucket.fetch(key, Person.class).execute();
- persons.add(p);
- } catch (UnresolvedConflictException | RiakRetryFailedException | ConversionException ex) {
- Logger.getLogger(PersonSessionBean.class.getName()).log(Level.SEVERE, null, ex);
- }
- }
- return persons;
- }
-}
diff --git a/extra/nosql/riak/src/main/webapp/WEB-INF/beans.xml b/extra/nosql/riak/src/main/webapp/WEB-INF/beans.xml
deleted file mode 100644
index aa81c7c3c..000000000
--- a/extra/nosql/riak/src/main/webapp/WEB-INF/beans.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/extra/nosql/riak/src/main/webapp/WEB-INF/template.xhtml b/extra/nosql/riak/src/main/webapp/WEB-INF/template.xhtml
deleted file mode 100644
index 730271b63..000000000
--- a/extra/nosql/riak/src/main/webapp/WEB-INF/template.xhtml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
- Riak using Java EE 7
-
-
-
-
-
- Riak using Java EE 7
-
-
-
- Content
-
-
-
-
-
diff --git a/extra/nosql/riak/src/main/webapp/WEB-INF/web.xml b/extra/nosql/riak/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index c5e7c7381..000000000
--- a/extra/nosql/riak/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
- javax.faces.PROJECT_STAGE
- Development
-
-
- Faces Servlet
- javax.faces.webapp.FacesServlet
- 1
-
-
- Faces Servlet
- /faces/*
-
-
-
- 30
-
-
-
- faces/index.xhtml
-
-
diff --git a/extra/nosql/riak/src/main/webapp/index.xhtml b/extra/nosql/riak/src/main/webapp/index.xhtml
deleted file mode 100644
index b05d3200a..000000000
--- a/extra/nosql/riak/src/main/webapp/index.xhtml
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Name:
- Age:
-
-
-
-
-
- Build from source (more details )
- Install Erlang (more details )
-
- curl -O http://erlang.org/download/otp_src_R15B01.tar.gz
- tar zxvf otp_src_R15B01.tar.gz
- cd otp_src_R15B01
- export CFLAGS=-O0
- ./configure --disable-hipe --enable-smp-support --enable-threads --enable-kernel-poll --enable-darwin-64bit
- unset CFLAGS
- make
- make install
-
- wget http://s3.amazonaws.com/downloads.basho.com/riak/1.4/1.4.2/riak-1.4.2.tar.gz
- tar zxvf riak-1.4.2.tar.gz
- cd riak-1.4.2
- make rel
- cd rel/riak
- ./bin/riak start
- ./bin/riak ping (to verify)
-
-
-
-
-
-
-
diff --git a/extra/nosql/riak/src/main/webapp/resources/css/cssLayout.css b/extra/nosql/riak/src/main/webapp/resources/css/cssLayout.css
deleted file mode 100644
index 8ee7cebe3..000000000
--- a/extra/nosql/riak/src/main/webapp/resources/css/cssLayout.css
+++ /dev/null
@@ -1,61 +0,0 @@
-
-#top {
- position: relative;
- background-color: #036fab;
- color: white;
- padding: 5px;
- margin: 0px 0px 10px 0px;
-}
-
-#bottom {
- position: relative;
- background-color: #c2dfef;
- padding: 5px;
- margin: 10px 0px 0px 0px;
-}
-
-#left {
- float: left;
- background-color: #ece3a5;
- padding: 5px;
- width: 150px;
-}
-
-#right {
- float: right;
- background-color: #ece3a5;
- padding: 5px;
- width: 150px;
-}
-
-.center_content {
- position: relative;
- background-color: #dddddd;
- padding: 5px;
-}
-
-.left_content {
- background-color: #dddddd;
- padding: 5px;
- margin-left: 170px;
-}
-
-.right_content {
- background-color: #dddddd;
- padding: 5px;
- margin: 0px 170px 0px 170px;
-}
-
-#top a:link, #top a:visited {
- color: white;
- font-weight : bold;
- text-decoration: none;
-}
-
-#top a:link:hover, #top a:visited:hover {
- color: black;
- font-weight : bold;
- text-decoration : underline;
-}
-
-
diff --git a/extra/nosql/riak/src/main/webapp/resources/css/default.css b/extra/nosql/riak/src/main/webapp/resources/css/default.css
deleted file mode 100644
index 6cbc3d18e..000000000
--- a/extra/nosql/riak/src/main/webapp/resources/css/default.css
+++ /dev/null
@@ -1,29 +0,0 @@
-body {
- background-color: #ffffff;
- font-size: 12px;
- font-family: Verdana, "Verdana CE", Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif;
- color: #000000;
- margin: 10px;
-}
-
-h1 {
- font-family: Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif;
- border-bottom: 1px solid #AFAFAF;
- font-size: 16px;
- font-weight: bold;
- margin: 0px;
- padding: 0px;
- color: #D20005;
-}
-
-a:link, a:visited {
- color: #045491;
- font-weight : bold;
- text-decoration: none;
-}
-
-a:link:hover, a:visited:hover {
- color: #045491;
- font-weight : bold;
- text-decoration : underline;
-}
diff --git a/extra/nosql/riak/src/main/webapp/show.xhtml b/extra/nosql/riak/src/main/webapp/show.xhtml
deleted file mode 100644
index 8f1d60f31..000000000
--- a/extra/nosql/riak/src/main/webapp/show.xhtml
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Name #{p.name}
- Age #{p.age}
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/extra/nosql/voldemort/pom.xml b/extra/nosql/voldemort/pom.xml
deleted file mode 100644
index 6f7ee6f70..000000000
--- a/extra/nosql/voldemort/pom.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
- 4.0.0
-
- org.javaee7.extra.nosql
- extra-nosql-samples
- 1.0-SNAPSHOT
- ../pom.xml
-
-
- org.javaee7.extra.nosql
- voldemort
- 1.0-SNAPSHOT
- war
-
-
-
- voldemort-repo
- http://repo.springsource.org/plugins-release/
-
-
-
-
-
- voldemort
- voldemort
- 0.96
-
-
- log4j
- log4j
- 1.2.17
-
-
-
diff --git a/extra/nosql/voldemort/src/main/java/org/javaee7/extra/nosql/voldemort/Person.java b/extra/nosql/voldemort/src/main/java/org/javaee7/extra/nosql/voldemort/Person.java
deleted file mode 100644
index 31315a539..000000000
--- a/extra/nosql/voldemort/src/main/java/org/javaee7/extra/nosql/voldemort/Person.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.nosql.voldemort;
-
-import java.io.Serializable;
-import java.util.StringTokenizer;
-import javax.enterprise.context.ApplicationScoped;
-import javax.inject.Named;
-import javax.validation.constraints.Size;
-
-/**
- * @author Arun Gupta
- */
-@Named
-@ApplicationScoped
-public class Person implements Serializable {
-
- @Size(min = 1, max = 20)
- private String name;
-
- private int age;
-
- public Person() {
- }
-
- public Person(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
-
- @Override
- public String toString() {
- return name + ", " + age;
- }
-
- public static Person fromString(String string) {
- StringTokenizer tokens = new StringTokenizer(string, ",");
-
- return new Person(tokens.nextToken(), Integer.parseInt(tokens.nextToken().trim()));
- }
-
-}
diff --git a/extra/nosql/voldemort/src/main/java/org/javaee7/extra/nosql/voldemort/PersonSessionBean.java b/extra/nosql/voldemort/src/main/java/org/javaee7/extra/nosql/voldemort/PersonSessionBean.java
deleted file mode 100644
index 811eedce7..000000000
--- a/extra/nosql/voldemort/src/main/java/org/javaee7/extra/nosql/voldemort/PersonSessionBean.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.nosql.voldemort;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Singleton;
-import voldemort.client.ClientConfig;
-import voldemort.client.SocketStoreClientFactory;
-import voldemort.client.StoreClient;
-import voldemort.client.StoreClientFactory;
-import voldemort.versioning.Versioned;
-
-/**
- * @author Arun Gupta
- */
-@Named
-@Singleton
-public class PersonSessionBean {
-
- @Inject
- Person person;
-
- Set set = new HashSet<>();
-
- StoreClient client;
-
- @PostConstruct
- private void initDB() {
-// // start embedded
-// VoldemortConfig config = VoldemortConfig.loadFromEnvironmentVariable();
-// VoldemortServer server = new VoldemortServer(config);
-// server.start();
-
- // bootstrap
- String bootstrapUrl = "tcp://localhost:6666";
- StoreClientFactory factory = new SocketStoreClientFactory(new ClientConfig().setBootstrapUrls(bootstrapUrl));
-
- // create a client that executes operations on a single store
- client = factory.getStoreClient("test");
- }
-
- @PreDestroy
- private void stopDB() {
- }
-
- public void createPerson() {
- client.put(person.getName(), new Person(person.getName(), person.getAge()).toString());
- set.add(person.getName());
- }
-
- public List getPersons() {
- Map map = client.getAll(set);
- List persons = new ArrayList();
- for (String key : map.keySet()) {
- persons.add(Person.fromString(map.get(key).getValue().toString()));
- }
- return persons;
- }
-}
diff --git a/extra/nosql/voldemort/src/main/webapp/WEB-INF/beans.xml b/extra/nosql/voldemort/src/main/webapp/WEB-INF/beans.xml
deleted file mode 100644
index aa81c7c3c..000000000
--- a/extra/nosql/voldemort/src/main/webapp/WEB-INF/beans.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/extra/nosql/voldemort/src/main/webapp/WEB-INF/template.xhtml b/extra/nosql/voldemort/src/main/webapp/WEB-INF/template.xhtml
deleted file mode 100644
index 31d2e3aeb..000000000
--- a/extra/nosql/voldemort/src/main/webapp/WEB-INF/template.xhtml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
- Voldemort using Java EE 7
-
-
-
-
-
- Voldemort using Java EE 7
-
-
-
- Content
-
-
-
-
-
diff --git a/extra/nosql/voldemort/src/main/webapp/WEB-INF/web.xml b/extra/nosql/voldemort/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index c5e7c7381..000000000
--- a/extra/nosql/voldemort/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
- javax.faces.PROJECT_STAGE
- Development
-
-
- Faces Servlet
- javax.faces.webapp.FacesServlet
- 1
-
-
- Faces Servlet
- /faces/*
-
-
-
- 30
-
-
-
- faces/index.xhtml
-
-
diff --git a/extra/nosql/voldemort/src/main/webapp/index.xhtml b/extra/nosql/voldemort/src/main/webapp/index.xhtml
deleted file mode 100644
index 457c3dba9..000000000
--- a/extra/nosql/voldemort/src/main/webapp/index.xhtml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Name:
- Age:
-
-
-
-
-
-
-
-
-
-
diff --git a/extra/nosql/voldemort/src/main/webapp/resources/css/cssLayout.css b/extra/nosql/voldemort/src/main/webapp/resources/css/cssLayout.css
deleted file mode 100644
index 8ee7cebe3..000000000
--- a/extra/nosql/voldemort/src/main/webapp/resources/css/cssLayout.css
+++ /dev/null
@@ -1,61 +0,0 @@
-
-#top {
- position: relative;
- background-color: #036fab;
- color: white;
- padding: 5px;
- margin: 0px 0px 10px 0px;
-}
-
-#bottom {
- position: relative;
- background-color: #c2dfef;
- padding: 5px;
- margin: 10px 0px 0px 0px;
-}
-
-#left {
- float: left;
- background-color: #ece3a5;
- padding: 5px;
- width: 150px;
-}
-
-#right {
- float: right;
- background-color: #ece3a5;
- padding: 5px;
- width: 150px;
-}
-
-.center_content {
- position: relative;
- background-color: #dddddd;
- padding: 5px;
-}
-
-.left_content {
- background-color: #dddddd;
- padding: 5px;
- margin-left: 170px;
-}
-
-.right_content {
- background-color: #dddddd;
- padding: 5px;
- margin: 0px 170px 0px 170px;
-}
-
-#top a:link, #top a:visited {
- color: white;
- font-weight : bold;
- text-decoration: none;
-}
-
-#top a:link:hover, #top a:visited:hover {
- color: black;
- font-weight : bold;
- text-decoration : underline;
-}
-
-
diff --git a/extra/nosql/voldemort/src/main/webapp/resources/css/default.css b/extra/nosql/voldemort/src/main/webapp/resources/css/default.css
deleted file mode 100644
index 6cbc3d18e..000000000
--- a/extra/nosql/voldemort/src/main/webapp/resources/css/default.css
+++ /dev/null
@@ -1,29 +0,0 @@
-body {
- background-color: #ffffff;
- font-size: 12px;
- font-family: Verdana, "Verdana CE", Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif;
- color: #000000;
- margin: 10px;
-}
-
-h1 {
- font-family: Arial, "Arial CE", "Lucida Grande CE", lucida, "Helvetica CE", sans-serif;
- border-bottom: 1px solid #AFAFAF;
- font-size: 16px;
- font-weight: bold;
- margin: 0px;
- padding: 0px;
- color: #D20005;
-}
-
-a:link, a:visited {
- color: #045491;
- font-weight : bold;
- text-decoration: none;
-}
-
-a:link:hover, a:visited:hover {
- color: #045491;
- font-weight : bold;
- text-decoration : underline;
-}
diff --git a/extra/nosql/voldemort/src/main/webapp/show.xhtml b/extra/nosql/voldemort/src/main/webapp/show.xhtml
deleted file mode 100644
index 8f1d60f31..000000000
--- a/extra/nosql/voldemort/src/main/webapp/show.xhtml
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Name #{p.name}
- Age #{p.age}
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/extra/pom.xml b/extra/pom.xml
deleted file mode 100644
index 4f34511ca..000000000
--- a/extra/pom.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
- 4.0.0
-
- org.javaee7
- javaee7-samples
- 1.0-SNAPSHOT
- ../pom.xml
-
-
- org.javaee7.extra
- extra-samples
- 1.0-SNAPSHOT
- pom
- Java EE 7 Extra Samples
-
-
- quartz
-
- nosql
-
-
diff --git a/extra/quartz/pom.xml b/extra/quartz/pom.xml
deleted file mode 100644
index 3702ea64d..000000000
--- a/extra/quartz/pom.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
- 4.0.0
-
- org.javaee7.extra
- extra-samples
- 1.0-SNAPSHOT
- ../pom.xml
-
-
- org.javaee7.extra
- quartz
- 1.0-SNAPSHOT
- war
-
-
-
- org.quartz-scheduler
- quartz
- 2.2.0
-
-
-
diff --git a/extra/quartz/src/main/java/org/javaee7/extra/quartz/MyBean.java b/extra/quartz/src/main/java/org/javaee7/extra/quartz/MyBean.java
deleted file mode 100644
index 991d85352..000000000
--- a/extra/quartz/src/main/java/org/javaee7/extra/quartz/MyBean.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.quartz;
-
-import java.io.Serializable;
-import javax.transaction.TransactionScoped;
-
-/**
- * @author Arun Gupta
- */
-@TransactionScoped
-public class MyBean implements Serializable {
-
- public String getId() {
- return this + "";
- }
-}
diff --git a/extra/quartz/src/main/java/org/javaee7/extra/quartz/MyCronJob.java b/extra/quartz/src/main/java/org/javaee7/extra/quartz/MyCronJob.java
deleted file mode 100644
index c588d228c..000000000
--- a/extra/quartz/src/main/java/org/javaee7/extra/quartz/MyCronJob.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.quartz;
-
-import java.util.Calendar;
-import org.quartz.Job;
-import org.quartz.JobExecutionContext;
-import org.quartz.JobExecutionException;
-
-/**
- * @author Arun Gupta
- */
-public class MyCronJob implements Job {
-
- @Override
- public void execute(JobExecutionContext jec) throws JobExecutionException {
- System.out.println("MyCronJob.execute: " + Calendar.getInstance().getTime());
- }
-
-}
diff --git a/extra/quartz/src/main/java/org/javaee7/extra/quartz/MySimpleJob.java b/extra/quartz/src/main/java/org/javaee7/extra/quartz/MySimpleJob.java
deleted file mode 100644
index 5b29f1d60..000000000
--- a/extra/quartz/src/main/java/org/javaee7/extra/quartz/MySimpleJob.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.quartz;
-
-import java.util.Calendar;
-import org.quartz.Job;
-import org.quartz.JobExecutionContext;
-import org.quartz.JobExecutionException;
-
-/**
- * @author Arun Gupta
- */
-public class MySimpleJob implements Job {
-
- @Override
- public void execute(JobExecutionContext jec) throws JobExecutionException {
- System.out.println("MySimpleJob.execute: " + Calendar.getInstance().getTime());
- }
-
-}
diff --git a/extra/quartz/src/main/java/org/javaee7/extra/quartz/TestServlet.java b/extra/quartz/src/main/java/org/javaee7/extra/quartz/TestServlet.java
deleted file mode 100644
index a017310e1..000000000
--- a/extra/quartz/src/main/java/org/javaee7/extra/quartz/TestServlet.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.quartz;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.quartz.CronScheduleBuilder;
-import org.quartz.JobBuilder;
-import org.quartz.JobDetail;
-import org.quartz.Scheduler;
-import org.quartz.SchedulerException;
-import org.quartz.SimpleScheduleBuilder;
-import org.quartz.Trigger;
-import org.quartz.TriggerBuilder;
-import org.quartz.impl.StdSchedulerFactory;
-
-/**
- * @author Arun Gupta
- */
-@WebServlet(urlPatterns = {"/TestServlet"})
-public class TestServlet extends HttpServlet {
-
- /**
- * Processes requests for both HTTP GET and POST
- * methods.
- *
- * @param request servlet request
- * @param response servlet response
- * @throws ServletException if a servlet-specific error occurs
- * @throws IOException if an I/O error occurs
- */
- protected void processRequest(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- response.setContentType("text/html;charset=UTF-8");
- try (PrintWriter out = response.getWriter()) {
- out.println("");
- out.println("");
- out.println("");
- out.println("Quartz Scheduler ");
- out.println("");
- out.println("");
- out.println("Quartz Scheduler ");
-
- JobDetail simpleJob = JobBuilder.newJob(MySimpleJob.class).build();
- JobDetail cronJob = JobBuilder.newJob(MyCronJob.class).build();
-
- Trigger simpleTrigger = TriggerBuilder
- .newTrigger()
- .withSchedule(
- SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever()
- )
- .build();
-
- Trigger cronTrigger = TriggerBuilder
- .newTrigger()
- .withSchedule(
- CronScheduleBuilder.cronSchedule("0/3 * * * * ?")
- )
- .build();
-
- Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
-
- out.println("Starting the scheduler");
- scheduler.start();
-
- out.println("Starting Simple Trigger - every 1 second ");
- scheduler.scheduleJob(simpleJob, simpleTrigger);
- out.println("Starting Cron Trigger - every 3 seconds ");
- scheduler.scheduleJob(cronJob, cronTrigger);
-
- out.println("Sleeping for 7 seconds");
- Thread.sleep(7000);
-
- out.println(" Shutting down the scheduler");
- scheduler.shutdown();
-
- out.println(" Check \"server.log\" for output - 8 outputs from simple trigger, 3 from cron trigger");
- out.println("");
- out.println("");
- } catch (SchedulerException | InterruptedException ex) {
- Logger.getLogger(TestServlet.class.getName()).log(Level.SEVERE, null, ex);
- }
- }
-
- //
- /**
- * Handles the HTTP GET method.
- *
- * @param request servlet request
- * @param response servlet response
- * @throws ServletException if a servlet-specific error occurs
- * @throws IOException if an I/O error occurs
- */
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- processRequest(request, response);
- }
-
- /**
- * Handles the HTTP POST method.
- *
- * @param request servlet request
- * @param response servlet response
- * @throws ServletException if a servlet-specific error occurs
- * @throws IOException if an I/O error occurs
- */
- @Override
- protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- processRequest(request, response);
- }
-
- /**
- * Returns a short description of the servlet.
- *
- * @return a String containing servlet description
- */
- @Override
- public String getServletInfo() {
- return "Short description";
- }//
-}
diff --git a/extra/quartz/src/main/webapp/WEB-INF/beans.xml b/extra/quartz/src/main/webapp/WEB-INF/beans.xml
deleted file mode 100644
index aa81c7c3c..000000000
--- a/extra/quartz/src/main/webapp/WEB-INF/beans.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/extra/quartz/src/main/webapp/index.jsp b/extra/quartz/src/main/webapp/index.jsp
deleted file mode 100644
index dfbe5fb27..000000000
--- a/extra/quartz/src/main/webapp/index.jsp
+++ /dev/null
@@ -1,56 +0,0 @@
-
-<%@page contentType="text/html" pageEncoding="UTF-8"%>
-
-
-
-
-
-
- Quartz Scheduler
-
-
- Quartz Scheduler
- Trigger scheduler
-
-
\ No newline at end of file
diff --git a/extra/twitter-search/pom.xml b/extra/twitter-search/pom.xml
deleted file mode 100644
index 75aa4ef73..000000000
--- a/extra/twitter-search/pom.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
- 4.0.0
-
- org.javaee7.extra
- extra-samples
- 1.0-SNAPSHOT
- ../pom.xml
-
-
- org.javaee7.extra
- twitter-search
- 1.0-SNAPSHOT
- war
-
-
-
- org.glassfish.samples
- twitter-api
- 1.0-SNAPSHOT
-
-
- com.sun.jersey.contribs.jersey-oauth
- oauth-client
- 1.11
-
-
- com.sun.jersey.contribs.jersey-oauth
- oauth-signature
- 1.11
-
-
-
-
diff --git a/extra/twitter-search/src/main/java/org/javaee7/extra/twitter/search/TestServlet.java b/extra/twitter-search/src/main/java/org/javaee7/extra/twitter/search/TestServlet.java
deleted file mode 100644
index 57dac711d..000000000
--- a/extra/twitter-search/src/main/java/org/javaee7/extra/twitter/search/TestServlet.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.twitter.search;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import javax.inject.Inject;
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.glassfish.samples.twitter.api.SearchResults;
-import org.glassfish.samples.twitter.api.SearchResultsTweet;
-import org.glassfish.samples.twitter.api.Twitter;
-
-/**
- * @author Arun Gupta
- */
-@WebServlet(urlPatterns = {"/TestServlet"})
-public class TestServlet extends HttpServlet {
-
- @Inject
- Twitter twitter;
-
- /**
- * Processes requests for both HTTP
- * GET and
- * POST methods.
- *
- * @param request servlet request
- * @param response servlet response
- * @throws ServletException if a servlet-specific error occurs
- * @throws IOException if an I/O error occurs
- */
- protected void processRequest(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- response.setContentType("text/html;charset=UTF-8");
- try (PrintWriter out = response.getWriter()) {
- out.println("");
- out.println("");
- out.println("");
- out.println("Servlet TestServlet ");
- out.println("");
- out.println("");
- out.println("Servlet TestServlet at " + request.getContextPath() + " ");
- SearchResults results = twitter.search("%23javaone%20%23javaee7%20%23q1", SearchResults.class);
- for (SearchResultsTweet tweet : results.getResults()) {
- tweet.getFrom_user();
- }
- out.println("");
- out.println("");
- }
- }
-
- //
- /**
- * Handles the HTTP
- * GET method.
- *
- * @param request servlet request
- * @param response servlet response
- * @throws ServletException if a servlet-specific error occurs
- * @throws IOException if an I/O error occurs
- */
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- processRequest(request, response);
- }
-
- /**
- * Handles the HTTP
- * POST method.
- *
- * @param request servlet request
- * @param response servlet response
- * @throws ServletException if a servlet-specific error occurs
- * @throws IOException if an I/O error occurs
- */
- @Override
- protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- processRequest(request, response);
- }
-
- /**
- * Returns a short description of the servlet.
- *
- * @return a String containing servlet description
- */
- @Override
- public String getServletInfo() {
- return "Short description";
- }//
-}
diff --git a/extra/twitter-search/src/main/java/org/javaee7/extra/twitter/search/TwitterSearch.java b/extra/twitter-search/src/main/java/org/javaee7/extra/twitter/search/TwitterSearch.java
deleted file mode 100644
index 6d851356a..000000000
--- a/extra/twitter-search/src/main/java/org/javaee7/extra/twitter/search/TwitterSearch.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
-package org.javaee7.extra.twitter.search;
-
-import javax.inject.Inject;
-import org.glassfish.samples.twitter.api.SearchResults;
-import org.glassfish.samples.twitter.api.Twitter;
-
-/**
- * @author Arun Gupta
- */
-public class TwitterSearch {
-
- @Inject
- Twitter twitter;
-
- public SearchResults getResults(String query) {
- return twitter.search(query, SearchResults.class);
- }
-}
diff --git a/extra/twitter-search/src/main/webapp/WEB-INF/beans.xml b/extra/twitter-search/src/main/webapp/WEB-INF/beans.xml
deleted file mode 100644
index aa81c7c3c..000000000
--- a/extra/twitter-search/src/main/webapp/WEB-INF/beans.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/extra/twitter-search/src/main/webapp/index.jsp b/extra/twitter-search/src/main/webapp/index.jsp
deleted file mode 100644
index ab292c347..000000000
--- a/extra/twitter-search/src/main/webapp/index.jsp
+++ /dev/null
@@ -1,13 +0,0 @@
-<%@page contentType="text/html" pageEncoding="UTF-8"%>
-
-
-
-
-
- JSP Page
-
-
- Hello World!
-
-
diff --git a/interceptor/README.md b/interceptor/README.md
new file mode 100644
index 000000000..92e052719
--- /dev/null
+++ b/interceptor/README.md
@@ -0,0 +1,13 @@
+# Java EE 7 Samples: Interceptor 1.2 #
+
+The [JSR 318](https://jcp.org/en/jsr/detail?id=318) specifies Interceptors 1.2. Since this is a maintenance release on top of 1.1 the JSR number still remained the same as EJB 3.1 (JSR 318).
+
+## Samples ##
+
+ - around-construct
+
+## How to run
+
+More information on how to run can be found at:
+
+
diff --git a/interceptor/around-construct/pom.xml b/interceptor/around-construct/pom.xml
new file mode 100644
index 000000000..4efdff461
--- /dev/null
+++ b/interceptor/around-construct/pom.xml
@@ -0,0 +1,13 @@
+
+
+ 4.0.0
+
+
+ org.javaee7
+ interceptor
+ 1.0-SNAPSHOT
+ ../pom.xml
+
+ interceptor-around-construct
+ Java EE 7 Sample: interceptor - around-construct
+
diff --git a/interceptor/around-construct/src/main/java/org/javaee7/interceptor/aroundconstruct/Greeting.java b/interceptor/around-construct/src/main/java/org/javaee7/interceptor/aroundconstruct/Greeting.java
new file mode 100644
index 000000000..59c96bfcd
--- /dev/null
+++ b/interceptor/around-construct/src/main/java/org/javaee7/interceptor/aroundconstruct/Greeting.java
@@ -0,0 +1,12 @@
+package org.javaee7.interceptor.aroundconstruct;
+
+/**
+ * @author Radim Hanus
+ */
+public interface Greeting {
+ boolean isConstructed();
+
+ boolean isInitialized();
+
+ Param getParam();
+}
diff --git a/interceptor/around-construct/src/main/java/org/javaee7/interceptor/aroundconstruct/GreetingBean.java b/interceptor/around-construct/src/main/java/org/javaee7/interceptor/aroundconstruct/GreetingBean.java
new file mode 100644
index 000000000..e09b539a1
--- /dev/null
+++ b/interceptor/around-construct/src/main/java/org/javaee7/interceptor/aroundconstruct/GreetingBean.java
@@ -0,0 +1,41 @@
+package org.javaee7.interceptor.aroundconstruct;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+
+/**
+ * @author Radim Hanus
+ */
+@MyInterceptorBinding
+public class GreetingBean implements Greeting {
+ private boolean constructed = false;
+ private boolean initialized = false;
+
+ private Param param;
+
+ @Inject
+ public GreetingBean(Param param) {
+ this.param = param;
+ constructed = true;
+ }
+
+ @PostConstruct
+ void onPostConstruct() {
+ initialized = true;
+ }
+
+ @Override
+ public boolean isConstructed() {
+ return constructed;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return initialized;
+ }
+
+ @Override
+ public Param getParam() {
+ return param;
+ }
+}
diff --git a/interceptor/around-construct/src/main/java/org/javaee7/interceptor/aroundconstruct/GreetingParam.java b/interceptor/around-construct/src/main/java/org/javaee7/interceptor/aroundconstruct/GreetingParam.java
new file mode 100644
index 000000000..477f2a92f
--- /dev/null
+++ b/interceptor/around-construct/src/main/java/org/javaee7/interceptor/aroundconstruct/GreetingParam.java
@@ -0,0 +1,17 @@
+package org.javaee7.interceptor.aroundconstruct;
+
+/**
+ * @author Radim Hanus
+ */
+public class GreetingParam implements Param {
+ private String value;
+
+ public GreetingParam() {
+ value = "Greeting";
+ }
+
+ @Override
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/interceptor/around-construct/src/main/java/org/javaee7/interceptor/aroundconstruct/MyInterceptor.java b/interceptor/around-construct/src/main/java/org/javaee7/interceptor/aroundconstruct/MyInterceptor.java
new file mode 100644
index 000000000..45a093154
--- /dev/null
+++ b/interceptor/around-construct/src/main/java/org/javaee7/interceptor/aroundconstruct/MyInterceptor.java
@@ -0,0 +1,61 @@
+package org.javaee7.interceptor.aroundconstruct;
+
+import javax.interceptor.AroundConstruct;
+import javax.interceptor.Interceptor;
+import javax.interceptor.InvocationContext;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+/**
+ * @author Radim Hanus
+ */
+@Interceptor
+@MyInterceptorBinding
+public class MyInterceptor {
+ @AroundConstruct
+ public Object onConstruct(InvocationContext context) throws Exception {
+ // null before the InvocationContext.proceed() returns
+ Object target = context.getTarget();
+ isNull(target);
+ // null in case of AroundConstruct
+ Method method = context.getMethod();
+ isNull(method);
+ // NOT null in case of AroundConstruct
+ Constructor ctor = context.getConstructor();
+ isNotNull(ctor);
+
+ // perform the constructor injection
+ Object result = context.proceed();
+ isNull(result);
+
+ // NOT null after the InvocationContext.proceed() completes
+ target = context.getTarget();
+ isNotNull(target);
+ // a constructor should have been called
+ GreetingBean bean = (GreetingBean) target;
+ isBoolean(bean.isConstructed(), true);
+ isBoolean(bean.isInitialized(), false);
+ // constructor injection should have been done
+ isNotNull(bean.getParam());
+
+ return null;
+ }
+
+ private static void isNull(Object o) throws Exception {
+ if (o != null) {
+ throw new IllegalStateException("null required");
+ }
+ }
+
+ private static void isNotNull(Object o) throws Exception {
+ if (o == null) {
+ throw new IllegalStateException("not null required");
+ }
+ }
+
+ private static void isBoolean(Object o, Boolean value) {
+ if (!o.equals(value)) {
+ throw new IllegalStateException(value + " required");
+ }
+ }
+}
diff --git a/interceptor/around-construct/src/main/java/org/javaee7/interceptor/aroundconstruct/MyInterceptorBinding.java b/interceptor/around-construct/src/main/java/org/javaee7/interceptor/aroundconstruct/MyInterceptorBinding.java
new file mode 100644
index 000000000..e7d17b872
--- /dev/null
+++ b/interceptor/around-construct/src/main/java/org/javaee7/interceptor/aroundconstruct/MyInterceptorBinding.java
@@ -0,0 +1,18 @@
+package org.javaee7.interceptor.aroundconstruct;
+
+import javax.interceptor.InterceptorBinding;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * @author Radim Hanus
+ */
+@InterceptorBinding
+@Retention(RUNTIME)
+@Target({ METHOD, TYPE })
+public @interface MyInterceptorBinding {
+}
diff --git a/interceptor/around-construct/src/main/java/org/javaee7/interceptor/aroundconstruct/Param.java b/interceptor/around-construct/src/main/java/org/javaee7/interceptor/aroundconstruct/Param.java
new file mode 100644
index 000000000..8aab12b2f
--- /dev/null
+++ b/interceptor/around-construct/src/main/java/org/javaee7/interceptor/aroundconstruct/Param.java
@@ -0,0 +1,8 @@
+package org.javaee7.interceptor.aroundconstruct;
+
+/**
+ * @author Radim Hanus
+ */
+public interface Param {
+ String getValue();
+}
diff --git a/interceptor/around-construct/src/test/java/org/javaee7/interceptor/aroundconstruct/GreetingBeanTest.java b/interceptor/around-construct/src/test/java/org/javaee7/interceptor/aroundconstruct/GreetingBeanTest.java
new file mode 100644
index 000000000..acb42e087
--- /dev/null
+++ b/interceptor/around-construct/src/test/java/org/javaee7/interceptor/aroundconstruct/GreetingBeanTest.java
@@ -0,0 +1,42 @@
+package org.javaee7.interceptor.aroundconstruct;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.inject.Inject;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Radim Hanus
+ */
+@RunWith(Arquillian.class)
+public class GreetingBeanTest {
+ @Inject
+ private Greeting bean;
+
+ @Deployment
+ public static Archive> deploy() {
+ return ShrinkWrap.create(JavaArchive.class)
+ .addClasses(Greeting.class, GreetingBean.class, GreetingParam.class, MyInterceptor.class, MyInterceptorBinding.class, Param.class)
+ .addAsManifestResource("beans.xml");
+ }
+
+ @Test
+ public void should_be_ready() throws Exception {
+ assertThat(bean, is(notNullValue()));
+ assertThat(bean, instanceOf(GreetingBean.class));
+ assertTrue(bean.isConstructed());
+ assertTrue(bean.isInitialized());
+ assertThat(bean.getParam(), instanceOf(GreetingParam.class));
+ }
+}
diff --git a/interceptor/around-construct/src/test/resources/beans.xml b/interceptor/around-construct/src/test/resources/beans.xml
new file mode 100644
index 000000000..04ea14faf
--- /dev/null
+++ b/interceptor/around-construct/src/test/resources/beans.xml
@@ -0,0 +1,11 @@
+
+
+
+
+ org.javaee7.interceptor.aroundconstruct.MyInterceptor
+
+
+
diff --git a/interceptor/pom.xml b/interceptor/pom.xml
new file mode 100644
index 000000000..d0767aa76
--- /dev/null
+++ b/interceptor/pom.xml
@@ -0,0 +1,27 @@
+
+ 4.0.0
+
+
+ org.javaee7
+ samples-parent
+ 1.0-SNAPSHOT
+
+
+ interceptor
+ pom
+
+ Java EE 7 Sample: interceptor
+
+
+ around-construct
+
+
+
+
+ org.javaee7
+ test-utils
+ ${project.version}
+ test
+
+
+
diff --git a/jacc/README.md b/jacc/README.md
new file mode 100644
index 000000000..53a9efaa5
--- /dev/null
+++ b/jacc/README.md
@@ -0,0 +1,13 @@
+# Java EE 7 Samples: JACC - Java Authorization Contract for Containers #
+
+The [JSR 115](https://jcp.org/en/jsr/detail?id=115) seeks to define a contract between containers and authorization service providers that will result in the implementation of providers for use by containers.
+
+## Samples ##
+
+ - contexts
+
+## How to run
+
+More information on how to run can be found at:
+
+
diff --git a/jacc/contexts/pom.xml b/jacc/contexts/pom.xml
new file mode 100644
index 000000000..e179ee0fa
--- /dev/null
+++ b/jacc/contexts/pom.xml
@@ -0,0 +1,22 @@
+
+
+ 4.0.0
+
+
+ org.javaee7
+ jacc
+ 1.0-SNAPSHOT
+ ../pom.xml
+
+ jacc-contexts
+ war
+ Java EE 7 Sample: jacc - contexts
+
+
+
+ org.javaee7
+ jaspic-common
+ 1.0-SNAPSHOT
+
+
+
diff --git a/jacc/contexts/src/main/java/org/javaee7/jacc/contexts/bean/JaccRequestBean.java b/jacc/contexts/src/main/java/org/javaee7/jacc/contexts/bean/JaccRequestBean.java
new file mode 100644
index 000000000..0d4a50497
--- /dev/null
+++ b/jacc/contexts/src/main/java/org/javaee7/jacc/contexts/bean/JaccRequestBean.java
@@ -0,0 +1,27 @@
+package org.javaee7.jacc.contexts.bean;
+
+import javax.ejb.Stateless;
+import javax.security.jacc.PolicyContext;
+import javax.security.jacc.PolicyContextException;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@Stateless
+public class JaccRequestBean {
+
+ public HttpServletRequest getRequest() throws PolicyContextException {
+ return (HttpServletRequest) PolicyContext.getContext("javax.servlet.http.HttpServletRequest");
+ }
+
+ public boolean hasAttribute() throws PolicyContextException {
+ return "true".equals(getRequest().getAttribute("jaccTest"));
+ }
+
+ public boolean hasParameter() throws PolicyContextException {
+ return "true".equals(getRequest().getParameter("jacc_test"));
+ }
+}
diff --git a/jacc/contexts/src/main/java/org/javaee7/jacc/contexts/sam/SamAutoRegistrationListener.java b/jacc/contexts/src/main/java/org/javaee7/jacc/contexts/sam/SamAutoRegistrationListener.java
new file mode 100644
index 000000000..e54f4c6ea
--- /dev/null
+++ b/jacc/contexts/src/main/java/org/javaee7/jacc/contexts/sam/SamAutoRegistrationListener.java
@@ -0,0 +1,22 @@
+package org.javaee7.jacc.contexts.sam;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.annotation.WebListener;
+
+import org.javaee7.jaspic.common.BaseServletContextListener;
+import org.javaee7.jaspic.common.JaspicUtils;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebListener
+public class SamAutoRegistrationListener extends BaseServletContextListener {
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ JaspicUtils.registerSAM(sce.getServletContext(), new TestServerAuthModule());
+ }
+
+}
\ No newline at end of file
diff --git a/jacc/contexts/src/main/java/org/javaee7/jacc/contexts/sam/TestServerAuthModule.java b/jacc/contexts/src/main/java/org/javaee7/jacc/contexts/sam/TestServerAuthModule.java
new file mode 100644
index 000000000..93793f0b2
--- /dev/null
+++ b/jacc/contexts/src/main/java/org/javaee7/jacc/contexts/sam/TestServerAuthModule.java
@@ -0,0 +1,95 @@
+package org.javaee7.jacc.contexts.sam;
+
+import static javax.security.auth.message.AuthStatus.SEND_SUCCESS;
+import static javax.security.auth.message.AuthStatus.SUCCESS;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.AuthStatus;
+import javax.security.auth.message.MessageInfo;
+import javax.security.auth.message.MessagePolicy;
+import javax.security.auth.message.callback.CallerPrincipalCallback;
+import javax.security.auth.message.callback.GroupPrincipalCallback;
+import javax.security.auth.message.module.ServerAuthModule;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Very basic SAM that returns a single hardcoded user named "test" with role "architect" when the request parameter
+ * doLogin is present.
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class TestServerAuthModule implements ServerAuthModule {
+
+ private CallbackHandler handler;
+ private Class>[] supportedMessageTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class };
+
+ @Override
+ public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler,
+ @SuppressWarnings("rawtypes") Map options) throws AuthException {
+ this.handler = handler;
+ }
+
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject)
+ throws AuthException {
+
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+
+ Callback[] callbacks;
+
+ if (request.getParameter("doLogin") != null) {
+
+ // For the test perform a login by directly "returning" the details of the authenticated user.
+ // Normally credentials would be checked and the details fetched from some repository
+
+ callbacks = new Callback[] {
+ // The name of the authenticated user
+ new CallerPrincipalCallback(clientSubject, "test"),
+ // the roles of the authenticated user
+ new GroupPrincipalCallback(clientSubject, new String[] { "architect" })
+ };
+ } else {
+
+ // The JASPIC protocol for "do nothing"
+ callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, (Principal) null) };
+ }
+
+ try {
+
+ // Communicate the details of the authenticated user to the container. In many
+ // cases the handler will just store the details and the container will actually handle
+ // the login after we return from this method.
+ handler.handle(callbacks);
+
+ } catch (IOException | UnsupportedCallbackException e) {
+ throw (AuthException) new AuthException().initCause(e);
+ }
+
+ return SUCCESS;
+ }
+
+ @Override
+ public Class>[] getSupportedMessageTypes() {
+ return supportedMessageTypes;
+ }
+
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+ return SEND_SUCCESS;
+ }
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+
+ }
+}
\ No newline at end of file
diff --git a/jacc/contexts/src/main/java/org/javaee7/jacc/contexts/servlet/RequestServlet.java b/jacc/contexts/src/main/java/org/javaee7/jacc/contexts/servlet/RequestServlet.java
new file mode 100644
index 000000000..5007ead25
--- /dev/null
+++ b/jacc/contexts/src/main/java/org/javaee7/jacc/contexts/servlet/RequestServlet.java
@@ -0,0 +1,49 @@
+package org.javaee7.jacc.contexts.servlet;
+
+import java.io.IOException;
+
+import javax.security.jacc.PolicyContext;
+import javax.security.jacc.PolicyContextException;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/requestServlet")
+public class RequestServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ request.setAttribute("jaccTest", "true");
+
+ try {
+ HttpServletRequest requestFromPolicy = (HttpServletRequest) PolicyContext.getContext("javax.servlet.http.HttpServletRequest");
+
+ if (requestFromPolicy != null) {
+ response.getWriter().print("Obtained request from context.");
+
+ if ("true".equals(requestFromPolicy.getAttribute("jaccTest"))) {
+ response.getWriter().print("Attribute present in request from context.");
+ }
+
+ if ("true".equals(requestFromPolicy.getParameter("jacc_test"))) {
+ response.getWriter().print("Request parameter present in request from context.");
+ }
+
+ }
+ } catch (PolicyContextException e) {
+ e.printStackTrace(response.getWriter());
+ }
+
+ }
+
+}
diff --git a/jacc/contexts/src/main/java/org/javaee7/jacc/contexts/servlet/RequestServletEJB.java b/jacc/contexts/src/main/java/org/javaee7/jacc/contexts/servlet/RequestServletEJB.java
new file mode 100644
index 000000000..43b9f705e
--- /dev/null
+++ b/jacc/contexts/src/main/java/org/javaee7/jacc/contexts/servlet/RequestServletEJB.java
@@ -0,0 +1,52 @@
+package org.javaee7.jacc.contexts.servlet;
+
+import java.io.IOException;
+
+import javax.inject.Inject;
+import javax.security.jacc.PolicyContextException;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.javaee7.jacc.contexts.bean.JaccRequestBean;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/requestServletEJB")
+public class RequestServletEJB extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Inject
+ private JaccRequestBean jaccRequestBean;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ request.setAttribute("jaccTest", "true");
+
+ try {
+ if (jaccRequestBean.getRequest() != null) {
+ response.getWriter().print("Obtained request from context.");
+
+ if (jaccRequestBean.hasAttribute()) {
+ response.getWriter().print("Attribute present in request from context.");
+ }
+
+ if (jaccRequestBean.hasParameter()) {
+ response.getWriter().print("Request parameter present in request from context.");
+ }
+
+ }
+ } catch (PolicyContextException e) {
+ e.printStackTrace(response.getWriter());
+ }
+
+ }
+
+}
diff --git a/jacc/contexts/src/main/java/org/javaee7/jacc/contexts/servlet/SubjectServlet.java b/jacc/contexts/src/main/java/org/javaee7/jacc/contexts/servlet/SubjectServlet.java
new file mode 100644
index 000000000..3a579f72f
--- /dev/null
+++ b/jacc/contexts/src/main/java/org/javaee7/jacc/contexts/servlet/SubjectServlet.java
@@ -0,0 +1,95 @@
+package org.javaee7.jacc.contexts.servlet;
+
+import static java.security.Policy.getPolicy;
+import static java.util.Collections.list;
+
+import java.io.IOException;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Principal;
+import java.security.ProtectionDomain;
+import java.security.cert.Certificate;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.security.jacc.PolicyContext;
+import javax.security.jacc.PolicyContextException;
+import javax.security.jacc.WebRoleRefPermission;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * This Servlet demonstrates both how to obtain the Subject and then how to retrieve the roles from
+ * this Subject.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/subjectServlet")
+public class SubjectServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ try {
+ Subject subject = (Subject) PolicyContext.getContext("javax.security.auth.Subject.container");
+
+ if (subject != null) {
+ response.getWriter().print("Obtained subject from context.\n");
+
+ // Get the permissions associated with the Subject we obtained
+ PermissionCollection permissionCollection = getPermissionCollection(subject);
+
+ // Resolve any potentially unresolved permissions
+ permissionCollection.implies(new WebRoleRefPermission("", "nothing"));
+
+ // Filter just the roles from all the permissions, which may include things like
+ // java.net.SocketPermission, java.io.FilePermission, and obtain the actual role names.
+ Set roles = filterRoles(request, permissionCollection);
+
+ for (String role : roles) {
+ response.getWriter().print("User has role " + role + "\n");
+ }
+ }
+ } catch (PolicyContextException e) {
+ e.printStackTrace(response.getWriter());
+ }
+ }
+
+ private PermissionCollection getPermissionCollection(Subject subject) {
+ return getPolicy().getPermissions(
+ new ProtectionDomain(
+ new CodeSource(null, (Certificate[]) null),
+ null, null,
+ subject.getPrincipals().toArray(new Principal[subject.getPrincipals().size()])
+ )
+ );
+ }
+
+ private Set filterRoles(HttpServletRequest request, PermissionCollection permissionCollection) {
+ Set roles = new HashSet<>();
+ for (Permission permission : list(permissionCollection.elements())) {
+ if (permission instanceof WebRoleRefPermission) {
+ String role = permission.getActions();
+
+ // Note that the WebRoleRefPermission is given for every Servlet in the application, even when
+ // no role refs are used anywhere. This will also include Servlets like the default servlet and the
+ // implicit JSP servlet. So if there are 2 application roles, and 3 application servlets, then
+ // at least 6 WebRoleRefPermission elements will be present in the collection.
+ if (!roles.contains(role) && request.isUserInRole(role)) {
+ roles.add(role);
+ }
+ }
+ }
+
+ return roles;
+ }
+
+}
diff --git a/jacc/contexts/src/main/webapp/WEB-INF/glassfish-web.xml b/jacc/contexts/src/main/webapp/WEB-INF/glassfish-web.xml
new file mode 100644
index 000000000..26559e3f6
--- /dev/null
+++ b/jacc/contexts/src/main/webapp/WEB-INF/glassfish-web.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ architect
+ architect
+
+
+
+
+
\ No newline at end of file
diff --git a/jacc/contexts/src/main/webapp/WEB-INF/jboss-web.xml b/jacc/contexts/src/main/webapp/WEB-INF/jboss-web.xml
new file mode 100644
index 000000000..b6ab7d0ba
--- /dev/null
+++ b/jacc/contexts/src/main/webapp/WEB-INF/jboss-web.xml
@@ -0,0 +1,5 @@
+
+
+
+ jaspitest
+
diff --git a/jacc/contexts/src/main/webapp/WEB-INF/web.xml b/jacc/contexts/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..ffd58ffa6
--- /dev/null
+++ b/jacc/contexts/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Test
+ /protected/*
+
+
+ architect
+
+
+
+
+ architect
+
+
+
\ No newline at end of file
diff --git a/jacc/contexts/src/test/java/org/javaee7/jacc/contexts/RequestFromPolicyContextTest.java b/jacc/contexts/src/test/java/org/javaee7/jacc/contexts/RequestFromPolicyContextTest.java
new file mode 100644
index 000000000..8e20af4f6
--- /dev/null
+++ b/jacc/contexts/src/test/java/org/javaee7/jacc/contexts/RequestFromPolicyContextTest.java
@@ -0,0 +1,114 @@
+package org.javaee7.jacc.contexts;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.javaee7.jacc.contexts.bean.JaccRequestBean;
+import org.javaee7.jacc.contexts.sam.SamAutoRegistrationListener;
+import org.javaee7.jacc.contexts.sam.TestServerAuthModule;
+import org.javaee7.jacc.contexts.servlet.RequestServlet;
+import org.javaee7.jacc.contexts.servlet.RequestServletEJB;
+import org.javaee7.jacc.contexts.servlet.SubjectServlet;
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * This tests demonstrates how code can obtain a reference to the {@link HttpServletRequest} from the JACC
+ * context.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class RequestFromPolicyContextTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ WebArchive archive = ((WebArchive) ArquillianBase.defaultArchive())
+ .addClasses(
+ SamAutoRegistrationListener.class, TestServerAuthModule.class,
+ RequestServlet.class, SubjectServlet.class);
+
+ if (!Boolean.valueOf(System.getProperty("skipEJB"))) {
+ archive.addClasses(JaccRequestBean.class, RequestServletEJB.class);
+ } else {
+ System.out.println("Skipping EJB based tests");
+ }
+
+ return archive;
+ }
+
+ /**
+ * Tests that we are able to obtain a reference to the {@link HttpServletRequest} from a Servlet.
+ */
+ @Test
+ public void testCanObtainRequestInServlet() throws IOException, SAXException {
+
+ String response = getFromServerPath("requestServlet");
+
+ assertTrue(response.contains("Obtained request from context."));
+ }
+
+
+ /**
+ * Tests that the {@link HttpServletRequest} reference that we obtained from JACC in a Servlet actually
+ * works by getting a request attribute and request parameter from it.
+ */
+ @Test
+ public void testDataInServlet() throws IOException, SAXException {
+
+ String response = getFromServerPath("requestServlet?jacc_test=true");
+
+ assertTrue(
+ "Request scope attribute not present in request obtained from context in Servlet, but should have been",
+ response.contains("Attribute present in request from context."));
+
+ assertTrue(
+ "Request parameter not present in request obtained from context in Servlet, but should have been",
+ response.contains("Request parameter present in request from context."));
+ }
+
+ /**
+ * Tests that the {@link HttpServletRequest} reference that we obtained from JACC in an EJB actually
+ * works by getting a request attribute and request parameter from it.
+ */
+ @Test
+ public void testDataInEJB() throws IOException, SAXException {
+
+ Assume.assumeTrue(false);
+
+ String response = getFromServerPath("requestServlet?jacc_test=true");
+
+ assertTrue(
+ "Request scope attribute not present in request obtained from context in EJB, but should have been",
+ response.contains("Attribute present in request from context."));
+
+ assertTrue(
+ "Request parameter not present in request obtained from context in EJB, but should have been",
+ response.contains("Request parameter present in request from context."));
+ }
+
+ /**
+ * Tests that we are able to obtain a reference to the {@link HttpServletRequest} from an EJB.
+ */
+ @Test
+ public void testCanObtainRequestInEJB() throws IOException, SAXException {
+
+ Assume.assumeTrue(false);
+
+ String response = getFromServerPath("requestServletEJB");
+
+ assertTrue(response.contains("Obtained request from context."));
+ }
+
+}
\ No newline at end of file
diff --git a/jacc/contexts/src/test/java/org/javaee7/jacc/contexts/SubjectFromPolicyContextTest.java b/jacc/contexts/src/test/java/org/javaee7/jacc/contexts/SubjectFromPolicyContextTest.java
new file mode 100644
index 000000000..3e155f0f8
--- /dev/null
+++ b/jacc/contexts/src/test/java/org/javaee7/jacc/contexts/SubjectFromPolicyContextTest.java
@@ -0,0 +1,88 @@
+package org.javaee7.jacc.contexts;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import javax.security.auth.Subject;
+import javax.servlet.http.HttpServletRequest;
+
+import org.javaee7.jacc.contexts.sam.SamAutoRegistrationListener;
+import org.javaee7.jacc.contexts.sam.TestServerAuthModule;
+import org.javaee7.jacc.contexts.servlet.RequestServlet;
+import org.javaee7.jacc.contexts.servlet.SubjectServlet;
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * This test demonstrates both how to obtain the {@link Subject} and then how to indirectly retrieve the roles from
+ * this Subject.
+ *
+ * This will be done by calling a Servlet that retrieves the {@link Subject} of the authenticated user.
+ * Authentication happens via the {@link TestServerAuthModule} when the "doLogin" parameter is present in
+ * the request.
+ *
+ * The Subject (a "bag of principals") typically contains the user name principal that can also be obtained via
+ * {@link HttpServletRequest#getUserPrincipal()} and may contain the roles this user has. But, it has never
+ * been standardized in Java EE which principal (attribute) of the Subject represents the user name and
+ * which ones represent the roles, so every container does it differently. On top of that JACC did not specify
+ * that *the* Subject should be returned and implementations not rarely return a Subject that contains only the
+ * user name principal instead of the real Subject with all principals.
+ *
+ * Via a somewhat obscure workaround via JACC it's possible to fetch the roles from the Subject
+ * in a standard way.
+ * See Using JACC to determine a caller's roles
+ *
+ *
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class SubjectFromPolicyContextTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ WebArchive archive = ((WebArchive) ArquillianBase.defaultArchive())
+ .addClasses(
+ SamAutoRegistrationListener.class, TestServerAuthModule.class,
+ RequestServlet.class, SubjectServlet.class);
+
+ return archive;
+ }
+
+ /**
+ * Tests that we are able to obtain a reference to the {@link Subject} from a Servlet.
+ */
+ @Test
+ public void testCanObtainRequestInServlet() throws IOException, SAXException {
+
+ String response = getFromServerPath("subjectServlet?doLogin=true");
+
+ assertTrue(response.contains("Obtained subject from context."));
+ }
+
+ /**
+ * Tests that we are able to obtain a reference to the {@link Subject} from a Servlet and
+ * use JACC to get the roles the user from its principals.
+ */
+ @Test
+ public void testCanObtainRolesFromSubjectInServlet() throws IOException, SAXException {
+
+ String response = getFromServerPath("subjectServlet?doLogin=true");
+
+ // The role that was assigned to the user in TestServerAuthModule
+ assertTrue(response.contains("User has role architect"));
+
+ // Servlet 13.3; Every authenticated user should have this role and isUserInRole should return true
+ // when tested.
+ assertTrue(response.contains("User has role **"));
+ }
+
+}
\ No newline at end of file
diff --git a/jacc/permissions-xml/pom.xml b/jacc/permissions-xml/pom.xml
new file mode 100644
index 000000000..a63d329d9
--- /dev/null
+++ b/jacc/permissions-xml/pom.xml
@@ -0,0 +1,161 @@
+
+ 4.0.0
+
+
+ org.javaee7
+ jacc
+ 1.0-SNAPSHOT
+
+
+ jacc-permissions-xml
+ war
+ Java EE 7 Sample: jacc - permissions.xml
+
+
+
+ org.glassfish.grizzly
+ grizzly-framework
+ 2.4.3.payara-p5
+ provided
+
+
+
+ org.glassfish.grizzly
+ grizzly-http
+ 2.4.3.payara-p5
+ provided
+
+
+ org.glassfish.grizzly
+ grizzly-http-server
+ 2.4.3.payara-p5
+ provided
+
+
+ org.glassfish.grizzly
+ grizzly-http-servlet
+ 2.4.3.payara-p5
+ provided
+
+
+ org.glassfish.grizzly
+ grizzly-portunif
+ 2.4.3.payara-p5
+ provided
+
+
+ org.glassfish.grizzly
+ grizzly-http-ajp
+ 2.4.3.payara-p5
+ provided
+
+
+ org.glassfish.grizzly
+ grizzly-websockets
+ 2.4.3.payara-p5
+ provided
+
+
+ org.glassfish.grizzly
+ grizzly-http2
+ 2.4.3.payara-p5
+ provided
+
+
+ org.glassfish.grizzly
+ grizzly-comet
+ 2.4.3.payara-p5
+ provided
+
+
+ org.glassfish.grizzly
+ grizzly-http-server-multipart
+ 2.4.3.payara-p5
+ provided
+
+
+ org.glassfish.grizzly
+ grizzly-http-server-jaxws
+ 2.4.3.payara-p5
+ provided
+
+
+ org.glassfish.grizzly
+ grizzly-http-servlet-extras
+ 2.4.3.payara-p5
+ provided
+
+
+ org.glassfish.grizzly
+ tls-sni
+ 2.4.3.payara-p5 provided
+
+
+ org.glassfish.grizzly.osgi
+ grizzly-httpservice
+ 2.4.3.payara-p5
+ provided
+
+
+ org.glassfish.grizzly
+ grizzly-framework-monitoring
+ 2.4.3.payara-p5
+ provided
+
+
+ org.glassfish.grizzly
+ grizzly-http-monitoring
+ 2.4.3.payara-p5
+ provided
+
+
+ org.glassfish.grizzly
+ grizzly-http-server-monitoring
+ 2.4.3.payara-p5
+ provided
+
+
+ org.glassfish.grizzly
+ grizzly-core
+ provided
+ 2.4.3.payara-p5
+
+
+ org.glassfish.grizzly
+ grizzly-http-server-core
+ 2.4.3.payara-p5
+ provided
+
+
+ org.glassfish.grizzly
+ grizzly-http-all
+ 2.4.3.payara-p5
+ provided
+
+
+ org.glassfish.grizzly
+ grizzly-http-servlet-server
+ 2.4.3.payara-p5
+ provided
+
+
+ org.glassfish.grizzly
+ grizzly-websockets-server
+ 2.4.3.payara-p5
+ provided
+
+
+ org.glassfish.grizzly
+ grizzly-comet-server
+ 2.4.3.payara-p5
+ provided
+
+
+ org.glassfish.grizzly.osgi
+ grizzly-httpservice-bundle
+ 2.4.3.payara-p5
+ provided
+
+
+
+
diff --git a/jacc/permissions-xml/src/main/java/org/javaee7/jacc/contexts/bean/BeanLeaf.java b/jacc/permissions-xml/src/main/java/org/javaee7/jacc/contexts/bean/BeanLeaf.java
new file mode 100644
index 000000000..8478a0992
--- /dev/null
+++ b/jacc/permissions-xml/src/main/java/org/javaee7/jacc/contexts/bean/BeanLeaf.java
@@ -0,0 +1,71 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can
+ * obtain a copy of the License at
+ * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+// Portions Copyright [2018] [Payara Foundation and/or its affiliates]
+package org.javaee7.jacc.contexts.bean;
+
+import javax.annotation.PostConstruct;
+import javax.ejb.EJB;
+import javax.ejb.Singleton;
+
+@Singleton
+public class BeanLeaf {
+
+ private static final String MESSAGE_POST = "PostBeanLeaf";
+ private static final String MESSAGE_HELLO = "HelloBeanLeaf";
+
+ @EJB
+ private BeanMessageInterface msg;
+
+ @PostConstruct
+ public void afterConstruct() {
+ if (msg != null && !msg.getMessage().contains(MESSAGE_POST)) {
+ msg.appendMessage(MESSAGE_POST);
+ }
+ }
+
+ public String sayHello() {
+ if (msg != null && !msg.getMessage().contains(MESSAGE_HELLO)) {
+ msg.appendMessage(MESSAGE_HELLO);
+ }
+
+ return "Hello from: " + this.getClass().getName() + "; " + System.identityHashCode(this);
+ }
+
+}
diff --git a/jacc/permissions-xml/src/main/java/org/javaee7/jacc/contexts/bean/BeanMessage.java b/jacc/permissions-xml/src/main/java/org/javaee7/jacc/contexts/bean/BeanMessage.java
new file mode 100644
index 000000000..6bbfaf8b5
--- /dev/null
+++ b/jacc/permissions-xml/src/main/java/org/javaee7/jacc/contexts/bean/BeanMessage.java
@@ -0,0 +1,72 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can
+ * obtain a copy of the License at
+ * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+// Portions Copyright [2018] [Payara Foundation and/or its affiliates]
+package org.javaee7.jacc.contexts.bean;
+
+import javax.ejb.Singleton;
+
+@Singleton
+public class BeanMessage implements BeanMessageInterface {
+
+ private String message = "";
+
+ @Override
+ public String getMessage() {
+ return message;
+ }
+
+ @Override
+ public void setMessage(String message) {
+ this.message = message;
+ System.out.println("BeanMessage: setMessage=" + this.message);
+ }
+
+ @Override
+ public void appendMessage(String message) {
+ this.message += message;
+ System.out.println("BeanMessage: appendMessage=" + this.message);
+ }
+
+ @Override
+ public String sayHello() {
+ return "Hello from: " + this.getClass().getName() + "; " + System.identityHashCode(this);
+ }
+
+}
diff --git a/jacc/permissions-xml/src/main/java/org/javaee7/jacc/contexts/bean/BeanMessageInterface.java b/jacc/permissions-xml/src/main/java/org/javaee7/jacc/contexts/bean/BeanMessageInterface.java
new file mode 100644
index 000000000..0a99b92dd
--- /dev/null
+++ b/jacc/permissions-xml/src/main/java/org/javaee7/jacc/contexts/bean/BeanMessageInterface.java
@@ -0,0 +1,53 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can
+ * obtain a copy of the License at
+ * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+// Portions Copyright [2018] [Payara Foundation and/or its affiliates]
+package org.javaee7.jacc.contexts.bean;
+
+public interface BeanMessageInterface {
+
+ String getMessage();
+
+ void setMessage(String message);
+
+ void appendMessage(String message);
+
+ String sayHello();
+
+}
diff --git a/jacc/permissions-xml/src/main/java/org/javaee7/jacc/contexts/bean/BeanRoot.java b/jacc/permissions-xml/src/main/java/org/javaee7/jacc/contexts/bean/BeanRoot.java
new file mode 100644
index 000000000..e75ac0fe1
--- /dev/null
+++ b/jacc/permissions-xml/src/main/java/org/javaee7/jacc/contexts/bean/BeanRoot.java
@@ -0,0 +1,122 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can
+ * obtain a copy of the License at
+ * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+// Portions Copyright [2018] [Payara Foundation and/or its affiliates]
+package org.javaee7.jacc.contexts.bean;
+
+import java.io.FilePermission;
+import java.security.AccessControlException;
+import java.security.AccessController;
+
+import javax.annotation.PostConstruct;
+import javax.ejb.EJB;
+import javax.ejb.Singleton;
+import javax.ejb.Startup;
+
+@Singleton
+@Startup
+public class BeanRoot implements BeanRootInterface {
+
+ @EJB
+ private BeanLeaf bl;
+
+ @EJB
+ private BeanMessageInterface msg;
+
+ String MESSAGE_POST = "PostBeanRoot";
+ String MESSAGE_HELLO = "HelloBeanRoot";
+
+ @Override
+ @PostConstruct
+ public void afterConstruct() {
+ if (msg != null && !msg.getMessage().contains(MESSAGE_POST)) {
+ msg.appendMessage(MESSAGE_POST);
+ }
+ String h = bl.sayHello();
+ System.out.println("** BeanRoot: Hello from beanLeaf: " + h);
+ }
+
+ @Override
+ public String sayHello() {
+ if (msg != null && !msg.getMessage().contains(MESSAGE_HELLO)) {
+ msg.appendMessage(MESSAGE_HELLO);
+ }
+
+ StringBuffer check = new StringBuffer(" -EJB test-");
+
+ FilePermission fp = new FilePermission("/scratch/spei/bug/test/war.txt", "delete");
+ try {
+ if (System.getSecurityManager() != null) {
+ AccessController.checkPermission(fp);
+ check.append("BeanRoot - success for WAR.txt; ");
+ } else
+ check.append("BeanRoot - bypass for WAR.txt; ");
+ } catch (AccessControlException e) {
+ check.append("BeanRoot - failed for WAR.txt; ");
+ }
+
+ fp = new FilePermission("/scratch/spei/bug/test/ear.txt", "delete");
+ try {
+ if (System.getSecurityManager() != null) {
+ AccessController.checkPermission(fp);
+ check.append("BeanRoot - success for EAR.txt; ");
+ } else
+ check.append("BeanRoot - bypass for EAR.txt; ");
+ } catch (AccessControlException e) {
+ check.append("BeanRoot - failed for EAR.txt; ");
+ }
+
+ fp = new FilePermission("/scratch/spei/bug/test/ejb.txt", "delete");
+ final FilePermission p1 = fp;
+ try {
+ if (System.getSecurityManager() != null) {
+ AccessController.checkPermission(p1);
+ check.append("BeanRoot - success for EJB.txt; ");
+ } else
+ check.append("BeanRoot - bypass for EJB.txt; ");
+ } catch (AccessControlException e) {
+ check.append("BeanRoot - failed for EJB.txt; " + e.getMessage());
+ }
+
+ return "Hello from: " + this.getClass().getName() + "; "
+ + check.toString() + " , code= "
+ + System.identityHashCode(this);
+ }
+
+}
diff --git a/jacc/permissions-xml/src/main/java/org/javaee7/jacc/contexts/bean/BeanRootInterface.java b/jacc/permissions-xml/src/main/java/org/javaee7/jacc/contexts/bean/BeanRootInterface.java
new file mode 100644
index 000000000..f1dec1ae1
--- /dev/null
+++ b/jacc/permissions-xml/src/main/java/org/javaee7/jacc/contexts/bean/BeanRootInterface.java
@@ -0,0 +1,49 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can
+ * obtain a copy of the License at
+ * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+// Portions Copyright [2018] [Payara Foundation and/or its affiliates]
+package org.javaee7.jacc.contexts.bean;
+
+public interface BeanRootInterface {
+
+ void afterConstruct();
+
+ String sayHello();
+
+}
diff --git a/jacc/permissions-xml/src/main/java/org/javaee7/jacc/contexts/servlet/TestServlet.java b/jacc/permissions-xml/src/main/java/org/javaee7/jacc/contexts/servlet/TestServlet.java
new file mode 100644
index 000000000..379321d8d
--- /dev/null
+++ b/jacc/permissions-xml/src/main/java/org/javaee7/jacc/contexts/servlet/TestServlet.java
@@ -0,0 +1,203 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common Development
+ * and Distribution License("CDDL") (collectively, the "License"). You
+ * may not use this file except in compliance with the License. You can
+ * obtain a copy of the License at
+ * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
+ * or packager/legal/LICENSE.txt. See the License for the specific
+ * language governing permissions and limitations under the License.
+ *
+ * When distributing the software, include this License Header Notice in each
+ * file and include the License file at packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [year] [name of copyright owner]"
+ *
+ * Contributor(s):
+ * If you wish your version of this file to be governed by only the CDDL or
+ * only the GPL Version 2, indicate your decision by adding "[Contributor]
+ * elects to include this software in this distribution under the [CDDL or GPL
+ * Version 2] license." If you don't indicate a single choice of license, a
+ * recipient has the option to distribute your version of this file under
+ * either the CDDL, the GPL Version 2 or to extend the choice of license to
+ * its licensees as provided above. However, if you add GPL Version 2 code
+ * and therefore, elected the GPL Version 2 license, then the option applies
+ * only if the new code is made subject to such option by the copyright
+ * holder.
+ */
+// Portions Copyright [2018] [Payara Foundation and/or its affiliates]
+package org.javaee7.jacc.contexts.servlet;
+
+import java.io.FilePermission;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.security.AccessControlException;
+import java.security.AccessController;
+
+import javax.ejb.EJB;
+import javax.naming.InitialContext;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.javaee7.jacc.contexts.bean.BeanMessageInterface;
+import org.javaee7.jacc.contexts.bean.BeanRootInterface;
+
+public class TestServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @EJB
+ private BeanRootInterface root;
+
+ @EJB
+ private BeanMessageInterface msg;
+
+ private String message;
+
+ @Override
+ public void init(ServletConfig config) throws ServletException {
+ super.init(config);
+ message = msg.getMessage();
+ System.out.println("servlet init: message=" + message);
+ }
+
+ protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.setContentType("text/plain");
+ PrintWriter out = response.getWriter();
+ String EXPECTED_RESULT = "PostBeanRootPostBeanLeafHelloBeanLeaf";
+ boolean status = false;
+
+ try {
+
+ String testcase = request.getParameter("tc");
+ out.println("testcase = " + testcase);
+ out.println("TestServlet");
+ out.println("contextPath=" + request.getContextPath());
+
+ if (testcase != null) {
+
+ if ("InjectLookup".equals(testcase)) {
+ // EJB injection check
+ // out.println("injected root: " + root);
+ String hello = root.sayHello();
+ out.println("Hello from injected bean: " + hello);
+
+ // EJB lookup check
+ InitialContext initialContext = new InitialContext();
+
+
+ String EJBlookupName = null;
+ if (request.getParameter("web") == null) {
+
+ // For war inside ears:
+
+ // "java"glabal[/]//"
+ // app-name -- name of ear file (option)
+ // module-name -- name of war or jar file
+ // bean-name -- name of ejb
+
+ EJBlookupName = "java:global/appperms/apppermsEJB/BeanRoot";
+ } else {
+ // For standalone war:
+ EJBlookupName = "java:module/BeanRoot";
+ }
+
+ BeanRootInterface root2 = (BeanRootInterface) initialContext.lookup(EJBlookupName);
+
+ // out.println("global root: " + root2);
+ String hello2 = root2.sayHello();
+ out.println("Hello from lookup bean: " + hello2);
+
+ StringBuffer checkReport = new StringBuffer(" -Servlet test- ");
+ FilePermission filePermission = new FilePermission("/scratch/spei/bug/test/war.txt", "delete");
+ try {
+ if (System.getSecurityManager() != null) {
+ AccessController.checkPermission(filePermission);
+ checkReport.append("servlet - success for WAR.txt; ");
+ } else
+ checkReport.append("servlet - bypass for WAR.txt; ");
+
+ } catch (AccessControlException e) {
+ checkReport.append("servlet - failed for WAR.txt; ");
+ }
+
+ filePermission = new FilePermission("/scratch/spei/bug/test/ear.txt", "delete");
+ try {
+ if (System.getSecurityManager() != null) {
+ AccessController.checkPermission(filePermission);
+ checkReport.append("servlet - success for EAR.txt; ");
+ } else
+ checkReport.append("servlet - bypass for EAR.txt; ");
+ } catch (AccessControlException e) {
+ checkReport.append("servlet - failed for EAR.txt; ");
+ }
+
+ filePermission = new FilePermission("/scratch/spei/bug/test/ejb.txt", "delete");
+ try {
+ if (System.getSecurityManager() != null) {
+ AccessController.checkPermission(filePermission);
+ checkReport.append("servlet - success for EJB.txt; ");
+ } else
+ checkReport.append("servlet - bypass for EJB.txt; ");
+ } catch (AccessControlException e) {
+ checkReport.append("servlet - failed for EJB.txt; ");
+ }
+
+ String checkReportString = checkReport.toString();
+ out.println("test: " + checkReportString);
+
+ if (hello.equals(hello2) && !checkReportString.contains("failed") && !hello.contains("failed")) {
+ status = true;
+ }
+ } else if ("Startup".equals(testcase)) {
+ // Deployment check for startup
+ out.println("message by deployment: " + message);
+ if (message != null && message.equals(EXPECTED_RESULT)) {
+ status = true;
+ }
+ }
+ }
+
+ } catch (Throwable th) {
+ th.printStackTrace(out);
+ } finally {
+ if (status) {
+ out.println("Test:Pass");
+ } else {
+ out.println("Test:Fail");
+ }
+ out.close();
+ }
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ processRequest(request, response);
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ processRequest(request, response);
+ }
+
+ @Override
+ public String getServletInfo() {
+ return "Short description";
+ }
+
+}
diff --git a/jacc/permissions-xml/src/main/resources/META-INF/application.xml b/jacc/permissions-xml/src/main/resources/META-INF/application.xml
new file mode 100644
index 000000000..8557113cc
--- /dev/null
+++ b/jacc/permissions-xml/src/main/resources/META-INF/application.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+ app-perms
+
+
+ apppermsEJB.jar
+
+
+
+
+ apppermsWeb.war
+ appperms
+
+
+
+
diff --git a/jacc/permissions-xml/src/main/resources/META-INF/permissions.xml b/jacc/permissions-xml/src/main/resources/META-INF/permissions.xml
new file mode 100644
index 000000000..f32a0f756
--- /dev/null
+++ b/jacc/permissions-xml/src/main/resources/META-INF/permissions.xml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+ java.io.FilePermission
+ /scratch/spei/bug/test/ear.txt
+ read,write,delete
+
+
+
+ java.io.FilePermission
+ /scratch/spei/bug/test/war.txt
+ read,write,delete
+
+
+
+ java.io.FilePermission
+ /scratch/spei/bug/test/ejb.txt
+ read,write,delete
+
+
+
+ java.lang.RuntimePermission
+ createClassLoader
+
+
+
\ No newline at end of file
diff --git a/jacc/permissions-xml/src/main/webapp/WEB-INF/web.xml b/jacc/permissions-xml/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..e49a81f4e
--- /dev/null
+++ b/jacc/permissions-xml/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+ TestServlet
+ org.javaee7.jacc.contexts.servlet.TestServlet
+
+
+ TestServlet
+ /test/*
+
+
diff --git a/jacc/permissions-xml/src/test/java/org/javaee7/jacc/permissionsxml/PermissionsXMLEarTest.java b/jacc/permissions-xml/src/test/java/org/javaee7/jacc/permissionsxml/PermissionsXMLEarTest.java
new file mode 100644
index 000000000..831de61bf
--- /dev/null
+++ b/jacc/permissions-xml/src/test/java/org/javaee7/jacc/permissionsxml/PermissionsXMLEarTest.java
@@ -0,0 +1,120 @@
+/** Copyright Payara Services Limited **/
+package org.javaee7.jacc.permissionsxml;
+
+import static javax.ws.rs.client.ClientBuilder.newClient;
+import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
+import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
+import static org.junit.Assert.assertTrue;
+import static org.junit.runners.MethodSorters.NAME_ASCENDING;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import javax.ws.rs.core.Response;
+
+import org.javaee7.jacc.contexts.bean.BeanRoot;
+import org.javaee7.jacc.contexts.servlet.TestServlet;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.container.test.api.RunAsClient;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.spec.EnterpriseArchive;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * This tests demonstrates the usage of a permissions.xml file inside
+ * an ear which contains both a web module and an EJB module.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+@FixMethodOrder(NAME_ASCENDING)
+public class PermissionsXMLEarTest {
+
+ private static final String WEBAPP_SRC = "src/main/webapp";
+
+ @ArquillianResource
+ private URL base;
+
+ @Deployment
+ public static Archive> deploy() {
+ if (System.getProperty("skipEAR") != null) {
+ return create(WebArchive.class);
+ }
+
+ return
+ // EAR module
+ create(EnterpriseArchive.class, "appperms.ear")
+
+ // Add permissions.xml, which is the main file we're testing
+ .addAsResource("META-INF/permissions.xml")
+ .setApplicationXML("META-INF/application.xml")
+
+ // EJB module
+ .addAsModule(
+ create(JavaArchive.class, "apppermsEJB.jar")
+
+ // Java classes containing the actual permission tests
+ // They are in the EJB module so we test the permissions work there
+ .addPackage(BeanRoot.class.getPackage())
+ )
+
+ // Web module
+ .addAsModule(
+ create(WebArchive.class, "apppermsWeb.war")
+ .addAsWebInfResource((new File(WEBAPP_SRC + "/WEB-INF", "web.xml")))
+
+ // This class kicks off the EJB tests, but also contains tests of its own.
+ // These own tests are there to test if the permissions also work in a web module
+ .addClass(TestServlet.class)
+ );
+ }
+
+
+ @Test
+ @RunAsClient
+ public void test1Startup() throws IOException, URISyntaxException {
+ if (System.getProperty("skipEAR") != null) {
+ return;
+ }
+
+ System.out.println("Testing Servlet from war from ear deployed at " + new URL(base, "test").toExternalForm());
+
+ Response response =
+ newClient()
+ .target(new URL(base, "test").toURI())
+ .queryParam("tc", "Startup")
+ .request(TEXT_PLAIN)
+ .get();
+
+ assertTrue(response.readEntity(String.class).contains("Test:Pass"));
+ }
+
+ @Test
+ @RunAsClient
+ public void test2PermissionsXML() throws IOException, URISyntaxException {
+ if (System.getProperty("skipEAR") != null) {
+ return;
+ }
+
+ System.out.println("Running actual permissions.xml test");
+
+ Response response =
+ newClient()
+ .target(new URL(base, "test").toURI())
+ .queryParam("tc", "InjectLookup")
+ .request(TEXT_PLAIN)
+ .get();
+
+ assertTrue(response.readEntity(String.class).contains("Test:Pass"));
+ }
+
+}
\ No newline at end of file
diff --git a/jacc/permissions-xml/src/test/java/org/javaee7/jacc/permissionsxml/PermissionsXMLServletTest.java b/jacc/permissions-xml/src/test/java/org/javaee7/jacc/permissionsxml/PermissionsXMLServletTest.java
new file mode 100644
index 000000000..22bd960d2
--- /dev/null
+++ b/jacc/permissions-xml/src/test/java/org/javaee7/jacc/permissionsxml/PermissionsXMLServletTest.java
@@ -0,0 +1,93 @@
+/** Copyright Payara Services Limited **/
+package org.javaee7.jacc.permissionsxml;
+
+import static javax.ws.rs.client.ClientBuilder.newClient;
+import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
+import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
+import static org.junit.Assert.assertTrue;
+import static org.junit.runners.MethodSorters.NAME_ASCENDING;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import javax.ws.rs.core.Response;
+
+import org.javaee7.jacc.contexts.bean.BeanRoot;
+import org.javaee7.jacc.contexts.servlet.TestServlet;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.container.test.api.RunAsClient;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * This tests demonstrates the usage of a permissions.xml file inside
+ * a standalone war
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+@FixMethodOrder(NAME_ASCENDING)
+public class PermissionsXMLServletTest {
+
+ private static final String WEBAPP_SRC = "src/main/webapp";
+
+ @ArquillianResource
+ private URL base;
+
+ @Deployment
+ public static Archive> deploy() {
+
+ return
+ create(WebArchive.class)
+ // Add permissions.xml, which is the main file we're testing
+ .addAsResource("META-INF/permissions.xml")
+ .addAsWebInfResource((new File(WEBAPP_SRC + "/WEB-INF", "web.xml")))
+
+ // This class kicks off the EJB tests (which reside with the web module),
+ // but also contains tests of its own
+ .addClass(TestServlet.class)
+ .addPackage(BeanRoot.class.getPackage())
+ ;
+ }
+
+
+ @Test
+ @RunAsClient
+ public void test1Startup() throws IOException, URISyntaxException {
+ System.out.println("Testing Servlet from war deployed at " + new URL(base, "test"));
+
+ Response response =
+ newClient()
+ .target(new URL(base, "test").toURI())
+ .queryParam("tc", "Startup")
+ .request(TEXT_PLAIN)
+ .get();
+
+ assertTrue(response.readEntity(String.class).contains("Test:Pass"));
+ }
+
+ @Test
+ @RunAsClient
+ public void test2PermissionsXML() throws IOException, URISyntaxException {
+ System.out.println("Running actual permissions.xml test");
+
+ Response response =
+ newClient()
+ .target(new URL(base, "test").toURI())
+ .queryParam("tc", "InjectLookup")
+ .queryParam("web", "true")
+ .request(TEXT_PLAIN)
+ .get();
+
+ assertTrue(response.readEntity(String.class).contains("Test:Pass"));
+ }
+
+}
\ No newline at end of file
diff --git a/jacc/pom.xml b/jacc/pom.xml
new file mode 100644
index 000000000..eeb4171f3
--- /dev/null
+++ b/jacc/pom.xml
@@ -0,0 +1,27 @@
+
+ 4.0.0
+
+ org.javaee7
+ samples-parent
+ 1.0-SNAPSHOT
+
+
+ jacc
+ pom
+
+ Java EE 7 Sample: jacc
+
+
+ contexts
+ permissions-xml
+
+
+
+
+ org.javaee7
+ test-utils
+ ${project.version}
+ test
+
+
+
diff --git a/jaspic/README.md b/jaspic/README.md
new file mode 100644
index 000000000..40c4613fa
--- /dev/null
+++ b/jaspic/README.md
@@ -0,0 +1,18 @@
+# Java EE 7 Samples: JASPIC - Java Authentication Service Provider Interface for Containers#
+
+The [JSR 196](https://jcp.org/en/jsr/detail?id=196) seeks to define a standard interface by which authentication modules may be integrated with containers and such that these modules may establish the authentication identities used by containers.
+
+## Samples ##
+
+ - async-authentication
+ - basic-authentication
+ - ejb-propagation
+ - lifecycle
+ - register-session
+ - wrapping
+
+## How to run
+
+More information on how to run can be found at:
+
+
diff --git a/jaspic/async-authentication/pom.xml b/jaspic/async-authentication/pom.xml
new file mode 100644
index 000000000..e213e640a
--- /dev/null
+++ b/jaspic/async-authentication/pom.xml
@@ -0,0 +1,35 @@
+
+
+ 4.0.0
+
+
+ org.javaee7
+ jaspic
+ 1.0-SNAPSHOT
+
+
+ jaspic-async-authentication
+ war
+ Java EE 7 Sample: jaspic - async-authentication
+
+
+
+ org.javaee7
+ jaspic-common
+ 1.0-SNAPSHOT
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ ${skipEJB}
+
+
+
+
+
+
diff --git a/jaspic/async-authentication/src/main/java/org/javaee7/jaspic/asyncauthentication/bean/AsyncBean.java b/jaspic/async-authentication/src/main/java/org/javaee7/jaspic/asyncauthentication/bean/AsyncBean.java
new file mode 100644
index 000000000..aec517f6b
--- /dev/null
+++ b/jaspic/async-authentication/src/main/java/org/javaee7/jaspic/asyncauthentication/bean/AsyncBean.java
@@ -0,0 +1,38 @@
+package org.javaee7.jaspic.asyncauthentication.bean;
+
+import static java.lang.Thread.interrupted;
+import static java.lang.Thread.sleep;
+
+import java.io.IOException;
+
+import javax.ejb.Asynchronous;
+import javax.ejb.Stateless;
+import javax.servlet.AsyncContext;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@Stateless
+public class AsyncBean {
+
+ @Asynchronous
+ public void doAsync(AsyncContext asyncContext) {
+
+ try {
+ sleep(1000);
+ } catch (InterruptedException e) {
+ interrupted();
+ }
+
+ try {
+ asyncContext.getResponse().getWriter().write("async response");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ asyncContext.complete();
+ }
+
+}
diff --git a/jaspic/async-authentication/src/main/java/org/javaee7/jaspic/asyncauthentication/sam/SamAutoRegistrationListener.java b/jaspic/async-authentication/src/main/java/org/javaee7/jaspic/asyncauthentication/sam/SamAutoRegistrationListener.java
new file mode 100644
index 000000000..77118e5ac
--- /dev/null
+++ b/jaspic/async-authentication/src/main/java/org/javaee7/jaspic/asyncauthentication/sam/SamAutoRegistrationListener.java
@@ -0,0 +1,22 @@
+package org.javaee7.jaspic.asyncauthentication.sam;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.annotation.WebListener;
+
+import org.javaee7.jaspic.common.BaseServletContextListener;
+import org.javaee7.jaspic.common.JaspicUtils;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebListener
+public class SamAutoRegistrationListener extends BaseServletContextListener {
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ JaspicUtils.registerSAM(sce.getServletContext(), new TestServerAuthModule());
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/async-authentication/src/main/java/org/javaee7/jaspic/asyncauthentication/sam/TestServerAuthModule.java b/jaspic/async-authentication/src/main/java/org/javaee7/jaspic/asyncauthentication/sam/TestServerAuthModule.java
new file mode 100644
index 000000000..61b779405
--- /dev/null
+++ b/jaspic/async-authentication/src/main/java/org/javaee7/jaspic/asyncauthentication/sam/TestServerAuthModule.java
@@ -0,0 +1,95 @@
+package org.javaee7.jaspic.asyncauthentication.sam;
+
+import static javax.security.auth.message.AuthStatus.SEND_SUCCESS;
+import static javax.security.auth.message.AuthStatus.SUCCESS;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.AuthStatus;
+import javax.security.auth.message.MessageInfo;
+import javax.security.auth.message.MessagePolicy;
+import javax.security.auth.message.callback.CallerPrincipalCallback;
+import javax.security.auth.message.callback.GroupPrincipalCallback;
+import javax.security.auth.message.module.ServerAuthModule;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Very basic SAM that returns a single hardcoded user named "test" with role "architect" when the request parameter
+ * doLogin is present.
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class TestServerAuthModule implements ServerAuthModule {
+
+ private CallbackHandler handler;
+ private Class>[] supportedMessageTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class };
+
+ @Override
+ public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler,
+ @SuppressWarnings("rawtypes") Map options) throws AuthException {
+ this.handler = handler;
+ }
+
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject)
+ throws AuthException {
+
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+
+ Callback[] callbacks;
+
+ if (request.getParameter("doLogin") != null) {
+
+ // For the test perform a login by directly "returning" the details of the authenticated user.
+ // Normally credentials would be checked and the details fetched from some repository
+
+ callbacks = new Callback[] {
+ // The name of the authenticated user
+ new CallerPrincipalCallback(clientSubject, "test"),
+ // the roles of the authenticated user
+ new GroupPrincipalCallback(clientSubject, new String[] { "architect" })
+ };
+ } else {
+
+ // The JASPIC protocol for "do nothing"
+ callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, (Principal) null) };
+ }
+
+ try {
+
+ // Communicate the details of the authenticated user to the container. In many
+ // cases the handler will just store the details and the container will actually handle
+ // the login after we return from this method.
+ handler.handle(callbacks);
+
+ } catch (IOException | UnsupportedCallbackException e) {
+ throw (AuthException) new AuthException().initCause(e);
+ }
+
+ return SUCCESS;
+ }
+
+ @Override
+ public Class>[] getSupportedMessageTypes() {
+ return supportedMessageTypes;
+ }
+
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+ return SEND_SUCCESS;
+ }
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+
+ }
+}
\ No newline at end of file
diff --git a/jaspic/async-authentication/src/main/java/org/javaee7/jaspic/asyncauthentication/servlet/AsyncServlet.java b/jaspic/async-authentication/src/main/java/org/javaee7/jaspic/asyncauthentication/servlet/AsyncServlet.java
new file mode 100644
index 000000000..efc9a54bd
--- /dev/null
+++ b/jaspic/async-authentication/src/main/java/org/javaee7/jaspic/asyncauthentication/servlet/AsyncServlet.java
@@ -0,0 +1,37 @@
+package org.javaee7.jaspic.asyncauthentication.servlet;
+
+import java.io.IOException;
+
+import javax.ejb.EJB;
+import javax.servlet.AsyncContext;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.javaee7.jaspic.asyncauthentication.bean.AsyncBean;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/public/asyncServlet", asyncSupported = true)
+public class AsyncServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @EJB
+ private AsyncBean asyncBean;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ AsyncContext asyncContext = request.startAsync();
+ asyncContext.setTimeout(5000);
+
+ asyncBean.doAsync(asyncContext);
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/async-authentication/src/main/webapp/WEB-INF/glassfish-web.xml b/jaspic/async-authentication/src/main/webapp/WEB-INF/glassfish-web.xml
new file mode 100644
index 000000000..26559e3f6
--- /dev/null
+++ b/jaspic/async-authentication/src/main/webapp/WEB-INF/glassfish-web.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ architect
+ architect
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/async-authentication/src/main/webapp/WEB-INF/ibm-application-bnd.xml b/jaspic/async-authentication/src/main/webapp/WEB-INF/ibm-application-bnd.xml
new file mode 100644
index 000000000..9aa892cbc
--- /dev/null
+++ b/jaspic/async-authentication/src/main/webapp/WEB-INF/ibm-application-bnd.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/async-authentication/src/main/webapp/WEB-INF/jboss-web.xml b/jaspic/async-authentication/src/main/webapp/WEB-INF/jboss-web.xml
new file mode 100644
index 000000000..b6ab7d0ba
--- /dev/null
+++ b/jaspic/async-authentication/src/main/webapp/WEB-INF/jboss-web.xml
@@ -0,0 +1,5 @@
+
+
+
+ jaspitest
+
diff --git a/jaspic/async-authentication/src/main/webapp/WEB-INF/web.xml b/jaspic/async-authentication/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..ffd58ffa6
--- /dev/null
+++ b/jaspic/async-authentication/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Test
+ /protected/*
+
+
+ architect
+
+
+
+
+ architect
+
+
+
\ No newline at end of file
diff --git a/jaspic/async-authentication/src/test/java/org/javaee7/jaspic/asyncauthentication/AsyncAuthenticationPublicTest.java b/jaspic/async-authentication/src/test/java/org/javaee7/jaspic/asyncauthentication/AsyncAuthenticationPublicTest.java
new file mode 100644
index 000000000..a689cfa94
--- /dev/null
+++ b/jaspic/async-authentication/src/test/java/org/javaee7/jaspic/asyncauthentication/AsyncAuthenticationPublicTest.java
@@ -0,0 +1,40 @@
+package org.javaee7.jaspic.asyncauthentication;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ *
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class AsyncAuthenticationPublicTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ /**
+ * This tests that an async response works at all in the mere presence of
+ * a JASPIC SAM (that does nothing)
+ */
+ @Test
+ public void testBasicAsync() throws IOException, SAXException {
+
+ String response = getFromServerPath("public/asyncServlet");
+ assertTrue(response.contains("async response"));
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/basic-authentication/pom.xml b/jaspic/basic-authentication/pom.xml
new file mode 100644
index 000000000..8c520010e
--- /dev/null
+++ b/jaspic/basic-authentication/pom.xml
@@ -0,0 +1,22 @@
+
+
+ 4.0.0
+
+
+ org.javaee7
+ jaspic
+ 1.0-SNAPSHOT
+
+
+ jaspic-basic-authentication
+ war
+ Java EE 7 Sample: jaspic - basic-authentication
+
+
+
+ org.javaee7
+ jaspic-common
+ 1.0-SNAPSHOT
+
+
+
diff --git a/jaspic/basic-authentication/src/main/java/org/javaee7/jaspic/basicauthentication/sam/SamAutoRegistrationListener.java b/jaspic/basic-authentication/src/main/java/org/javaee7/jaspic/basicauthentication/sam/SamAutoRegistrationListener.java
new file mode 100644
index 000000000..5f3743192
--- /dev/null
+++ b/jaspic/basic-authentication/src/main/java/org/javaee7/jaspic/basicauthentication/sam/SamAutoRegistrationListener.java
@@ -0,0 +1,22 @@
+package org.javaee7.jaspic.basicauthentication.sam;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.annotation.WebListener;
+
+import org.javaee7.jaspic.common.BaseServletContextListener;
+import org.javaee7.jaspic.common.JaspicUtils;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebListener
+public class SamAutoRegistrationListener extends BaseServletContextListener {
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ JaspicUtils.registerSAM(sce.getServletContext(), new TestServerAuthModule());
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/basic-authentication/src/main/java/org/javaee7/jaspic/basicauthentication/sam/TestServerAuthModule.java b/jaspic/basic-authentication/src/main/java/org/javaee7/jaspic/basicauthentication/sam/TestServerAuthModule.java
new file mode 100644
index 000000000..ca1616221
--- /dev/null
+++ b/jaspic/basic-authentication/src/main/java/org/javaee7/jaspic/basicauthentication/sam/TestServerAuthModule.java
@@ -0,0 +1,95 @@
+package org.javaee7.jaspic.basicauthentication.sam;
+
+import static javax.security.auth.message.AuthStatus.SEND_SUCCESS;
+import static javax.security.auth.message.AuthStatus.SUCCESS;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.AuthStatus;
+import javax.security.auth.message.MessageInfo;
+import javax.security.auth.message.MessagePolicy;
+import javax.security.auth.message.callback.CallerPrincipalCallback;
+import javax.security.auth.message.callback.GroupPrincipalCallback;
+import javax.security.auth.message.module.ServerAuthModule;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Very basic SAM that returns a single hardcoded user named "test" with role "architect" when the request parameter
+ * doLogin is present.
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class TestServerAuthModule implements ServerAuthModule {
+
+ private CallbackHandler handler;
+ private Class>[] supportedMessageTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class };
+
+ @Override
+ public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler,
+ @SuppressWarnings("rawtypes") Map options) throws AuthException {
+ this.handler = handler;
+ }
+
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject)
+ throws AuthException {
+
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+
+ Callback[] callbacks;
+
+ if (request.getParameter("doLogin") != null) {
+
+ // For the test perform a login by directly "returning" the details of the authenticated user.
+ // Normally credentials would be checked and the details fetched from some repository
+
+ callbacks = new Callback[] {
+ // The name of the authenticated user
+ new CallerPrincipalCallback(clientSubject, "test"),
+ // the roles of the authenticated user
+ new GroupPrincipalCallback(clientSubject, new String[] { "architect" })
+ };
+ } else {
+
+ // The JASPIC protocol for "do nothing"
+ callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, (Principal) null) };
+ }
+
+ try {
+
+ // Communicate the details of the authenticated user to the container. In many
+ // cases the handler will just store the details and the container will actually handle
+ // the login after we return from this method.
+ handler.handle(callbacks);
+
+ } catch (IOException | UnsupportedCallbackException e) {
+ throw (AuthException) new AuthException().initCause(e);
+ }
+
+ return SUCCESS;
+ }
+
+ @Override
+ public Class>[] getSupportedMessageTypes() {
+ return supportedMessageTypes;
+ }
+
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+ return SEND_SUCCESS;
+ }
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+
+ }
+}
\ No newline at end of file
diff --git a/jaspic/basic-authentication/src/main/java/org/javaee7/jaspic/basicauthentication/servlet/ProtectedServlet.java b/jaspic/basic-authentication/src/main/java/org/javaee7/jaspic/basicauthentication/servlet/ProtectedServlet.java
new file mode 100644
index 000000000..34e8178aa
--- /dev/null
+++ b/jaspic/basic-authentication/src/main/java/org/javaee7/jaspic/basicauthentication/servlet/ProtectedServlet.java
@@ -0,0 +1,39 @@
+package org.javaee7.jaspic.basicauthentication.servlet;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/protected/servlet")
+public class ProtectedServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ response.getWriter().write("This is a protected servlet \n");
+
+ String webName = null;
+ if (request.getUserPrincipal() != null) {
+ webName = request.getUserPrincipal().getName();
+ }
+
+ response.getWriter().write("web username: " + webName + "\n");
+
+ boolean webHasRole = request.isUserInRole("architect");
+
+ response.getWriter().write("web user has role \"architect\": " + webHasRole + "\n");
+
+ }
+
+}
diff --git a/jaspic/basic-authentication/src/main/java/org/javaee7/jaspic/basicauthentication/servlet/PublicServlet.java b/jaspic/basic-authentication/src/main/java/org/javaee7/jaspic/basicauthentication/servlet/PublicServlet.java
new file mode 100644
index 000000000..de9f6a3b6
--- /dev/null
+++ b/jaspic/basic-authentication/src/main/java/org/javaee7/jaspic/basicauthentication/servlet/PublicServlet.java
@@ -0,0 +1,39 @@
+package org.javaee7.jaspic.basicauthentication.servlet;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/public/servlet")
+public class PublicServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ response.getWriter().write("This is a public servlet \n");
+
+ String webName = null;
+ if (request.getUserPrincipal() != null) {
+ webName = request.getUserPrincipal().getName();
+ }
+
+ response.getWriter().write("web username: " + webName + "\n");
+
+ boolean webHasRole = request.isUserInRole("architect");
+
+ response.getWriter().write("web user has role \"architect\": " + webHasRole + "\n");
+
+ }
+
+}
diff --git a/jaspic/basic-authentication/src/main/webapp/WEB-INF/glassfish-web.xml b/jaspic/basic-authentication/src/main/webapp/WEB-INF/glassfish-web.xml
new file mode 100644
index 000000000..26559e3f6
--- /dev/null
+++ b/jaspic/basic-authentication/src/main/webapp/WEB-INF/glassfish-web.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ architect
+ architect
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/basic-authentication/src/main/webapp/WEB-INF/ibm-application-bnd.xml b/jaspic/basic-authentication/src/main/webapp/WEB-INF/ibm-application-bnd.xml
new file mode 100644
index 000000000..9aa892cbc
--- /dev/null
+++ b/jaspic/basic-authentication/src/main/webapp/WEB-INF/ibm-application-bnd.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/basic-authentication/src/main/webapp/WEB-INF/jboss-web.xml b/jaspic/basic-authentication/src/main/webapp/WEB-INF/jboss-web.xml
new file mode 100644
index 000000000..b6ab7d0ba
--- /dev/null
+++ b/jaspic/basic-authentication/src/main/webapp/WEB-INF/jboss-web.xml
@@ -0,0 +1,5 @@
+
+
+
+ jaspitest
+
diff --git a/jaspic/basic-authentication/src/main/webapp/WEB-INF/web.xml b/jaspic/basic-authentication/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..ffd58ffa6
--- /dev/null
+++ b/jaspic/basic-authentication/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Test
+ /protected/*
+
+
+ architect
+
+
+
+
+ architect
+
+
+
\ No newline at end of file
diff --git a/jaspic/basic-authentication/src/test/java/org/javaee7/jaspic/basicauthentication/BasicAuthenticationProtectedTest.java b/jaspic/basic-authentication/src/test/java/org/javaee7/jaspic/basicauthentication/BasicAuthenticationProtectedTest.java
new file mode 100644
index 000000000..eb09f87f4
--- /dev/null
+++ b/jaspic/basic-authentication/src/test/java/org/javaee7/jaspic/basicauthentication/BasicAuthenticationProtectedTest.java
@@ -0,0 +1,85 @@
+package org.javaee7.jaspic.basicauthentication;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * This tests that we can login from a protected resource (a resource for which
+ * security constraints have been set) and then access it.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class BasicAuthenticationProtectedTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void testProtectedPageNotLoggedin() throws IOException, SAXException {
+
+ String response = getFromServerPath("protected/servlet");
+
+ // Not logged-in thus should not be accessible.
+ assertFalse(
+ "Not authenticated, so should not have been able to access protected resource",
+ response.contains("This is a protected servlet")
+ );
+ }
+
+ @Test
+ public void testProtectedPageLoggedin() throws IOException, SAXException {
+
+ String response = getFromServerPath("protected/servlet?doLogin=true");
+
+ // Now has to be logged-in so page is accessible
+ assertTrue(
+ "Should have been authenticated, but could not access protected resource",
+ response.contains("This is a protected servlet")
+ );
+
+ // Not only does the page needs to be accessible, the caller should have
+ // the correct
+ // name and roles as well
+
+ // Being able to access a page protected by a role but then seeing the un-authenticated
+ // (anonymous) user would normally be impossible, but could happen if the authorization
+ // system checks roles on the authenticated subject, but does not correctly expose
+ // or propagate these to the HttpServletRequest
+ assertFalse(
+ "Protected resource could be accessed, but the user appears to be the unauthenticated user. " +
+ "This should not be possible",
+ response.contains("web username: null")
+ );
+
+ // An authenticated user should have the exact name "test" and nothing else.
+ assertTrue(
+ "Protected resource could be accessed, but the username is not correct.",
+ response.contains("web username: test")
+ );
+
+ // Being able to access a page protected by role "architect" but failing
+ // the test for this role would normally be impossible, but could happen if the
+ // authorization system checks roles on the authenticated subject, but does not
+ // correctly expose or propagate these to the HttpServletRequest
+ assertTrue(
+ "Resource protected by role \"architect\" could be accessed, but user fails test for this role." +
+ "This should not be possible",
+ response.contains("web user has role \"architect\": true")
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/basic-authentication/src/test/java/org/javaee7/jaspic/basicauthentication/BasicAuthenticationPublicTest.java b/jaspic/basic-authentication/src/test/java/org/javaee7/jaspic/basicauthentication/BasicAuthenticationPublicTest.java
new file mode 100644
index 000000000..147b3006b
--- /dev/null
+++ b/jaspic/basic-authentication/src/test/java/org/javaee7/jaspic/basicauthentication/BasicAuthenticationPublicTest.java
@@ -0,0 +1,67 @@
+package org.javaee7.jaspic.basicauthentication;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * This tests that we can login from a public page (a page for which no security constraints have been set).
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class BasicAuthenticationPublicTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void testPublicPageNotLoggedin() throws IOException, SAXException {
+
+ String response = getFromServerPath("public/servlet");
+
+ // Not logged-in
+ assertTrue(
+ "Not authenticated, but a username other than null was encountered. " +
+ "This is not correct.",
+ response.contains("web username: null")
+ );
+ assertTrue(
+ "Not authenticated, but the user seems to have the role \"architect\". " +
+ "This is not correct.",
+ response.contains("web user has role \"architect\": false")
+ );
+ }
+
+ @Test
+ public void testPublicPageLoggedin() throws IOException, SAXException {
+
+ // JASPIC has to be able to authenticate a user when accessing a public (non-protected) resource.
+
+ String response = getFromServerPath("public/servlet?doLogin=true");
+
+ // Now has to be logged-in
+ assertTrue(
+ "User should have been authenticated and given name \"test\", " +
+ " but does not appear to have this name",
+ response.contains("web username: test")
+ );
+ assertTrue(
+ "User should have been authenticated and given role \"architect\", " +
+ " but does not appear to have this role",
+ response.contains("web user has role \"architect\": true")
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/basic-authentication/src/test/java/org/javaee7/jaspic/basicauthentication/BasicAuthenticationStatelessTest.java b/jaspic/basic-authentication/src/test/java/org/javaee7/jaspic/basicauthentication/BasicAuthenticationStatelessTest.java
new file mode 100644
index 000000000..b2d64fde6
--- /dev/null
+++ b/jaspic/basic-authentication/src/test/java/org/javaee7/jaspic/basicauthentication/BasicAuthenticationStatelessTest.java
@@ -0,0 +1,201 @@
+package org.javaee7.jaspic.basicauthentication;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class BasicAuthenticationStatelessTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ /**
+ * Tests that access to a protected page does not depend on the authenticated identity that was established in a previous
+ * request.
+ */
+ @Test
+ public void testProtectedAccessIsStateless() throws IOException, SAXException {
+
+ // -------------------- Request 1 ---------------------------
+
+ // Accessing protected page without login
+ String response = getFromServerPath("protected/servlet");
+
+ // Not logged-in thus should not be accessible.
+ assertFalse(response.contains("This is a protected servlet"));
+
+
+ // -------------------- Request 2 ---------------------------
+
+ // JASPIC is stateless and login (re-authenticate) has to happen for every request
+ //
+ // If the following fails but "testProtectedPageLoggedin" has succeeded,
+ // the container has probably remembered the "unauthenticated identity", e.g. it has remembered that
+ // we're not authenticated and it will deny further attempts to authenticate. This may happen when
+ // the container does not correctly recognize the JASPIC protocol for "do nothing".
+
+ response = getFromServerPath("protected/servlet?doLogin=true");
+
+ // Now has to be logged-in so page is accessible
+ assertTrue(
+ "Could not access protected page, but should be able to. " +
+ "Did the container remember the previously set 'unauthenticated identity'?",
+ response.contains("This is a protected servlet")
+ );
+
+
+ // -------------------- Request 3 ---------------------------
+
+ // JASPIC is stateless and login (re-authenticate) has to happen for every request
+ //
+ // In the following method we do a call without logging in after one where we did login.
+ // The container should not remember this login and has to deny access.
+ response = getFromServerPath("protected/servlet");
+
+ // Not logged-in thus should not be accessible.
+ assertFalse(
+ "Could access protected page, but should not be able to. " +
+ "Did the container remember the authenticated identity that was set in previous request?",
+ response.contains("This is a protected servlet")
+ );
+ }
+
+ /**
+ * Tests that access to a protected page does not depend on the authenticated identity that was established in a previous
+ * request, but use a different request order than the previous test.
+ */
+ @Test
+ public void testProtectedAccessIsStateless2() throws IOException, SAXException {
+
+ // -------------------- Request 1 ---------------------------
+
+ // Start with doing a login
+ String response = getFromServerPath("protected/servlet?doLogin=true");
+
+
+ // -------------------- Request 2 ---------------------------
+
+ // JASPIC is stateless and login (re-authenticate) has to happen for every request
+ //
+ // In the following method we do a call without logging in after one where we did login.
+ // The container should not remember this login and has to deny access.
+
+ // Accessing protected page without login
+ response = getFromServerPath("protected/servlet");
+
+ // Not logged-in thus should not be accessible.
+ assertFalse(
+ "Could access protected page, but should not be able to. " +
+ "Did the container remember the authenticated identity that was set in the previous request?",
+ response.contains("This is a protected servlet")
+ );
+ }
+
+ /**
+ * Tests that access to a public page does not depend on the authenticated identity that was established in a previous
+ * request.
+ */
+ @Test
+ public void testPublicAccessIsStateless() throws IOException, SAXException {
+
+ // -------------------- Request 1 ---------------------------
+
+ String response = getFromServerPath("public/servlet");
+
+ // Establish that we're initially not logged-in
+ assertTrue(
+ "Not authenticated, but a username other than null was encountered. " +
+ "This is not correct.",
+ response.contains("web username: null")
+ );
+ assertTrue(
+ "Not authenticated, but the user seems to have the role \"architect\". " +
+ "This is not correct.",
+ response.contains("web user has role \"architect\": false")
+ );
+
+
+ // -------------------- Request 2 ---------------------------
+
+ response = getFromServerPath("public/servlet?doLogin=true");
+
+ // Now has to be logged-in
+ assertTrue(
+ "User should have been authenticated and given name \"test\", " +
+ " but does not appear to have this name",
+ response.contains("web username: test")
+ );
+ assertTrue(response.contains("web user has role \"architect\": true"));
+
+
+ // -------------------- Request 3 ---------------------------
+
+ // Accessing public page without login
+ response = getFromServerPath("public/servlet");
+
+ // No details should linger around
+ assertTrue(
+ "Should not be authenticated, but a username other than null was encountered. " +
+ "Did the container remember the authenticated identity that was set in the previous request?",
+ response.contains("web username: null")
+ );
+ assertTrue(
+ "The unauthenticated user has the role 'architect', which should not be the case. " +
+ "The container seemed to have remembered it from the previous request.",
+ response.contains("web user has role \"architect\": false")
+ );
+ }
+
+ /**
+ * Tests independently from being able to access a protected resource if any details of a previously established
+ * authenticated identity are remembered
+ */
+ @Test
+ public void testProtectedThenPublicAccessIsStateless() throws IOException, SAXException {
+
+ // -------------------- Request 1 ---------------------------
+
+ // Accessing protected page with login
+ String response = getFromServerPath("protected/servlet?doLogin=true");
+
+
+ // -------------------- Request 2 ---------------------------
+
+ // Accessing public page without login
+ response = getFromServerPath("public/servlet");
+
+ // No details should linger around
+ assertFalse(
+ "User principal was 'test', but it should be null here. " +
+ "The container seemed to have remembered it from the previous request.",
+ response.contains("web username: test")
+ );
+ assertTrue(
+ "User principal was not null, but it should be null here. ",
+ response.contains("web username: null")
+ );
+ assertTrue(
+ "The unauthenticated user has the role 'architect', which should not be the case. " +
+ "The container seemed to have remembered it from the previous request.",
+ response.contains("web user has role \"architect\": false")
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/common/pom.xml b/jaspic/common/pom.xml
new file mode 100644
index 000000000..069b74319
--- /dev/null
+++ b/jaspic/common/pom.xml
@@ -0,0 +1,64 @@
+
+
+
+ 4.0.0
+
+ org.javaee7
+ jaspic-common
+ 1.0-SNAPSHOT
+
+ jar
+ Java EE 7 Sample: jaspic - common
+
+
+ UTF-8
+ 1.7
+ 1.7
+
+
+
+
+
+ org.jboss.arquillian
+ arquillian-bom
+ 1.1.14.Final
+ import
+ pom
+
+
+
+
+
+
+ javax
+ javaee-api
+ 7.0
+ provided
+
+
+ org.jboss.arquillian.junit
+ arquillian-junit-container
+ provided
+
+
+ junit
+ junit
+ 4.13.1
+ provided
+
+
+ net.sourceforge.htmlunit
+ htmlunit
+ 2.37.0
+ provided
+
+
+ org.jsoup
+ jsoup
+ 1.14.2
+
+
+
diff --git a/jaspic/common/src/main/java/org/javaee7/jaspic/common/ArquillianBase.java b/jaspic/common/src/main/java/org/javaee7/jaspic/common/ArquillianBase.java
new file mode 100644
index 000000000..b2f0e9687
--- /dev/null
+++ b/jaspic/common/src/main/java/org/javaee7/jaspic/common/ArquillianBase.java
@@ -0,0 +1,172 @@
+package org.javaee7.jaspic.common;
+
+import static java.lang.Boolean.getBoolean;
+import static java.util.logging.Level.SEVERE;
+import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
+import static org.jsoup.Jsoup.parse;
+import static org.jsoup.parser.Parser.xmlParser;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ArchivePath;
+import org.jboss.shrinkwrap.api.Node;
+import org.jboss.shrinkwrap.api.spec.EnterpriseArchive;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
+
+import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
+import com.gargoylesoftware.htmlunit.WebClient;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class ArquillianBase {
+
+ private static final String WEBAPP_SRC = "src/main/webapp";
+ private static final Logger logger = Logger.getLogger(ArquillianBase.class.getName());
+
+ private WebClient webClient;
+ private String response;
+
+ @Rule
+ public TestWatcher ruleExample = new TestWatcher() {
+ @Override
+ protected void failed(Throwable e, Description description) {
+ super.failed(e, description);
+
+ logger.log(SEVERE,
+ "\n\nTest failed: " +
+ description.getClassName() + "." + description.getMethodName() +
+
+ "\nMessage: " + e.getMessage() +
+
+ "\nLast response: " +
+
+ "\n\n" + formatHTML(response) + "\n\n");
+
+ }
+ };
+
+ public static String formatHTML(String html) {
+ try {
+ return parse(html, "", xmlParser()).toString();
+ } catch (Exception e) {
+ return html;
+ }
+ }
+
+ public static Archive> defaultArchive() {
+ return tryWrapEAR(defaultWebArchive());
+ }
+
+ public static WebArchive defaultWebArchive() {
+ return
+ removeTestClasses(
+ create(WebArchive.class, "test.war")
+ .addPackages(true, "org.javaee7.jaspic")
+ .addAsWebInfResource(resource("web.xml"))
+ .addAsWebInfResource(resource("jboss-web.xml"))
+ .addAsWebInfResource(resource("glassfish-web.xml")));
+ }
+
+ private static WebArchive removeTestClasses(WebArchive archive) {
+ for (Map.Entry content : archive.getContent().entrySet()) {
+ if (content.getKey().get().endsWith("Test.class")) {
+ archive.delete(content.getKey().get());
+ }
+ }
+ archive.deleteClass(ArquillianBase.class);
+
+ return archive;
+ }
+
+ public static Archive> tryWrapEAR(WebArchive webArchive) {
+ if (getBoolean("useEarForJaspic")) {
+ return
+ // EAR archive
+ create(EnterpriseArchive.class, "test.ear")
+
+ // Liberty needs to have the binding file in an ear.
+ // TODO: this is no longer the case and this code can be removed (-bnd.xml
+ // needs to be moved to correct place)
+ .addAsManifestResource(resource("ibm-application-bnd.xml"))
+
+ // Web module
+ // This is needed to prevent Arquillian generating an illegal application.xml
+ .addAsModule(
+ webArchive
+ );
+ } else {
+ return webArchive;
+ }
+ }
+
+ public static File resource(String name) {
+ return new File(WEBAPP_SRC + "/WEB-INF", name);
+ }
+
+ public static File web(String name) {
+ return new File(WEBAPP_SRC, name);
+ }
+
+ @ArquillianResource
+ private URL base;
+
+ @Before
+ public void setUp() {
+ webClient = new WebClient();
+ webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
+ }
+
+ @After
+ public void tearDown() {
+ webClient.getCookieManager().clearCookies();
+ webClient.close();
+ }
+
+
+
+ protected WebClient getWebClient() {
+ return webClient;
+ }
+
+ protected URL getBase() {
+ return base;
+ }
+
+ /**
+ * Gets content from the path that's relative to the base URL on which the Arquillian test
+ * archive is deployed.
+ *
+ * @param path the path relative to the URL on which the Arquillian test is deployed
+ * @return the raw content as a string as returned by the server
+ */
+ protected String getFromServerPath(final String path) {
+ response = null;
+ for (int i=0; i<=3; i++) {
+ try {
+ response = webClient.getPage(base + path).getWebResponse().getContentAsString();
+ if (!response.contains("The response wrapper must wrap the response obtained from getResponse()")) {
+ return response;
+ }
+ } catch (FailingHttpStatusCodeException | IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ return response;
+ }
+
+}
diff --git a/jaspic/common/src/main/java/org/javaee7/jaspic/common/BaseServletContextListener.java b/jaspic/common/src/main/java/org/javaee7/jaspic/common/BaseServletContextListener.java
new file mode 100644
index 000000000..271b06996
--- /dev/null
+++ b/jaspic/common/src/main/java/org/javaee7/jaspic/common/BaseServletContextListener.java
@@ -0,0 +1,23 @@
+package org.javaee7.jaspic.common;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class BaseServletContextListener implements ServletContextListener {
+
+ @Override
+ public void contextInitialized(ServletContextEvent arg0) {
+ // NOOP
+ }
+
+ @Override
+ public void contextDestroyed(ServletContextEvent arg0) {
+ // NOOP
+ }
+
+}
diff --git a/jaspic/common/src/main/java/org/javaee7/jaspic/common/JaspicUtils.java b/jaspic/common/src/main/java/org/javaee7/jaspic/common/JaspicUtils.java
new file mode 100644
index 000000000..d89eaf22f
--- /dev/null
+++ b/jaspic/common/src/main/java/org/javaee7/jaspic/common/JaspicUtils.java
@@ -0,0 +1,32 @@
+package org.javaee7.jaspic.common;
+
+import javax.security.auth.message.config.AuthConfigFactory;
+import javax.security.auth.message.module.ServerAuthModule;
+import javax.servlet.ServletContext;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+public final class JaspicUtils {
+
+ private JaspicUtils() {
+ }
+
+ /**
+ * Registers the given SAM using the standard JASPIC {@link AuthConfigFactory} but using a small set of wrappers that just
+ * pass the calls through to the SAM.
+ *
+ * @param serverAuthModule
+ */
+ public static void registerSAM(ServletContext context, ServerAuthModule serverAuthModule) {
+ AuthConfigFactory.getFactory().registerConfigProvider(new TestAuthConfigProvider(serverAuthModule), "HttpServlet",
+ getAppContextID(context), "Test authentication config provider");
+ }
+
+ public static String getAppContextID(ServletContext context) {
+ return context.getVirtualServerName() + " " + context.getContextPath();
+ }
+
+}
diff --git a/jaspic/common/src/main/java/org/javaee7/jaspic/common/TestAuthConfigProvider.java b/jaspic/common/src/main/java/org/javaee7/jaspic/common/TestAuthConfigProvider.java
new file mode 100644
index 000000000..053ee1ee9
--- /dev/null
+++ b/jaspic/common/src/main/java/org/javaee7/jaspic/common/TestAuthConfigProvider.java
@@ -0,0 +1,91 @@
+package org.javaee7.jaspic.common;
+
+import java.util.Map;
+
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.config.AuthConfigFactory;
+import javax.security.auth.message.config.AuthConfigProvider;
+import javax.security.auth.message.config.ClientAuthConfig;
+import javax.security.auth.message.config.ServerAuthConfig;
+import javax.security.auth.message.config.ServerAuthContext;
+import javax.security.auth.message.module.ServerAuthModule;
+
+/**
+ * This class functions as a kind of factory-factory for {@link ServerAuthConfig} instances, which are by themselves factories
+ * for {@link ServerAuthContext} instances, which are delegates for the actual {@link ServerAuthModule} (SAM) that we're after.
+ *
+ * @author Arjan Tijms
+ */
+public class TestAuthConfigProvider implements AuthConfigProvider {
+
+ private static final String CALLBACK_HANDLER_PROPERTY_NAME = "authconfigprovider.client.callbackhandler";
+
+ private Map providerProperties;
+ private ServerAuthModule serverAuthModule;
+
+ public TestAuthConfigProvider(ServerAuthModule serverAuthModule) {
+ this.serverAuthModule = serverAuthModule;
+ }
+
+ /**
+ * Constructor with signature and implementation that's required by API.
+ *
+ * @param properties
+ * @param factory
+ */
+ public TestAuthConfigProvider(Map properties, AuthConfigFactory factory) {
+ this.providerProperties = properties;
+
+ // API requires self registration if factory is provided. Not clear
+ // where the "layer" (2nd parameter)
+ // and especially "appContext" (3rd parameter) values have to come from
+ // at this place.
+ if (factory != null) {
+ factory.registerConfigProvider(this, null, null, "Auto registration");
+ }
+ }
+
+ /**
+ * The actual factory method that creates the factory used to eventually obtain the delegate for a SAM.
+ */
+ @Override
+ public ServerAuthConfig getServerAuthConfig(String layer, String appContext, CallbackHandler handler) throws AuthException,
+ SecurityException {
+ return new TestServerAuthConfig(layer, appContext, handler == null ? createDefaultCallbackHandler() : handler,
+ providerProperties, serverAuthModule);
+ }
+
+ @Override
+ public ClientAuthConfig getClientAuthConfig(String layer, String appContext, CallbackHandler handler) throws AuthException,
+ SecurityException {
+ return null;
+ }
+
+ @Override
+ public void refresh() {
+ }
+
+ /**
+ * Creates a default callback handler via the system property "authconfigprovider.client.callbackhandler", as seemingly
+ * required by the API (API uses wording "may" create default handler). TODO: Isn't
+ * "authconfigprovider.client.callbackhandler" JBoss specific?
+ *
+ * @return
+ * @throws AuthException
+ */
+ private CallbackHandler createDefaultCallbackHandler() throws AuthException {
+ String callBackClassName = System.getProperty(CALLBACK_HANDLER_PROPERTY_NAME);
+
+ if (callBackClassName == null) {
+ throw new AuthException("No default handler set via system property: " + CALLBACK_HANDLER_PROPERTY_NAME);
+ }
+
+ try {
+ return (CallbackHandler) Thread.currentThread().getContextClassLoader().loadClass(callBackClassName).newInstance();
+ } catch (Exception e) {
+ throw new AuthException(e.getMessage());
+ }
+ }
+
+}
diff --git a/jaspic/common/src/main/java/org/javaee7/jaspic/common/TestServerAuthConfig.java b/jaspic/common/src/main/java/org/javaee7/jaspic/common/TestServerAuthConfig.java
new file mode 100644
index 000000000..510a29f2f
--- /dev/null
+++ b/jaspic/common/src/main/java/org/javaee7/jaspic/common/TestServerAuthConfig.java
@@ -0,0 +1,79 @@
+package org.javaee7.jaspic.common;
+
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.MessageInfo;
+import javax.security.auth.message.config.ServerAuthConfig;
+import javax.security.auth.message.config.ServerAuthContext;
+import javax.security.auth.message.module.ServerAuthModule;
+
+/**
+ * This class functions as a kind of factory for {@link ServerAuthContext} instances, which are delegates for the actual
+ * {@link ServerAuthModule} (SAM) that we're after.
+ *
+ * @author Arjan Tijms
+ */
+public class TestServerAuthConfig implements ServerAuthConfig {
+
+ private String layer;
+ private String appContext;
+ private CallbackHandler handler;
+ private Map providerProperties;
+ private ServerAuthModule serverAuthModule;
+
+ public TestServerAuthConfig(String layer, String appContext, CallbackHandler handler,
+ Map providerProperties, ServerAuthModule serverAuthModule) {
+ this.layer = layer;
+ this.appContext = appContext;
+ this.handler = handler;
+ this.providerProperties = providerProperties;
+ this.serverAuthModule = serverAuthModule;
+ }
+
+ @Override
+ public ServerAuthContext getAuthContext(String authContextID, Subject serviceSubject,
+ @SuppressWarnings("rawtypes") Map properties) throws AuthException {
+ return new TestServerAuthContext(handler, serverAuthModule);
+ }
+
+ // ### The methods below mostly just return what has been passed into the
+ // constructor.
+ // ### In practice they don't seem to be called
+
+ @Override
+ public String getMessageLayer() {
+ return layer;
+ }
+
+ /**
+ * It's not entirely clear what the difference is between the "application context identifier" (appContext) and the
+ * "authentication context identifier" (authContext). In early iterations of the specification, authContext was called
+ * "operation" and instead of the MessageInfo it was obtained by something called an "authParam".
+ */
+ @Override
+ public String getAuthContextID(MessageInfo messageInfo) {
+ return appContext;
+ }
+
+ @Override
+ public String getAppContext() {
+ return appContext;
+ }
+
+ @Override
+ public void refresh() {
+ }
+
+ @Override
+ public boolean isProtected() {
+ return false;
+ }
+
+ public Map getProviderProperties() {
+ return providerProperties;
+ }
+
+}
diff --git a/jaspic/common/src/main/java/org/javaee7/jaspic/common/TestServerAuthContext.java b/jaspic/common/src/main/java/org/javaee7/jaspic/common/TestServerAuthContext.java
new file mode 100644
index 000000000..9c2d09558
--- /dev/null
+++ b/jaspic/common/src/main/java/org/javaee7/jaspic/common/TestServerAuthContext.java
@@ -0,0 +1,49 @@
+package org.javaee7.jaspic.common;
+
+import java.util.Collections;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.AuthStatus;
+import javax.security.auth.message.MessageInfo;
+import javax.security.auth.message.ServerAuth;
+import javax.security.auth.message.config.ServerAuthContext;
+import javax.security.auth.message.module.ServerAuthModule;
+
+/**
+ * The Server Authentication Context is an extra (required) indirection between the Application Server and the actual Server
+ * Authentication Module (SAM). This can be used to encapsulate any number of SAMs and either select one at run-time, invoke
+ * them all in order, etc.
+ *
+ * Since this simple example only has a single SAM, we delegate directly to that one. Note that this {@link ServerAuthContext}
+ * and the {@link ServerAuthModule} (SAM) share a common base interface: {@link ServerAuth}.
+ *
+ * @author Arjan Tijms
+ */
+public class TestServerAuthContext implements ServerAuthContext {
+
+ private final ServerAuthModule serverAuthModule;
+
+ public TestServerAuthContext(CallbackHandler handler, ServerAuthModule serverAuthModule) throws AuthException {
+ this.serverAuthModule = serverAuthModule;
+ serverAuthModule.initialize(null, null, handler, Collections. emptyMap());
+ }
+
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject)
+ throws AuthException {
+ return serverAuthModule.validateRequest(messageInfo, clientSubject, serviceSubject);
+ }
+
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+ return serverAuthModule.secureResponse(messageInfo, serviceSubject);
+ }
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+ serverAuthModule.cleanSubject(messageInfo, subject);
+ }
+
+}
diff --git a/jaspic/custom-principal/pom.xml b/jaspic/custom-principal/pom.xml
new file mode 100644
index 000000000..a5c863683
--- /dev/null
+++ b/jaspic/custom-principal/pom.xml
@@ -0,0 +1,23 @@
+
+
+ 4.0.0
+
+
+ org.javaee7
+ jaspic
+ 1.0-SNAPSHOT
+ ../pom.xml
+
+
+ jaspic-custom-principal
+ war
+ Java EE 7 Sample: jaspic - custom principal
+
+
+
+ org.javaee7
+ jaspic-common
+ 1.0-SNAPSHOT
+
+
+
diff --git a/jaspic/custom-principal/src/main/java/org/javaee7/jaspic/customprincipal/sam/MyPrincipal.java b/jaspic/custom-principal/src/main/java/org/javaee7/jaspic/customprincipal/sam/MyPrincipal.java
new file mode 100644
index 000000000..ba208c4da
--- /dev/null
+++ b/jaspic/custom-principal/src/main/java/org/javaee7/jaspic/customprincipal/sam/MyPrincipal.java
@@ -0,0 +1,23 @@
+package org.javaee7.jaspic.customprincipal.sam;
+
+import java.security.Principal;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class MyPrincipal implements Principal {
+
+ private final String name;
+
+ public MyPrincipal(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+}
diff --git a/jaspic/custom-principal/src/main/java/org/javaee7/jaspic/customprincipal/sam/SamAutoRegistrationListener.java b/jaspic/custom-principal/src/main/java/org/javaee7/jaspic/customprincipal/sam/SamAutoRegistrationListener.java
new file mode 100644
index 000000000..6562a46ef
--- /dev/null
+++ b/jaspic/custom-principal/src/main/java/org/javaee7/jaspic/customprincipal/sam/SamAutoRegistrationListener.java
@@ -0,0 +1,22 @@
+package org.javaee7.jaspic.customprincipal.sam;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.annotation.WebListener;
+
+import org.javaee7.jaspic.common.BaseServletContextListener;
+import org.javaee7.jaspic.common.JaspicUtils;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebListener
+public class SamAutoRegistrationListener extends BaseServletContextListener {
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ JaspicUtils.registerSAM(sce.getServletContext(), new TestServerAuthModule());
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/custom-principal/src/main/java/org/javaee7/jaspic/customprincipal/sam/TestServerAuthModule.java b/jaspic/custom-principal/src/main/java/org/javaee7/jaspic/customprincipal/sam/TestServerAuthModule.java
new file mode 100644
index 000000000..8ff11b4d4
--- /dev/null
+++ b/jaspic/custom-principal/src/main/java/org/javaee7/jaspic/customprincipal/sam/TestServerAuthModule.java
@@ -0,0 +1,96 @@
+package org.javaee7.jaspic.customprincipal.sam;
+
+import static javax.security.auth.message.AuthStatus.SEND_SUCCESS;
+import static javax.security.auth.message.AuthStatus.SUCCESS;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.AuthStatus;
+import javax.security.auth.message.MessageInfo;
+import javax.security.auth.message.MessagePolicy;
+import javax.security.auth.message.callback.CallerPrincipalCallback;
+import javax.security.auth.message.callback.GroupPrincipalCallback;
+import javax.security.auth.message.module.ServerAuthModule;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Variant of the SAM used by the basic-authentication test, where the so-called "Principal form" of the
+ * CallerPrincipalCallback is used. Here we pass in a custom Principal instead of a string.
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class TestServerAuthModule implements ServerAuthModule {
+
+ private CallbackHandler handler;
+ private Class>[] supportedMessageTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class };
+
+ @Override
+ public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler,
+ @SuppressWarnings("rawtypes") Map options) throws AuthException {
+ this.handler = handler;
+ }
+
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject)
+ throws AuthException {
+
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+
+ Callback[] callbacks;
+
+ if (request.getParameter("doLogin") != null) {
+
+ // For the test perform a login by directly "returning" the details of the authenticated user.
+ // Normally credentials would be checked and the details fetched from some repository
+
+ callbacks = new Callback[] {
+ // The name of the authenticated user *** VIA A CUSTOM PRINCIPAL ***.
+ // This is the main variant of this test vs basic-authentication
+ new CallerPrincipalCallback(clientSubject, new MyPrincipal("test")),
+ // the roles of the authenticated user
+ new GroupPrincipalCallback(clientSubject, new String[] { "architect" })
+ };
+ } else {
+
+ // The JASPIC protocol for "do nothing"
+ callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, (Principal) null) };
+ }
+
+ try {
+
+ // Communicate the details of the authenticated user to the container. In many
+ // cases the handler will just store the details and the container will actually handle
+ // the login after we return from this method.
+ handler.handle(callbacks);
+
+ } catch (IOException | UnsupportedCallbackException e) {
+ throw (AuthException) new AuthException().initCause(e);
+ }
+
+ return SUCCESS;
+ }
+
+ @Override
+ public Class>[] getSupportedMessageTypes() {
+ return supportedMessageTypes;
+ }
+
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+ return SEND_SUCCESS;
+ }
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+
+ }
+}
\ No newline at end of file
diff --git a/jaspic/custom-principal/src/main/java/org/javaee7/jaspic/customprincipal/servlet/ProtectedServlet.java b/jaspic/custom-principal/src/main/java/org/javaee7/jaspic/customprincipal/servlet/ProtectedServlet.java
new file mode 100644
index 000000000..fe4cf9788
--- /dev/null
+++ b/jaspic/custom-principal/src/main/java/org/javaee7/jaspic/customprincipal/servlet/ProtectedServlet.java
@@ -0,0 +1,45 @@
+package org.javaee7.jaspic.customprincipal.servlet;
+
+import java.io.IOException;
+import java.security.Principal;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.javaee7.jaspic.customprincipal.sam.MyPrincipal;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/protected/servlet")
+public class ProtectedServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ response.getWriter().write("This is a protected servlet \n");
+
+ String webName = null;
+ boolean isCustomPrincipal = false;
+ if (request.getUserPrincipal() != null) {
+ Principal principal = request.getUserPrincipal();
+ isCustomPrincipal = principal instanceof MyPrincipal;
+ webName = request.getUserPrincipal().getName();
+ }
+
+ boolean webHasRole = request.isUserInRole("architect");
+
+ response.getWriter().write("isCustomPrincipal: " + isCustomPrincipal + "\n");
+ response.getWriter().write("web username: " + webName + "\n");
+ response.getWriter().write("web user has role \"architect\": " + webHasRole + "\n");
+
+ }
+
+}
diff --git a/jaspic/custom-principal/src/main/java/org/javaee7/jaspic/customprincipal/servlet/PublicServlet.java b/jaspic/custom-principal/src/main/java/org/javaee7/jaspic/customprincipal/servlet/PublicServlet.java
new file mode 100644
index 000000000..46ff7203c
--- /dev/null
+++ b/jaspic/custom-principal/src/main/java/org/javaee7/jaspic/customprincipal/servlet/PublicServlet.java
@@ -0,0 +1,44 @@
+package org.javaee7.jaspic.customprincipal.servlet;
+
+import java.io.IOException;
+import java.security.Principal;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.javaee7.jaspic.customprincipal.sam.MyPrincipal;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/public/servlet")
+public class PublicServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ response.getWriter().write("This is a public servlet \n");
+
+ String webName = null;
+ boolean isCustomPrincipal = false;
+ if (request.getUserPrincipal() != null) {
+ Principal principal = request.getUserPrincipal();
+ isCustomPrincipal = principal instanceof MyPrincipal;
+ webName = principal.getName();
+ }
+
+ boolean webHasRole = request.isUserInRole("architect");
+
+ response.getWriter().write("isCustomPrincipal: " + isCustomPrincipal + "\n");
+ response.getWriter().write("web username: " + webName + "\n");
+ response.getWriter().write("web user has role \"architect\": " + webHasRole + "\n");
+ }
+
+}
diff --git a/jaspic/custom-principal/src/main/webapp/WEB-INF/glassfish-web.xml b/jaspic/custom-principal/src/main/webapp/WEB-INF/glassfish-web.xml
new file mode 100644
index 000000000..26559e3f6
--- /dev/null
+++ b/jaspic/custom-principal/src/main/webapp/WEB-INF/glassfish-web.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ architect
+ architect
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/custom-principal/src/main/webapp/WEB-INF/ibm-application-bnd.xml b/jaspic/custom-principal/src/main/webapp/WEB-INF/ibm-application-bnd.xml
new file mode 100644
index 000000000..9aa892cbc
--- /dev/null
+++ b/jaspic/custom-principal/src/main/webapp/WEB-INF/ibm-application-bnd.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/custom-principal/src/main/webapp/WEB-INF/jboss-web.xml b/jaspic/custom-principal/src/main/webapp/WEB-INF/jboss-web.xml
new file mode 100644
index 000000000..b6ab7d0ba
--- /dev/null
+++ b/jaspic/custom-principal/src/main/webapp/WEB-INF/jboss-web.xml
@@ -0,0 +1,5 @@
+
+
+
+ jaspitest
+
diff --git a/jaspic/custom-principal/src/main/webapp/WEB-INF/web.xml b/jaspic/custom-principal/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..ffd58ffa6
--- /dev/null
+++ b/jaspic/custom-principal/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Test
+ /protected/*
+
+
+ architect
+
+
+
+
+ architect
+
+
+
\ No newline at end of file
diff --git a/jaspic/custom-principal/src/test/java/org/javaee7/jaspictest/customprincipal/CustomPrincipalProtectedTest.java b/jaspic/custom-principal/src/test/java/org/javaee7/jaspictest/customprincipal/CustomPrincipalProtectedTest.java
new file mode 100644
index 000000000..7280b1108
--- /dev/null
+++ b/jaspic/custom-principal/src/test/java/org/javaee7/jaspictest/customprincipal/CustomPrincipalProtectedTest.java
@@ -0,0 +1,56 @@
+package org.javaee7.jaspictest.customprincipal;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * This tests that we can login from a protected resource (a resource for which security constraints have been set), then
+ * access it and that for this type of page the custom principal correctly arrives in a Servlet.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class CustomPrincipalProtectedTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void testProtectedPageLoggedin() throws IOException, SAXException {
+
+ String response = getFromServerPath("protected/servlet?doLogin=true");
+
+ // Target resource should be accessible
+ assertTrue(
+ "Authentication seems to have failed, as the expected response from the requested resource is not correct.",
+ response.contains("This is a protected servlet")
+ );
+
+ // Has to be logged-in with the right principal
+ assertTrue(
+ "Authentication but username is not the expected one 'test'",
+ response.contains("web username: test")
+ );
+ assertTrue(
+ "Authentication succeeded and username is correct, but the expected role 'architect' is not present.",
+ response.contains("web user has role \"architect\": true"));
+
+ assertTrue(
+ "Authentication succeeded and username and roles are correct, but principal type is not the expected custom type.",
+ response.contains("isCustomPrincipal: true")
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/custom-principal/src/test/java/org/javaee7/jaspictest/customprincipal/CustomPrincipalPublicTest.java b/jaspic/custom-principal/src/test/java/org/javaee7/jaspictest/customprincipal/CustomPrincipalPublicTest.java
new file mode 100644
index 000000000..6f70aeba6
--- /dev/null
+++ b/jaspic/custom-principal/src/test/java/org/javaee7/jaspictest/customprincipal/CustomPrincipalPublicTest.java
@@ -0,0 +1,52 @@
+package org.javaee7.jaspictest.customprincipal;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * This tests that we can login from a public page (a page for which no security constraints have been set)
+ * and that for this type of page the custom principal correctly arrives in a Servlet.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class CustomPrincipalPublicTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void testPublicPageLoggedin() throws IOException, SAXException {
+
+ // JASPIC has to be able to authenticate a user when accessing a public (non-protected) resource.
+
+ String response = getFromServerPath("public/servlet?doLogin=true");
+
+ // Has to be logged-in with the right principal
+ assertTrue(
+ "Username is not the expected one 'test'",
+ response.contains("web username: test")
+ );
+ assertTrue(
+ "Username is correct, but the expected role 'architect' is not present.",
+ response.contains("web user has role \"architect\": true")
+ );
+ assertTrue(
+ "Username and roles are correct, but principal type is not the expected custom type.",
+ response.contains("isCustomPrincipal: true")
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/custom-principal/src/test/java/org/javaee7/jaspictest/customprincipal/CustomPrincipalStatelessTest.java b/jaspic/custom-principal/src/test/java/org/javaee7/jaspictest/customprincipal/CustomPrincipalStatelessTest.java
new file mode 100644
index 000000000..6ab3f7814
--- /dev/null
+++ b/jaspic/custom-principal/src/test/java/org/javaee7/jaspictest/customprincipal/CustomPrincipalStatelessTest.java
@@ -0,0 +1,180 @@
+package org.javaee7.jaspictest.customprincipal;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * Idential test as in basic-authentication, but now performed against a SAM which sets a custom principal.
+ * Therefore tests that for this kind of usage of the PrincipalCallback JASPIC is stateless just as well.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class CustomPrincipalStatelessTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ /**
+ * Tests that access to a protected page does not depend on the authenticated identity that was established in a previous
+ * request.
+ */
+ @Test
+ public void testProtectedAccessIsStateless() throws IOException, SAXException {
+
+ // -------------------- Request 1 ---------------------------
+
+ // Accessing protected page without login
+ String response = getFromServerPath("protected/servlet");
+
+ // Not logged-in thus should not be accessible.
+ assertFalse(response.contains("This is a protected servlet"));
+
+ // -------------------- Request 2 ---------------------------
+
+ // JASPIC is stateless and login (re-authenticate) has to happen for every request
+ //
+ // If the following fails but "testProtectedPageLoggedin" has succeeded,
+ // the container has probably remembered the "unauthenticated identity", e.g. it has remembered that
+ // we're not authenticated and it will deny further attempts to authenticate. This may happen when
+ // the container does not correctly recognize the JASPIC protocol for "do nothing".
+
+ response = getFromServerPath("protected/servlet?doLogin=true");
+
+ // Now has to be logged-in so page is accessible
+ assertTrue("Could not access protected page, but should be able to. "
+ + "Did the container remember the previously set 'unauthenticated identity'?",
+ response.contains("This is a protected servlet"));
+
+ // -------------------- Request 3 ---------------------------
+
+ // JASPIC is stateless and login (re-authenticate) has to happen for every request
+ //
+ // In the following method we do a call without logging in after one where we did login.
+ // The container should not remember this login and has to deny access.
+ response = getFromServerPath("protected/servlet");
+
+ // Not logged-in thus should not be accessible.
+ assertFalse("Could access protected page, but should not be able to. "
+ + "Did the container remember the authenticated identity that was set in previous request?",
+ response.contains("This is a protected servlet"));
+ }
+
+ /**
+ * Tests that access to a protected page does not depend on the authenticated identity that was established in a previous
+ * request, but use a different request order than the previous test.
+ */
+ @Test
+ public void testProtectedAccessIsStateless2() throws IOException, SAXException {
+
+ // -------------------- Request 1 ---------------------------
+
+ // Start with doing a login
+ String response = getFromServerPath("protected/servlet?doLogin=true");
+
+ // -------------------- Request 2 ---------------------------
+
+ // JASPIC is stateless and login (re-authenticate) has to happen for every request
+ //
+ // In the following method we do a call without logging in after one where we did login.
+ // The container should not remember this login and has to deny access.
+
+ // Accessing protected page without login
+ response = getFromServerPath("protected/servlet");
+
+ // Not logged-in thus should not be accessible.
+ assertFalse(
+ "Could access protected page, but should not be able to. " +
+ "Did the container remember the authenticated identity that was set in previous request?",
+ response.contains("This is a protected servlet")
+ );
+ }
+
+ @Test
+ public void testPublicAccessIsStateless() throws IOException, SAXException {
+
+ // -------------------- Request 1 ---------------------------
+
+ String response = getFromServerPath("public/servlet");
+
+ // Not logged-in
+ assertTrue(response.contains("web username: null"));
+ assertTrue(response.contains("web user has role \"architect\": false"));
+
+ // -------------------- Request 2 ---------------------------
+
+ response = getFromServerPath("public/servlet?doLogin=true");
+
+ // Now has to be logged-in
+ assertTrue(
+ "Username is not the expected one 'test'",
+ response.contains("web username: test")
+ );
+ assertTrue(
+ "Username is correct, but the expected role 'architect' is not present.",
+ response.contains("web user has role \"architect\": true")
+ );
+
+ // -------------------- Request 3 ---------------------------
+
+ response = getFromServerPath("public/servlet");
+
+ // Not logged-in
+ assertTrue(
+ "Should not be authenticated, but username was not null. Did the container remember it from previous request?",
+ response.contains("web username: null")
+ );
+ assertTrue(
+ "Request was not authenticated (username correctly null), but unauthenticated user incorrectly has role 'architect'",
+ response.contains("web user has role \"architect\": false")
+ );
+ }
+
+ /**
+ * Tests independently from being able to access a protected resource if any details of a previously established
+ * authenticated identity are remembered
+ */
+ @Test
+ public void testProtectedThenPublicAccessIsStateless() throws IOException, SAXException {
+
+ // -------------------- Request 1 ---------------------------
+
+ // Accessing protected page with login
+ String response = getFromServerPath("protected/servlet?doLogin=true");
+
+ // -------------------- Request 2 ---------------------------
+
+ // Accessing public page without login
+ response = getFromServerPath("public/servlet");
+
+ // No details should linger around
+ assertFalse(
+ "User principal was 'test', but it should be null here. " +
+ "The container seemed to have remembered it from the previous request.",
+ response.contains("web username: test")
+ );
+ assertTrue(
+ "User principal was not null, but it should be null here. ",
+ response.contains("web username: null")
+ );
+ assertTrue(
+ "The unauthenticated user has the role 'architect', which should not be the case. " +
+ "The container seemed to have remembered it from the previous request.",
+ response.contains("web user has role \"architect\": false")
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/dispatching-jsf-cdi/pom.xml b/jaspic/dispatching-jsf-cdi/pom.xml
new file mode 100644
index 000000000..c9656c95d
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/pom.xml
@@ -0,0 +1,35 @@
+
+
+ 4.0.0
+
+
+ org.javaee7
+ jaspic
+ 1.0-SNAPSHOT
+
+
+ jaspic-dispatching-jsf-cdi
+ war
+ Java EE 7 Sample: jaspic - dispatching JSF CDI
+
+
+
+ org.javaee7
+ jaspic-common
+ 1.0-SNAPSHOT
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ ${skipJSF}
+
+
+
+
+
+
diff --git a/jaspic/dispatching-jsf-cdi/src/main/java/org/javaee7/jaspic/dispatching/bean/MyBean.java b/jaspic/dispatching-jsf-cdi/src/main/java/org/javaee7/jaspic/dispatching/bean/MyBean.java
new file mode 100644
index 000000000..5d605fe0f
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/main/java/org/javaee7/jaspic/dispatching/bean/MyBean.java
@@ -0,0 +1,23 @@
+package org.javaee7.jaspic.dispatching.bean;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.servlet.http.HttpServletRequest;
+
+@Named
+@RequestScoped
+public class MyBean {
+
+ @Inject
+ private HttpServletRequest request;
+
+ public String getText() {
+ return "Called from CDI\n";
+ }
+
+ public String getServletPath() {
+ return request.getServletPath();
+ }
+
+}
diff --git a/jaspic/dispatching-jsf-cdi/src/main/java/org/javaee7/jaspic/dispatching/sam/SamAutoRegistrationListener.java b/jaspic/dispatching-jsf-cdi/src/main/java/org/javaee7/jaspic/dispatching/sam/SamAutoRegistrationListener.java
new file mode 100644
index 000000000..b0e15c5d3
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/main/java/org/javaee7/jaspic/dispatching/sam/SamAutoRegistrationListener.java
@@ -0,0 +1,22 @@
+package org.javaee7.jaspic.dispatching.sam;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.annotation.WebListener;
+
+import org.javaee7.jaspic.common.BaseServletContextListener;
+import org.javaee7.jaspic.common.JaspicUtils;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebListener
+public class SamAutoRegistrationListener extends BaseServletContextListener {
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ JaspicUtils.registerSAM(sce.getServletContext(), new TestServerAuthModule());
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/dispatching-jsf-cdi/src/main/java/org/javaee7/jaspic/dispatching/sam/TestServerAuthModule.java b/jaspic/dispatching-jsf-cdi/src/main/java/org/javaee7/jaspic/dispatching/sam/TestServerAuthModule.java
new file mode 100644
index 000000000..02154b5d7
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/main/java/org/javaee7/jaspic/dispatching/sam/TestServerAuthModule.java
@@ -0,0 +1,103 @@
+package org.javaee7.jaspic.dispatching.sam;
+
+import static javax.security.auth.message.AuthStatus.SEND_CONTINUE;
+import static javax.security.auth.message.AuthStatus.SEND_SUCCESS;
+import static javax.security.auth.message.AuthStatus.SUCCESS;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.AuthStatus;
+import javax.security.auth.message.MessageInfo;
+import javax.security.auth.message.MessagePolicy;
+import javax.security.auth.message.callback.CallerPrincipalCallback;
+import javax.security.auth.message.module.ServerAuthModule;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class TestServerAuthModule implements ServerAuthModule {
+
+ private CallbackHandler handler;
+ private Class>[] supportedMessageTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class };
+
+ @Override
+ public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler,
+ @SuppressWarnings("rawtypes") Map options) throws AuthException {
+ this.handler = handler;
+ }
+
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+
+ try {
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+ HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();
+
+ if ("include".equals(request.getParameter("dispatch"))) {
+
+ String target = "/includedServlet";
+ if ("jsf".equals(request.getParameter("tech"))) {
+ target = "/include.jsf";
+ } else if ("jsfcdi".equals(request.getParameter("tech"))) {
+ target = "/include-cdi.jsf";
+ }
+
+ request.getRequestDispatcher(target)
+ .include(request, response);
+
+ // "Do nothing", required protocol when returning SUCCESS
+ handler.handle(new Callback[] { new CallerPrincipalCallback(clientSubject, (Principal) null) });
+
+ // When using includes, the response stays open and the main
+ // resource can also
+ // write to the response
+ return SUCCESS;
+
+ } else {
+
+ String target = "/forwardedServlet";
+ if ("jsf".equals(request.getParameter("tech"))) {
+ target = "/forward.jsf";
+ } else if ("jsfcdi".equals(request.getParameter("tech"))) {
+ target = "/forward-cdi.jsf";
+ }
+
+ request.getRequestDispatcher(target)
+ .forward(request, response);
+
+ // MUST NOT invoke the resource, so CAN NOT return SUCCESS here.
+ return SEND_CONTINUE;
+ }
+
+ } catch (IOException | ServletException | UnsupportedCallbackException e) {
+ throw (AuthException) new AuthException().initCause(e);
+ }
+ }
+
+ @Override
+ public Class>[] getSupportedMessageTypes() {
+ return supportedMessageTypes;
+ }
+
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+ return SEND_SUCCESS;
+ }
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+
+ }
+}
\ No newline at end of file
diff --git a/jaspic/dispatching-jsf-cdi/src/main/java/org/javaee7/jaspic/dispatching/servlet/ForwardedServlet.java b/jaspic/dispatching-jsf-cdi/src/main/java/org/javaee7/jaspic/dispatching/servlet/ForwardedServlet.java
new file mode 100644
index 000000000..1b439076d
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/main/java/org/javaee7/jaspic/dispatching/servlet/ForwardedServlet.java
@@ -0,0 +1,43 @@
+package org.javaee7.jaspic.dispatching.servlet;
+
+import static java.util.logging.Level.SEVERE;
+
+import java.io.IOException;
+import java.util.logging.Logger;
+
+import javax.inject.Inject;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.javaee7.jaspic.dispatching.bean.MyBean;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/forwardedServlet")
+public class ForwardedServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ private final static Logger logger = Logger.getLogger(ForwardedServlet.class.getName());
+
+ @Inject
+ private MyBean myBean;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.getWriter().write("response from forwardedServlet - " + myBean.getText());
+ response.getWriter().write("servletPath via Servlet - " + request.getServletPath() + "\n");
+ try {
+ response.getWriter().write("servletPath via CDI - " + myBean.getServletPath());
+ } catch (Exception e) {
+ logger.log(SEVERE, "", e);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/dispatching-jsf-cdi/src/main/java/org/javaee7/jaspic/dispatching/servlet/IncludedServlet.java b/jaspic/dispatching-jsf-cdi/src/main/java/org/javaee7/jaspic/dispatching/servlet/IncludedServlet.java
new file mode 100644
index 000000000..a2c6ccb59
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/main/java/org/javaee7/jaspic/dispatching/servlet/IncludedServlet.java
@@ -0,0 +1,32 @@
+package org.javaee7.jaspic.dispatching.servlet;
+
+import java.io.IOException;
+
+import javax.inject.Inject;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.javaee7.jaspic.dispatching.bean.MyBean;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/includedServlet")
+public class IncludedServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Inject
+ private MyBean myBean;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.getWriter().write("response from includedServlet - " + myBean.getText());
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/dispatching-jsf-cdi/src/main/java/org/javaee7/jaspic/dispatching/servlet/ProtectedServlet.java b/jaspic/dispatching-jsf-cdi/src/main/java/org/javaee7/jaspic/dispatching/servlet/ProtectedServlet.java
new file mode 100644
index 000000000..a220bfbde
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/main/java/org/javaee7/jaspic/dispatching/servlet/ProtectedServlet.java
@@ -0,0 +1,25 @@
+package org.javaee7.jaspic.dispatching.servlet;
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/protected/servlet")
+public class ProtectedServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.getWriter().write("Resource invoked\n");
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/dispatching-jsf-cdi/src/main/java/org/javaee7/jaspic/dispatching/servlet/PublicServlet.java b/jaspic/dispatching-jsf-cdi/src/main/java/org/javaee7/jaspic/dispatching/servlet/PublicServlet.java
new file mode 100644
index 000000000..e2289822b
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/main/java/org/javaee7/jaspic/dispatching/servlet/PublicServlet.java
@@ -0,0 +1,25 @@
+package org.javaee7.jaspic.dispatching.servlet;
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/public/servlet")
+public class PublicServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.getWriter().write("Resource invoked\n");
+ }
+
+}
\ No newline at end of file
diff --git a/cdi/beanmanager/src/main/webapp/WEB-INF/beans.xml b/jaspic/dispatching-jsf-cdi/src/main/webapp/WEB-INF/beans.xml
similarity index 100%
rename from cdi/beanmanager/src/main/webapp/WEB-INF/beans.xml
rename to jaspic/dispatching-jsf-cdi/src/main/webapp/WEB-INF/beans.xml
diff --git a/jaspic/dispatching-jsf-cdi/src/main/webapp/WEB-INF/faces-config.xml b/jaspic/dispatching-jsf-cdi/src/main/webapp/WEB-INF/faces-config.xml
new file mode 100644
index 000000000..75e5888f4
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/main/webapp/WEB-INF/faces-config.xml
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file
diff --git a/jaspic/dispatching-jsf-cdi/src/main/webapp/WEB-INF/glassfish-web.xml b/jaspic/dispatching-jsf-cdi/src/main/webapp/WEB-INF/glassfish-web.xml
new file mode 100644
index 000000000..26559e3f6
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/main/webapp/WEB-INF/glassfish-web.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ architect
+ architect
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/dispatching-jsf-cdi/src/main/webapp/WEB-INF/ibm-application-bnd.xml b/jaspic/dispatching-jsf-cdi/src/main/webapp/WEB-INF/ibm-application-bnd.xml
new file mode 100644
index 000000000..9aa892cbc
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/main/webapp/WEB-INF/ibm-application-bnd.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/dispatching-jsf-cdi/src/main/webapp/WEB-INF/jboss-web.xml b/jaspic/dispatching-jsf-cdi/src/main/webapp/WEB-INF/jboss-web.xml
new file mode 100644
index 000000000..b6ab7d0ba
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/main/webapp/WEB-INF/jboss-web.xml
@@ -0,0 +1,5 @@
+
+
+
+ jaspitest
+
diff --git a/jaspic/dispatching-jsf-cdi/src/main/webapp/WEB-INF/web.xml b/jaspic/dispatching-jsf-cdi/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..ffd58ffa6
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Test
+ /protected/*
+
+
+ architect
+
+
+
+
+ architect
+
+
+
\ No newline at end of file
diff --git a/jaspic/dispatching-jsf-cdi/src/main/webapp/forward-cdi.xhtml b/jaspic/dispatching-jsf-cdi/src/main/webapp/forward-cdi.xhtml
new file mode 100644
index 000000000..9acd6c061
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/main/webapp/forward-cdi.xhtml
@@ -0,0 +1,11 @@
+
+
+
+
+ Forward with CDI
+
+
+ response from JSF forward - #{myBean.text}
+
+
diff --git a/jaspic/dispatching-jsf-cdi/src/main/webapp/forward.xhtml b/jaspic/dispatching-jsf-cdi/src/main/webapp/forward.xhtml
new file mode 100644
index 000000000..0004cbbef
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/main/webapp/forward.xhtml
@@ -0,0 +1,11 @@
+
+
+
+
+ Forward
+
+
+ response from JSF forward
+
+
diff --git a/jaspic/dispatching-jsf-cdi/src/main/webapp/include-cdi.xhtml b/jaspic/dispatching-jsf-cdi/src/main/webapp/include-cdi.xhtml
new file mode 100644
index 000000000..a2e090649
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/main/webapp/include-cdi.xhtml
@@ -0,0 +1,11 @@
+
+
+
+
+ Include with CDI
+
+
+ response from JSF include - #{myBean.text}
+
+
diff --git a/jaspic/dispatching-jsf-cdi/src/main/webapp/include.xhtml b/jaspic/dispatching-jsf-cdi/src/main/webapp/include.xhtml
new file mode 100644
index 000000000..e99418f7d
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/main/webapp/include.xhtml
@@ -0,0 +1,11 @@
+
+
+
+
+ Include
+
+
+ response from JSF include
+
+
diff --git a/jaspic/dispatching-jsf-cdi/src/test/java/org/javaee7/jaspictest/dispatching/CDIForwardTest.java b/jaspic/dispatching-jsf-cdi/src/test/java/org/javaee7/jaspictest/dispatching/CDIForwardTest.java
new file mode 100644
index 000000000..d6ba19ea5
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/test/java/org/javaee7/jaspictest/dispatching/CDIForwardTest.java
@@ -0,0 +1,156 @@
+package org.javaee7.jaspictest.dispatching;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * The basic forward test tests that a SAM is able to forward to a simple Servlet.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class CDIForwardTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return tryWrapEAR(
+ defaultWebArchive()
+ .addAsWebInfResource(resource("beans.xml"))
+ );
+ }
+
+ /**
+ * Tests that the forwarded resource can utilize a CDI bean
+ *
+ * @throws IOException
+ * @throws SAXException
+ */
+ @Test
+ public void testCDIForwardViaPublicResource() throws IOException, SAXException {
+
+ String response = getFromServerPath("public/servlet");
+ assertTrue(
+ "Response did not contain output from public Servlet with CDI that SAM forwarded to.",
+ response.contains("response from forwardedServlet - Called from CDI")
+ );
+ }
+
+ /**
+ * Tests that the forwarded resource can utilize a CDI bean
+ *
+ * @throws IOException
+ * @throws SAXException
+ */
+ @Test
+ public void testCDIForwardViaProtectedResource() throws IOException, SAXException {
+
+ String response = getFromServerPath("protected/servlet");
+ assertTrue(
+ "Response did not contain output from protected Servlet with CDI that SAM forwarded to.",
+ response.contains("response from forwardedServlet - Called from CDI")
+ );
+ }
+
+ /**
+ * Tests that the forwarded resource has the correct servlet path
+ *
+ * @throws IOException
+ * @throws SAXException
+ */
+ @Test
+ public void testCDIForwardWithRequestPublic() throws IOException, SAXException {
+
+ String response = getFromServerPath("public/servlet");
+
+ assertTrue(
+ "Servletpath reported by servlet request after forward from SAM not as expected.",
+ response.contains("servletPath via Servlet - /forwardedServlet")
+ );
+ }
+
+ /**
+ * Tests that the forwarded resource has the correct servlet path
+ *
+ * @throws IOException
+ * @throws SAXException
+ */
+ @Test
+ public void testCDIForwardWithRequestProtected() throws IOException, SAXException {
+
+ String response = getFromServerPath("protected/servlet");
+
+ assertTrue(
+ "Servletpath reported by servlet request after forward from SAM not as expected.",
+ response.contains("servletPath via Servlet - /forwardedServlet")
+ );
+ }
+
+ /**
+ * Tests that the forwarded resource can utilize an injected HttpServletRequest and that
+ * the value is correct.
+ *
+ * @throws IOException
+ * @throws SAXException
+ */
+ @Test
+ public void testCDIForwardWithRequestInjectPublic() throws IOException, SAXException {
+
+ String response = getFromServerPath("public/servlet");
+
+ assertTrue(
+ "Servletpath reported by servlet request after forward from SAM not as expected.",
+ response.contains("servletPath via Servlet - /forwardedServlet")
+ );
+
+ assertTrue(
+ "Response did not contain output from forwarded Servlet using CDI injected request. " +
+ "Request appears not to be usable.",
+ response.contains("servletPath via CDI")
+ );
+
+ assertTrue(
+ "Servletpath reported by injected request after forward from SAM not as expected.",
+ response.contains("servletPath via CDI - /forwardedServlet")
+ );
+ }
+
+ /**
+ * Tests that the forwarded resource can utilize an injected HttpServletRequest and that
+ * the value is correct.
+ *
+ * @throws IOException
+ * @throws SAXException
+ */
+ @Test
+ public void testCDIForwardWithRequestInjectProtected() throws IOException, SAXException {
+
+ String response = getFromServerPath("protected/servlet");
+
+ assertTrue(
+ "Servletpath reported by servlet request after forward from SAM not as expected.",
+ response.contains("servletPath via Servlet - /forwardedServlet")
+ );
+
+ assertTrue(
+ "Response did not contain output from forwarded Servlet using CDI injected request. " +
+ "Request appears not to be usable.",
+ response.contains("servletPath via CDI")
+ );
+
+ assertTrue(
+ "Servletpath reported by injected request after forward from SAM not as expected.",
+ response.contains("servletPath via CDI - /forwardedServlet")
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/dispatching-jsf-cdi/src/test/java/org/javaee7/jaspictest/dispatching/CDIIncludeTest.java b/jaspic/dispatching-jsf-cdi/src/test/java/org/javaee7/jaspictest/dispatching/CDIIncludeTest.java
new file mode 100644
index 000000000..523547a27
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/test/java/org/javaee7/jaspictest/dispatching/CDIIncludeTest.java
@@ -0,0 +1,50 @@
+package org.javaee7.jaspictest.dispatching;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * The basic forward test tests that a SAM is able to forward to a simple Servlet.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class CDIIncludeTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void testCDIIncludeViaPublicResource() throws IOException, SAXException {
+
+ String response = getFromServerPath("public/servlet?dispatch=include");
+
+ assertTrue(
+ "Response did not contain output from public Servlet with CDI that SAM included to.",
+ response.contains("response from includedServlet - Called from CDI")
+ );
+
+ assertTrue(
+ "Response did not contain output from target Servlet after included one.",
+ response.contains("Resource invoked")
+ );
+
+ assertTrue(
+ "Output from included Servlet with CDI and target Servlet in wrong order.",
+ response.indexOf("response from includedServlet - Called from CDI") < response.indexOf("Resource invoked")
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/dispatching-jsf-cdi/src/test/java/org/javaee7/jaspictest/dispatching/JSFCDIForwardTest.java b/jaspic/dispatching-jsf-cdi/src/test/java/org/javaee7/jaspictest/dispatching/JSFCDIForwardTest.java
new file mode 100644
index 000000000..89b4469d3
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/test/java/org/javaee7/jaspictest/dispatching/JSFCDIForwardTest.java
@@ -0,0 +1,55 @@
+package org.javaee7.jaspictest.dispatching;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * The JSF with CDI forward test tests that a SAM is able to forward to a JSF view
+ * that uses a CDI backing bean.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class JSFCDIForwardTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return tryWrapEAR(
+ defaultWebArchive()
+ .addAsWebInfResource(resource("beans.xml"))
+ .addAsWebInfResource(resource("faces-config.xml"))
+ .addAsWebResource(web("forward-cdi.xhtml"))
+ );
+ }
+
+ @Test
+ public void testJSFwithCDIForwardViaPublicResource() throws IOException, SAXException {
+
+ String response = getFromServerPath("public/servlet?tech=jsfcdi");
+ assertTrue(
+ "Response did not contain output from JSF view with CDI that SAM forwarded to.",
+ response.contains("response from JSF forward - Called from CDI")
+ );
+ }
+
+ @Test
+ public void testJSFwithCDIForwardViaProtectedResource() throws IOException, SAXException {
+
+ String response = getFromServerPath("protected/servlet?tech=jsfcdi");
+ assertTrue(
+ "Response did not contain output from JSF view with CDI that SAM forwarded to.",
+ response.contains("response from JSF forward - Called from CDI")
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/dispatching-jsf-cdi/src/test/java/org/javaee7/jaspictest/dispatching/JSFCDIIncludeTest.java b/jaspic/dispatching-jsf-cdi/src/test/java/org/javaee7/jaspictest/dispatching/JSFCDIIncludeTest.java
new file mode 100644
index 000000000..687184e3b
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/test/java/org/javaee7/jaspictest/dispatching/JSFCDIIncludeTest.java
@@ -0,0 +1,58 @@
+package org.javaee7.jaspictest.dispatching;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * The JSF with CDI forward test tests that a SAM is able to include a JSF view
+ * that uses a CDI backing bean.
+ *
+ * Excluded for now as it fails, but the failure is not JASPIC related
+ *
+ * @author Arjan Tijms
+ *
+ */
+//@RunWith(Arquillian.class)
+public class JSFCDIIncludeTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return tryWrapEAR(
+ defaultWebArchive()
+ .addAsWebInfResource(resource("beans.xml"))
+ .addAsWebInfResource(resource("faces-config.xml"))
+ .addAsWebResource(web("include-cdi.xhtml"))
+ );
+ }
+
+ //@Test
+ public void testJSFwithCDIIncludeViaPublicResource() throws IOException, SAXException {
+
+ String response = getFromServerPath("public/servlet?dispatch=include&tech=jsfcdi");
+
+ assertTrue(
+ "Response did not contain output from JSF view that SAM included.",
+ response.contains("response from JSF include - Called from CDI")
+ );
+
+ assertTrue(
+ "Response did not contain output from target Servlet after included JSF view.",
+ response.contains("Resource invoked")
+ );
+
+ assertTrue(
+ "Output from included JSF view and target Servlet in wrong order.",
+ response.indexOf("response from JSF include - Called from CDI") < response.indexOf("Resource invoked")
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/dispatching-jsf-cdi/src/test/java/org/javaee7/jaspictest/dispatching/JSFForwardTest.java b/jaspic/dispatching-jsf-cdi/src/test/java/org/javaee7/jaspictest/dispatching/JSFForwardTest.java
new file mode 100644
index 000000000..639bdc138
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/test/java/org/javaee7/jaspictest/dispatching/JSFForwardTest.java
@@ -0,0 +1,53 @@
+package org.javaee7.jaspictest.dispatching;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * The JSF with CDI forward test tests that a SAM is able to forward to a plain JSF view.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class JSFForwardTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return tryWrapEAR(
+ defaultWebArchive()
+ .addAsWebInfResource(resource("faces-config.xml"))
+ .addAsWebResource(web("forward.xhtml"))
+ );
+ }
+
+ @Test
+ public void testJSFForwardViaPublicResource() throws IOException, SAXException {
+
+ String response = getFromServerPath("public/servlet?tech=jsf");
+ assertTrue(
+ "Response did not contain output from JSF view that SAM forwarded to.",
+ response.contains("response from JSF forward")
+ );
+ }
+
+ @Test
+ public void testJSFForwardViaProtectedResource() throws IOException, SAXException {
+
+ String response = getFromServerPath("protected/servlet?tech=jsf");
+ assertTrue(
+ "Response did not contain output from JSF view that SAM forwarded to.",
+ response.contains("response from JSF forward")
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/dispatching-jsf-cdi/src/test/java/org/javaee7/jaspictest/dispatching/JSFIncludeTest.java b/jaspic/dispatching-jsf-cdi/src/test/java/org/javaee7/jaspictest/dispatching/JSFIncludeTest.java
new file mode 100644
index 000000000..0bb45f2fc
--- /dev/null
+++ b/jaspic/dispatching-jsf-cdi/src/test/java/org/javaee7/jaspictest/dispatching/JSFIncludeTest.java
@@ -0,0 +1,56 @@
+package org.javaee7.jaspictest.dispatching;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * The JSF with CDI forward test tests that a SAM is able to include a plain JSF view.
+ *
+ * Excluded for now as it fails, but the failure is not JASPIC related
+ *
+ * @author Arjan Tijms
+ *
+ */
+//@RunWith(Arquillian.class)
+public class JSFIncludeTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return tryWrapEAR(
+ defaultWebArchive()
+ .addAsWebInfResource(resource("faces-config.xml"))
+ .addAsWebResource(web("include.xhtml"))
+ );
+ }
+
+ //@Test
+ public void testJSFIncludeViaPublicResource() throws IOException, SAXException {
+
+ String response = getFromServerPath("public/servlet?dispatch=include&tech=jsf");
+
+ assertTrue(
+ "Response did not contain output from JSF view that SAM included.",
+ response.contains("response from JSF include")
+ );
+
+ assertTrue(
+ "Response did not contain output from target Servlet after included JSF view.",
+ response.contains("Resource invoked")
+ );
+
+ assertTrue(
+ "Output from included JSF view and target Servlet in wrong order.",
+ response.indexOf("response from JSF include") < response.indexOf("Resource invoked")
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/dispatching/pom.xml b/jaspic/dispatching/pom.xml
new file mode 100644
index 000000000..8e9917d77
--- /dev/null
+++ b/jaspic/dispatching/pom.xml
@@ -0,0 +1,24 @@
+
+
+ 4.0.0
+
+
+ org.javaee7
+ jaspic
+ 1.0-SNAPSHOT
+ ../pom.xml
+
+ org.javaee7
+ jaspic-dispatching
+ 1.0-SNAPSHOT
+ war
+ Java EE 7 Sample: jaspic - dispatching
+
+
+
+ org.javaee7
+ jaspic-common
+ 1.0-SNAPSHOT
+
+
+
diff --git a/jaspic/dispatching/src/main/java/org/javaee7/jaspic/dispatching/sam/SamAutoRegistrationListener.java b/jaspic/dispatching/src/main/java/org/javaee7/jaspic/dispatching/sam/SamAutoRegistrationListener.java
new file mode 100644
index 000000000..b0e15c5d3
--- /dev/null
+++ b/jaspic/dispatching/src/main/java/org/javaee7/jaspic/dispatching/sam/SamAutoRegistrationListener.java
@@ -0,0 +1,22 @@
+package org.javaee7.jaspic.dispatching.sam;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.annotation.WebListener;
+
+import org.javaee7.jaspic.common.BaseServletContextListener;
+import org.javaee7.jaspic.common.JaspicUtils;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebListener
+public class SamAutoRegistrationListener extends BaseServletContextListener {
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ JaspicUtils.registerSAM(sce.getServletContext(), new TestServerAuthModule());
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/dispatching/src/main/java/org/javaee7/jaspic/dispatching/sam/TestServerAuthModule.java b/jaspic/dispatching/src/main/java/org/javaee7/jaspic/dispatching/sam/TestServerAuthModule.java
new file mode 100644
index 000000000..d52159a5b
--- /dev/null
+++ b/jaspic/dispatching/src/main/java/org/javaee7/jaspic/dispatching/sam/TestServerAuthModule.java
@@ -0,0 +1,85 @@
+package org.javaee7.jaspic.dispatching.sam;
+
+import static javax.security.auth.message.AuthStatus.SEND_CONTINUE;
+import static javax.security.auth.message.AuthStatus.SEND_SUCCESS;
+import static javax.security.auth.message.AuthStatus.SUCCESS;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.AuthStatus;
+import javax.security.auth.message.MessageInfo;
+import javax.security.auth.message.MessagePolicy;
+import javax.security.auth.message.callback.CallerPrincipalCallback;
+import javax.security.auth.message.module.ServerAuthModule;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class TestServerAuthModule implements ServerAuthModule {
+
+ private CallbackHandler handler;
+ private Class>[] supportedMessageTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class };
+
+ @Override
+ public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler,
+ @SuppressWarnings("rawtypes") Map options) throws AuthException {
+ this.handler = handler;
+ }
+
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+ try {
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+ HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();
+
+ if ("include".equals(request.getParameter("dispatch"))) {
+ request.getRequestDispatcher("/includedServlet")
+ .include(request, response);
+
+ // "Do nothing", required protocol when returning SUCCESS
+ handler.handle(new Callback[] { new CallerPrincipalCallback(clientSubject, (Principal) null) });
+
+ // When using includes, the response stays open and the main
+ // resource can also write to the response
+ return SUCCESS;
+
+ } else {
+ request.getRequestDispatcher("/forwardedServlet")
+ .forward(request, response);
+
+ // MUST NOT invoke the resource, so CAN NOT return SUCCESS here.
+ return SEND_CONTINUE;
+ }
+
+ } catch (IOException | ServletException | UnsupportedCallbackException e) {
+ throw (AuthException) new AuthException().initCause(e);
+ }
+ }
+
+ @Override
+ public Class>[] getSupportedMessageTypes() {
+ return supportedMessageTypes;
+ }
+
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+ return SEND_SUCCESS;
+ }
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+
+ }
+}
\ No newline at end of file
diff --git a/jaspic/dispatching/src/main/java/org/javaee7/jaspic/dispatching/servlet/ForwardedServlet.java b/jaspic/dispatching/src/main/java/org/javaee7/jaspic/dispatching/servlet/ForwardedServlet.java
new file mode 100644
index 000000000..df5ab5301
--- /dev/null
+++ b/jaspic/dispatching/src/main/java/org/javaee7/jaspic/dispatching/servlet/ForwardedServlet.java
@@ -0,0 +1,26 @@
+package org.javaee7.jaspic.dispatching.servlet;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/forwardedServlet")
+public class ForwardedServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.getWriter().write("response from forwardedServlet");
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/dispatching/src/main/java/org/javaee7/jaspic/dispatching/servlet/IncludedServlet.java b/jaspic/dispatching/src/main/java/org/javaee7/jaspic/dispatching/servlet/IncludedServlet.java
new file mode 100644
index 000000000..2f832c7f0
--- /dev/null
+++ b/jaspic/dispatching/src/main/java/org/javaee7/jaspic/dispatching/servlet/IncludedServlet.java
@@ -0,0 +1,26 @@
+package org.javaee7.jaspic.dispatching.servlet;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/includedServlet")
+public class IncludedServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.getWriter().write("response from includedServlet");
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/dispatching/src/main/java/org/javaee7/jaspic/dispatching/servlet/ProtectedServlet.java b/jaspic/dispatching/src/main/java/org/javaee7/jaspic/dispatching/servlet/ProtectedServlet.java
new file mode 100644
index 000000000..a220bfbde
--- /dev/null
+++ b/jaspic/dispatching/src/main/java/org/javaee7/jaspic/dispatching/servlet/ProtectedServlet.java
@@ -0,0 +1,25 @@
+package org.javaee7.jaspic.dispatching.servlet;
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/protected/servlet")
+public class ProtectedServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.getWriter().write("Resource invoked\n");
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/dispatching/src/main/java/org/javaee7/jaspic/dispatching/servlet/PublicServlet.java b/jaspic/dispatching/src/main/java/org/javaee7/jaspic/dispatching/servlet/PublicServlet.java
new file mode 100644
index 000000000..e2289822b
--- /dev/null
+++ b/jaspic/dispatching/src/main/java/org/javaee7/jaspic/dispatching/servlet/PublicServlet.java
@@ -0,0 +1,25 @@
+package org.javaee7.jaspic.dispatching.servlet;
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/public/servlet")
+public class PublicServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.getWriter().write("Resource invoked\n");
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/dispatching/src/main/webapp/WEB-INF/glassfish-web.xml b/jaspic/dispatching/src/main/webapp/WEB-INF/glassfish-web.xml
new file mode 100644
index 000000000..26559e3f6
--- /dev/null
+++ b/jaspic/dispatching/src/main/webapp/WEB-INF/glassfish-web.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ architect
+ architect
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/dispatching/src/main/webapp/WEB-INF/ibm-application-bnd.xml b/jaspic/dispatching/src/main/webapp/WEB-INF/ibm-application-bnd.xml
new file mode 100644
index 000000000..9aa892cbc
--- /dev/null
+++ b/jaspic/dispatching/src/main/webapp/WEB-INF/ibm-application-bnd.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/dispatching/src/main/webapp/WEB-INF/jboss-web.xml b/jaspic/dispatching/src/main/webapp/WEB-INF/jboss-web.xml
new file mode 100644
index 000000000..b6ab7d0ba
--- /dev/null
+++ b/jaspic/dispatching/src/main/webapp/WEB-INF/jboss-web.xml
@@ -0,0 +1,5 @@
+
+
+
+ jaspitest
+
diff --git a/jaspic/dispatching/src/main/webapp/WEB-INF/web.xml b/jaspic/dispatching/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..ffd58ffa6
--- /dev/null
+++ b/jaspic/dispatching/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Test
+ /protected/*
+
+
+ architect
+
+
+
+
+ architect
+
+
+
\ No newline at end of file
diff --git a/jaspic/dispatching/src/test/java/org/javaee7/jaspic/dispatching/BasicForwardTest.java b/jaspic/dispatching/src/test/java/org/javaee7/jaspic/dispatching/BasicForwardTest.java
new file mode 100644
index 000000000..507b28f89
--- /dev/null
+++ b/jaspic/dispatching/src/test/java/org/javaee7/jaspic/dispatching/BasicForwardTest.java
@@ -0,0 +1,49 @@
+package org.javaee7.jaspic.dispatching;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * The basic forward test tests that a SAM is able to forward to a simple Servlet.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class BasicForwardTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void testBasicForwardViaPublicResource() throws IOException, SAXException {
+
+ String response = getFromServerPath("public/servlet");
+ assertTrue(
+ "Response did not contain output from public Servlet that SAM forwarded to.",
+ response.contains("response from forwardedServlet")
+ );
+ }
+
+ @Test
+ public void testBasicForwardViaProtectedResource() throws IOException, SAXException {
+
+ String response = getFromServerPath("protected/servlet");
+ assertTrue(
+ "Response did not contain output from protected Servlet that SAM forwarded to.",
+ response.contains("response from forwardedServlet")
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/dispatching/src/test/java/org/javaee7/jaspic/dispatching/BasicIncludeTest.java b/jaspic/dispatching/src/test/java/org/javaee7/jaspic/dispatching/BasicIncludeTest.java
new file mode 100644
index 000000000..3725a007f
--- /dev/null
+++ b/jaspic/dispatching/src/test/java/org/javaee7/jaspic/dispatching/BasicIncludeTest.java
@@ -0,0 +1,50 @@
+package org.javaee7.jaspic.dispatching;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * The basic include test tests that a SAM is able to include a simple Servlet.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class BasicIncludeTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void testBasicIncludeViaPublicResource() throws IOException, SAXException {
+
+ String response = getFromServerPath("public/servlet?dispatch=include");
+
+ assertTrue(
+ "Response did not contain output from public Servlet that SAM included to.",
+ response.contains("response from includedServlet")
+ );
+
+ assertTrue(
+ "Response did not contain output from target Servlet after included one.",
+ response.contains("Resource invoked")
+ );
+
+ assertTrue(
+ "Output from included Servler and target Servlet in wrong order.",
+ response.indexOf("response from includedServlet") < response.indexOf("Resource invoked")
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/ejb-propagation/pom.xml b/jaspic/ejb-propagation/pom.xml
new file mode 100644
index 000000000..6a6bf0774
--- /dev/null
+++ b/jaspic/ejb-propagation/pom.xml
@@ -0,0 +1,35 @@
+
+
+ 4.0.0
+
+
+ org.javaee7
+ jaspic
+ 1.0-SNAPSHOT
+
+
+ jaspic-ejb-propagation
+ war
+ Java EE 7 Sample: jaspic - ejb-propagation
+
+
+
+ org.javaee7
+ jaspic-common
+ 1.0-SNAPSHOT
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ ${skipEJB}
+
+
+
+
+
+
diff --git a/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/ejb/ProtectedEJB.java b/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/ejb/ProtectedEJB.java
new file mode 100644
index 000000000..c3ab52725
--- /dev/null
+++ b/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/ejb/ProtectedEJB.java
@@ -0,0 +1,51 @@
+package org.javaee7.jaspic.ejbpropagation.ejb;
+
+import javax.annotation.Resource;
+import javax.annotation.security.DeclareRoles;
+import javax.annotation.security.PermitAll;
+import javax.annotation.security.RolesAllowed;
+import javax.ejb.EJBContext;
+import javax.ejb.Stateless;
+
+/**
+ * This is a "protected" EJB in the sense that there is role checking done prior to accessing (some) methods.
+ *
+ * In JBoss EAP 6.1+ the use of any declarative security annotation switches the bean to a different mode, called "secured" in
+ * JBoss terms.
+ *
+ * GlassFish requires the @DeclareRoles annotation when programmatic role checking is done (making dynamic role
+ * checking impossible).
+ *
+ * @author Arjan Tijms
+ */
+@Stateless
+//Required by GlassFish
+@DeclareRoles({ "architect" })
+//JBoss EAP 6.1+ defaults unchecked methods to DenyAll
+@PermitAll
+public class ProtectedEJB {
+
+ @Resource
+ private EJBContext ejbContext;
+
+ @RolesAllowed("architect")
+ public String getUserName() {
+ try {
+ return ejbContext.getCallerPrincipal() != null ? ejbContext.getCallerPrincipal().getName() : null;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public boolean isUserArchitect() {
+ try {
+ return ejbContext.isCallerInRole("architect");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return false;
+
+ }
+
+}
diff --git a/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/ejb/PublicEJB.java b/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/ejb/PublicEJB.java
new file mode 100644
index 000000000..9d8289f01
--- /dev/null
+++ b/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/ejb/PublicEJB.java
@@ -0,0 +1,28 @@
+package org.javaee7.jaspic.ejbpropagation.ejb;
+
+import javax.annotation.Resource;
+import javax.ejb.EJBContext;
+import javax.ejb.Stateless;
+
+/**
+ * This is a "public" EJB in the sense that all its methods should be accessible and there is no declarative role checking prior
+ * to accessing a method.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@Stateless
+public class PublicEJB {
+
+ @Resource
+ private EJBContext ejbContext;
+
+ public String getUserName() {
+ try {
+ return ejbContext.getCallerPrincipal() != null ? ejbContext.getCallerPrincipal().getName() : null;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+}
diff --git a/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/sam/SamAutoRegistrationListener.java b/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/sam/SamAutoRegistrationListener.java
new file mode 100644
index 000000000..e91dd3576
--- /dev/null
+++ b/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/sam/SamAutoRegistrationListener.java
@@ -0,0 +1,22 @@
+package org.javaee7.jaspic.ejbpropagation.sam;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.annotation.WebListener;
+
+import org.javaee7.jaspic.common.BaseServletContextListener;
+import org.javaee7.jaspic.common.JaspicUtils;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebListener
+public class SamAutoRegistrationListener extends BaseServletContextListener {
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ JaspicUtils.registerSAM(sce.getServletContext(), new TestServerAuthModule());
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/sam/TestServerAuthModule.java b/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/sam/TestServerAuthModule.java
new file mode 100644
index 000000000..a11992455
--- /dev/null
+++ b/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/sam/TestServerAuthModule.java
@@ -0,0 +1,82 @@
+package org.javaee7.jaspic.ejbpropagation.sam;
+
+import static javax.security.auth.message.AuthStatus.SUCCESS;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.AuthStatus;
+import javax.security.auth.message.MessageInfo;
+import javax.security.auth.message.MessagePolicy;
+import javax.security.auth.message.callback.CallerPrincipalCallback;
+import javax.security.auth.message.callback.GroupPrincipalCallback;
+import javax.security.auth.message.module.ServerAuthModule;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Very basic SAM that returns a single hardcoded user named "test" with role "architect" when the request parameter
+ * doLogin is present.
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class TestServerAuthModule implements ServerAuthModule {
+
+ private CallbackHandler handler;
+ private Class>[] supportedMessageTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class };
+
+ @Override
+ public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler,
+ @SuppressWarnings("rawtypes") Map options) throws AuthException {
+ this.handler = handler;
+ }
+
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject)
+ throws AuthException {
+
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+
+ Callback[] callbacks;
+
+ if (request.getParameter("doLogin") != null) {
+
+ callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, "test"),
+ new GroupPrincipalCallback(clientSubject, new String[] { "architect" }) };
+ } else {
+
+ // The JASPIC protocol for "do nothing"
+ callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, (Principal) null) };
+ }
+
+ try {
+ handler.handle(callbacks);
+ } catch (IOException | UnsupportedCallbackException e) {
+ throw (AuthException) new AuthException().initCause(e);
+ }
+
+ return SUCCESS;
+ }
+
+ @Override
+ public Class>[] getSupportedMessageTypes() {
+ return supportedMessageTypes;
+ }
+
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+ return AuthStatus.SEND_SUCCESS;
+ }
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+
+ }
+}
\ No newline at end of file
diff --git a/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/servlet/ProtectedServletProtectedEJB.java b/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/servlet/ProtectedServletProtectedEJB.java
new file mode 100644
index 000000000..1607b6fe0
--- /dev/null
+++ b/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/servlet/ProtectedServletProtectedEJB.java
@@ -0,0 +1,63 @@
+package org.javaee7.jaspic.ejbpropagation.servlet;
+
+import static java.util.logging.Level.SEVERE;
+
+import java.io.IOException;
+import java.util.logging.Logger;
+
+import javax.ejb.EJB;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.javaee7.jaspic.ejbpropagation.ejb.ProtectedEJB;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/protected/servlet-protected-ejb")
+public class ProtectedServletProtectedEJB extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+ private final static Logger logger = Logger.getLogger(ProtectedServletProtectedEJB.class.getName());
+
+ @EJB
+ private ProtectedEJB protectedEJB;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ String webName = null;
+ if (request.getUserPrincipal() != null) {
+ webName = request.getUserPrincipal().getName();
+ }
+
+ String ejbName = "";
+ try {
+ ejbName = protectedEJB.getUserName();
+ } catch (Exception e) {
+ logger.log(SEVERE, "", e);
+ }
+
+ response.getWriter().write("web username: " + webName + "\n" + "EJB username: " + ejbName + "\n");
+
+ boolean webHasRole = request.isUserInRole("architect");
+
+ boolean ejbHasRole = false;
+ try {
+ ejbHasRole = protectedEJB.isUserArchitect();
+ } catch (Exception e) {
+ logger.log(SEVERE, "", e);
+ }
+
+ response.getWriter().write(
+ "web user has role \"architect\": " + webHasRole + "\n" + "EJB user has role \"architect\": " + ejbHasRole
+ + "\n");
+
+ }
+
+}
diff --git a/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/servlet/ProtectedServletPublicEJB.java b/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/servlet/ProtectedServletPublicEJB.java
new file mode 100644
index 000000000..44fa661d1
--- /dev/null
+++ b/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/servlet/ProtectedServletPublicEJB.java
@@ -0,0 +1,50 @@
+package org.javaee7.jaspic.ejbpropagation.servlet;
+
+import static java.util.logging.Level.SEVERE;
+
+import java.io.IOException;
+import java.util.logging.Logger;
+
+import javax.ejb.EJB;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.javaee7.jaspic.ejbpropagation.ejb.PublicEJB;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/protected/servlet-public-ejb")
+public class ProtectedServletPublicEJB extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+ private final static Logger logger = Logger.getLogger(ProtectedServletPublicEJB.class.getName());
+
+ @EJB
+ private PublicEJB publicEJB;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ String webName = null;
+ if (request.getUserPrincipal() != null) {
+ webName = request.getUserPrincipal().getName();
+ }
+
+ String ejbName = publicEJB.getUserName();
+ try {
+ ejbName = publicEJB.getUserName();
+ } catch (Exception e) {
+ logger.log(SEVERE, "", e);
+ }
+
+ response.getWriter().write("web username: " + webName + "\n" + "EJB username: " + ejbName + "\n");
+
+ }
+
+}
diff --git a/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/servlet/PublicServletProtectedEJB.java b/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/servlet/PublicServletProtectedEJB.java
new file mode 100644
index 000000000..9069dc044
--- /dev/null
+++ b/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/servlet/PublicServletProtectedEJB.java
@@ -0,0 +1,63 @@
+package org.javaee7.jaspic.ejbpropagation.servlet;
+
+import static java.util.logging.Level.SEVERE;
+
+import java.io.IOException;
+import java.util.logging.Logger;
+
+import javax.ejb.EJB;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.javaee7.jaspic.ejbpropagation.ejb.ProtectedEJB;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/public/servlet-protected-ejb")
+public class PublicServletProtectedEJB extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+ private final static Logger logger = Logger.getLogger(PublicServletProtectedEJB.class.getName());
+
+ @EJB
+ private ProtectedEJB protectedEJB;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ String webName = null;
+ if (request.getUserPrincipal() != null) {
+ webName = request.getUserPrincipal().getName();
+ }
+
+ String ejbName = "";
+ try {
+ ejbName = protectedEJB.getUserName();
+ } catch (Exception e) {
+ logger.log(SEVERE, "", e);
+ }
+
+ response.getWriter().write("web username: " + webName + "\n" + "EJB username: " + ejbName + "\n");
+
+ boolean webHasRole = request.isUserInRole("architect");
+
+ boolean ejbHasRole = false;
+ try {
+ ejbHasRole = protectedEJB.isUserArchitect();
+ } catch (Exception e) {
+ logger.log(SEVERE, "", e);
+ }
+
+ response.getWriter().write(
+ "web user has role \"architect\": " + webHasRole + "\n" + "EJB user has role \"architect\": " + ejbHasRole
+ + "\n");
+
+ }
+
+}
diff --git a/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/servlet/PublicServletPublicEJB.java b/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/servlet/PublicServletPublicEJB.java
new file mode 100644
index 000000000..7b944bcec
--- /dev/null
+++ b/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/servlet/PublicServletPublicEJB.java
@@ -0,0 +1,50 @@
+package org.javaee7.jaspic.ejbpropagation.servlet;
+
+import static java.util.logging.Level.SEVERE;
+
+import java.io.IOException;
+import java.util.logging.Logger;
+
+import javax.ejb.EJB;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.javaee7.jaspic.ejbpropagation.ejb.PublicEJB;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/public/servlet-public-ejb")
+public class PublicServletPublicEJB extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+ private final static Logger logger = Logger.getLogger(PublicServletPublicEJB.class.getName());
+
+ @EJB
+ private PublicEJB publicEJB;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ String webName = null;
+ if (request.getUserPrincipal() != null) {
+ webName = request.getUserPrincipal().getName();
+ }
+
+ String ejbName = "";
+ try {
+ ejbName = publicEJB.getUserName();
+ } catch (Exception e) {
+ logger.log(SEVERE, "", e);
+ }
+
+ response.getWriter().write("web username: " + webName + "\n" + "EJB username: " + ejbName + "\n");
+
+ }
+
+}
diff --git a/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/servlet/PublicServletPublicEJBLogout.java b/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/servlet/PublicServletPublicEJBLogout.java
new file mode 100644
index 000000000..453d094f2
--- /dev/null
+++ b/jaspic/ejb-propagation/src/main/java/org/javaee7/jaspic/ejbpropagation/servlet/PublicServletPublicEJBLogout.java
@@ -0,0 +1,70 @@
+package org.javaee7.jaspic.ejbpropagation.servlet;
+
+import static java.util.logging.Level.SEVERE;
+
+import java.io.IOException;
+import java.util.logging.Logger;
+
+import javax.ejb.EJB;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.javaee7.jaspic.ejbpropagation.ejb.PublicEJB;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/public/servlet-public-ejb-logout")
+public class PublicServletPublicEJBLogout extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+ private final static Logger logger = Logger.getLogger(PublicServletPublicEJBLogout.class.getName());
+
+ @EJB
+ private PublicEJB publicEJB;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ String webName = null;
+ if (request.getUserPrincipal() != null) {
+ webName = request.getUserPrincipal().getName();
+ }
+
+ String ejbName = "";
+ try {
+ ejbName = publicEJB.getUserName();
+ } catch (Exception e) {
+ logger.log(SEVERE, "", e);
+ }
+
+ request.logout();
+ HttpSession session = request.getSession(false);
+ if (session != null) {
+ session.invalidate();
+ }
+
+ String webNameAfterLogout = null;
+ if (request.getUserPrincipal() != null) {
+ webNameAfterLogout = request.getUserPrincipal().getName();
+ }
+
+ String ejbNameAfterLogout = "";
+ try {
+ ejbNameAfterLogout = publicEJB.getUserName();
+ } catch (Exception e) {
+ logger.log(SEVERE, "", e);
+ }
+
+ response.getWriter().write("web username: " + webName + "\n" + "EJB username: " + ejbName + "\n");
+ response.getWriter().write("web username after logout: " + webNameAfterLogout + "\n" + "EJB username after logout: " + ejbNameAfterLogout + "\n");
+
+ }
+
+}
diff --git a/jaspic/ejb-propagation/src/main/webapp/WEB-INF/glassfish-web.xml b/jaspic/ejb-propagation/src/main/webapp/WEB-INF/glassfish-web.xml
new file mode 100644
index 000000000..26559e3f6
--- /dev/null
+++ b/jaspic/ejb-propagation/src/main/webapp/WEB-INF/glassfish-web.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ architect
+ architect
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/ejb-propagation/src/main/webapp/WEB-INF/ibm-application-bnd.xml b/jaspic/ejb-propagation/src/main/webapp/WEB-INF/ibm-application-bnd.xml
new file mode 100644
index 000000000..9aa892cbc
--- /dev/null
+++ b/jaspic/ejb-propagation/src/main/webapp/WEB-INF/ibm-application-bnd.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/ejb-propagation/src/main/webapp/WEB-INF/jboss-web.xml b/jaspic/ejb-propagation/src/main/webapp/WEB-INF/jboss-web.xml
new file mode 100644
index 000000000..b6ab7d0ba
--- /dev/null
+++ b/jaspic/ejb-propagation/src/main/webapp/WEB-INF/jboss-web.xml
@@ -0,0 +1,5 @@
+
+
+
+ jaspitest
+
diff --git a/jaspic/ejb-propagation/src/main/webapp/WEB-INF/web.xml b/jaspic/ejb-propagation/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..ffd58ffa6
--- /dev/null
+++ b/jaspic/ejb-propagation/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Test
+ /protected/*
+
+
+ architect
+
+
+
+
+ architect
+
+
+
\ No newline at end of file
diff --git a/jaspic/ejb-propagation/src/test/java/org/javaee7/jaspic/ejbpropagation/ProtectedEJBPropagationTest.java b/jaspic/ejb-propagation/src/test/java/org/javaee7/jaspic/ejbpropagation/ProtectedEJBPropagationTest.java
new file mode 100644
index 000000000..ea2501fb7
--- /dev/null
+++ b/jaspic/ejb-propagation/src/test/java/org/javaee7/jaspic/ejbpropagation/ProtectedEJBPropagationTest.java
@@ -0,0 +1,83 @@
+package org.javaee7.jaspic.ejbpropagation;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * This tests that the established authenticated identity propagates correctly from the web layer to a "protected" EJB (an EJB
+ * with declarative role checking).
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class ProtectedEJBPropagationTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void protectedServletCallingProtectedEJB() throws IOException, SAXException {
+
+ String response = getFromServerPath("protected/servlet-protected-ejb?doLogin=true");
+
+ // Both the web (HttpServletRequest) and EJB (EJBContext) should see the same
+ // user name.
+ assertTrue(
+ "User should have been authenticated in the web layer and given name \"test\", " +
+ " but does not appear to have this name",
+ response.contains("web username: test")
+ );
+ assertTrue(
+ "Web has user principal set, but EJB not.",
+ response.contains("EJB username: test")
+ );
+
+ // Both the web (HttpServletRequest) and EJB (EJBContext) should see that the
+ // user has the role "architect".
+ assertTrue(response.contains("web user has role \"architect\": true"));
+ assertTrue("Web user principal has role \"architect\", but one in EJB doesn't.",
+ response.contains("EJB user has role \"architect\": true"));
+ }
+
+ /**
+ * A small variation on the testProtectedServletWithLoginCallingEJB that tests if for authentication that happened for
+ * public resources the security context also propagates to EJB.
+ *
+ */
+ @Test
+ public void publicServletCallingProtectedEJB() throws IOException, SAXException {
+
+ String response = getFromServerPath("public/servlet-protected-ejb?doLogin=true");
+
+ // Both the web (HttpServletRequest) and EJB (EJBContext) should see the same
+ // user name.
+ assertTrue(
+ "User should have been authenticated in the web layer and given name \"test\", " +
+ " but does not appear to have this name",
+ response.contains("web username: test")
+ );
+ assertTrue(
+ "Web has user principal set, but EJB not.",
+ response.contains("EJB username: test")
+ );
+
+ // Both the web (HttpServletRequest) and EJB (EJBContext) should see that the
+ // user has the role "architect".
+ assertTrue(response.contains("web user has role \"architect\": true"));
+ assertTrue("Web user principal has role \"architect\", but one in EJB doesn't.",
+ response.contains("EJB user has role \"architect\": true"));
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/ejb-propagation/src/test/java/org/javaee7/jaspic/ejbpropagation/PublicEJBPropagationLogoutTest.java b/jaspic/ejb-propagation/src/test/java/org/javaee7/jaspic/ejbpropagation/PublicEJBPropagationLogoutTest.java
new file mode 100644
index 000000000..dbe451b60
--- /dev/null
+++ b/jaspic/ejb-propagation/src/test/java/org/javaee7/jaspic/ejbpropagation/PublicEJBPropagationLogoutTest.java
@@ -0,0 +1,65 @@
+package org.javaee7.jaspic.ejbpropagation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * This tests that the established authenticated identity propagates correctly
+ * from the web layer to a "public" EJB (an EJB without declarative role
+ * checking) and that after logging out but still within the same request this
+ * identity is cleared.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class PublicEJBPropagationLogoutTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void publicServletCallingPublicEJBThenLogout() {
+
+ String response = getFromServerPath("public/servlet-public-ejb-logout?doLogin=true");
+
+ System.out.println(response);
+
+ // Both the web (HttpServletRequest) and EJB (EJBContext) should see the
+ // same user name.
+
+ assertTrue(
+ "User should have been authenticated in the web layer and given name \"test\", " +
+ " but does not appear to have this name",
+ response.contains("web username: test")
+ );
+ assertTrue(
+ "Web has user principal set, but EJB not.",
+ response.contains("EJB username: test")
+ );
+
+
+ // After logging out, both the web and EJB should no longer see the user
+ // name
+
+ assertFalse(
+ "Web module did not clear authenticated identity after logout",
+ response.contains("web username after logout: test")
+ );
+ assertFalse(
+ "EJB did not clear authenticated identity after logout",
+ response.contains("EJB username after logout: test")
+ );
+
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/ejb-propagation/src/test/java/org/javaee7/jaspic/ejbpropagation/PublicEJBPropagationTest.java b/jaspic/ejb-propagation/src/test/java/org/javaee7/jaspic/ejbpropagation/PublicEJBPropagationTest.java
new file mode 100644
index 000000000..0868f06a3
--- /dev/null
+++ b/jaspic/ejb-propagation/src/test/java/org/javaee7/jaspic/ejbpropagation/PublicEJBPropagationTest.java
@@ -0,0 +1,45 @@
+package org.javaee7.jaspic.ejbpropagation;
+
+import static org.junit.Assert.assertTrue;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * This tests that the established authenticated identity propagates correctly from the web layer to a "public" EJB (an EJB
+ * without declarative role checking).
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class PublicEJBPropagationTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void protectedServletCallingPublicEJB() {
+
+ String response = getFromServerPath("protected/servlet-public-ejb?doLogin=true");
+
+ // Both the web (HttpServletRequest) and EJB (EJBContext) should see the same
+ // user name.
+ assertTrue(
+ "User should have been authenticated in the web layer and given name \"test\", " +
+ " but does not appear to have this name",
+ response.contains("web username: test")
+ );
+ assertTrue(
+ "Web has user principal set, but EJB not.",
+ response.contains("EJB username: test")
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/ejb-register-session/pom.xml b/jaspic/ejb-register-session/pom.xml
new file mode 100644
index 000000000..fb23ef646
--- /dev/null
+++ b/jaspic/ejb-register-session/pom.xml
@@ -0,0 +1,36 @@
+
+
+ 4.0.0
+
+
+ org.javaee7
+ jaspic
+ 1.0-SNAPSHOT
+
+
+ jaspic-ejb-register-session
+ war
+
+ Java EE 7 Sample: jaspic - ejb-register-session
+
+
+
+ org.javaee7
+ jaspic-common
+ 1.0-SNAPSHOT
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ ${skipEJB}
+
+
+
+
+
+
diff --git a/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/ejb/ProtectedEJB.java b/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/ejb/ProtectedEJB.java
new file mode 100644
index 000000000..d02edd32c
--- /dev/null
+++ b/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/ejb/ProtectedEJB.java
@@ -0,0 +1,51 @@
+package org.javaee7.jaspic.registersession.ejb;
+
+import javax.annotation.Resource;
+import javax.annotation.security.DeclareRoles;
+import javax.annotation.security.PermitAll;
+import javax.annotation.security.RolesAllowed;
+import javax.ejb.EJBContext;
+import javax.ejb.Stateless;
+
+/**
+ * This is a "protected" EJB in the sense that there is role checking done prior to accessing (some) methods.
+ *
+ * In JBoss EAP 6.1+ the use of any declarative security annotation switches the bean to a different mode, called "secured" in
+ * JBoss terms.
+ *
+ * GlassFish requires the @DeclareRoles annotation when programmatic role checking is done (making dynamic role
+ * checking impossible).
+ *
+ * @author Arjan Tijms
+ */
+@Stateless
+//Required by GlassFish
+@DeclareRoles({ "architect" })
+//JBoss EAP 6.1+ defaults unchecked methods to DenyAll
+@PermitAll
+public class ProtectedEJB {
+
+ @Resource
+ private EJBContext ejbContext;
+
+ @RolesAllowed("architect")
+ public String getUserName() {
+ try {
+ return ejbContext.getCallerPrincipal() != null ? ejbContext.getCallerPrincipal().getName() : null;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public boolean isUserArchitect() {
+ try {
+ return ejbContext.isCallerInRole("architect");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return false;
+
+ }
+
+}
diff --git a/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/ejb/PublicEJB.java b/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/ejb/PublicEJB.java
new file mode 100644
index 000000000..3eea81834
--- /dev/null
+++ b/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/ejb/PublicEJB.java
@@ -0,0 +1,27 @@
+package org.javaee7.jaspic.registersession.ejb;
+import javax.annotation.Resource;
+import javax.ejb.EJBContext;
+import javax.ejb.Stateless;
+
+/**
+ * This is a "public" EJB in the sense that all its methods should be accessible and there is no declarative role checking prior
+ * to accessing a method.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@Stateless
+public class PublicEJB {
+
+ @Resource
+ private EJBContext ejbContext;
+
+ public String getUserName() {
+ try {
+ return ejbContext.getCallerPrincipal() != null ? ejbContext.getCallerPrincipal().getName() : null;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/sam/MyPrincipal.java b/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/sam/MyPrincipal.java
new file mode 100644
index 000000000..6cb47c75b
--- /dev/null
+++ b/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/sam/MyPrincipal.java
@@ -0,0 +1,23 @@
+package org.javaee7.jaspic.registersession.sam;
+
+import java.security.Principal;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class MyPrincipal implements Principal {
+
+ private final String name;
+
+ public MyPrincipal(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+}
diff --git a/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/sam/SamAutoRegistrationListener.java b/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/sam/SamAutoRegistrationListener.java
new file mode 100644
index 000000000..2241d934c
--- /dev/null
+++ b/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/sam/SamAutoRegistrationListener.java
@@ -0,0 +1,22 @@
+package org.javaee7.jaspic.registersession.sam;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.annotation.WebListener;
+
+import org.javaee7.jaspic.common.BaseServletContextListener;
+import org.javaee7.jaspic.common.JaspicUtils;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebListener
+public class SamAutoRegistrationListener extends BaseServletContextListener {
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ JaspicUtils.registerSAM(sce.getServletContext(), new TestServerAuthModule());
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/sam/TestServerAuthModule.java b/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/sam/TestServerAuthModule.java
new file mode 100644
index 000000000..89ea01287
--- /dev/null
+++ b/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/sam/TestServerAuthModule.java
@@ -0,0 +1,116 @@
+package org.javaee7.jaspic.registersession.sam;
+
+import static java.lang.Boolean.TRUE;
+import static javax.security.auth.message.AuthStatus.SUCCESS;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.AuthStatus;
+import javax.security.auth.message.MessageInfo;
+import javax.security.auth.message.MessagePolicy;
+import javax.security.auth.message.callback.CallerPrincipalCallback;
+import javax.security.auth.message.callback.GroupPrincipalCallback;
+import javax.security.auth.message.module.ServerAuthModule;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class TestServerAuthModule implements ServerAuthModule {
+
+ private CallbackHandler handler;
+ private Class>[] supportedMessageTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class };
+
+ @Override
+ public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler,
+ @SuppressWarnings("rawtypes") Map options) throws AuthException {
+ this.handler = handler;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject)
+ throws AuthException {
+
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+ Callback[] callbacks;
+
+ Principal userPrincipal = request.getUserPrincipal();
+ if (userPrincipal != null && request.getParameter("continueSession") != null) {
+
+ // ### If already authenticated before, continue this session
+
+ // Execute protocol to signal container registered authentication session be used.
+ callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, userPrincipal) };
+
+ } else if (request.getParameter("doLogin") != null) {
+
+ // ### If not authenticated before, do a new login if so requested
+
+ // For the test perform a login by directly "returning" the details of the authenticated user.
+ // Normally credentials would be checked and the details fetched from some repository
+
+ callbacks = new Callback[] {
+ // The name of the authenticated user
+
+ request.getParameter("customPrincipal") == null?
+ // Name based Callback
+ new CallerPrincipalCallback(clientSubject, "test") :
+
+ // Custom principal based Callback
+ new CallerPrincipalCallback(clientSubject, new MyPrincipal("test")),
+
+
+ // the roles of the authenticated user
+ new GroupPrincipalCallback(clientSubject, new String[] { "architect" }) };
+
+ // Tell container to register an authentication session.
+ messageInfo.getMap().put("javax.servlet.http.registerSession", TRUE.toString());
+ } else {
+
+ // ### If no registered session and no login request "do nothing"
+
+ // The JASPIC protocol for "do nothing"
+ callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, (Principal) null) };
+ }
+
+ try {
+
+ // Communicate the details of the authenticated user to the container. In many
+ // cases the handler will just store the details and the container will actually handle
+ // the login after we return from this method.
+ handler.handle(callbacks);
+
+ } catch (IOException | UnsupportedCallbackException e) {
+ throw (AuthException) new AuthException().initCause(e);
+ }
+
+ return SUCCESS;
+ }
+
+ @Override
+ public Class>[] getSupportedMessageTypes() {
+ return supportedMessageTypes;
+ }
+
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+ return AuthStatus.SEND_SUCCESS;
+ }
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+
+ }
+}
\ No newline at end of file
diff --git a/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/servlet/ProtectedServlet.java b/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/servlet/ProtectedServlet.java
new file mode 100644
index 000000000..9b5c06774
--- /dev/null
+++ b/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/servlet/ProtectedServlet.java
@@ -0,0 +1,46 @@
+package org.javaee7.jaspic.registersession.servlet;
+
+import java.io.IOException;
+import java.security.Principal;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.javaee7.jaspic.registersession.sam.MyPrincipal;
+
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/protected/servlet")
+public class ProtectedServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ response.getWriter().write("This is a protected servlet \n");
+
+ String webName = null;
+ boolean isCustomPrincipal = false;
+ if (request.getUserPrincipal() != null) {
+ Principal principal = request.getUserPrincipal();
+ isCustomPrincipal = principal instanceof MyPrincipal;
+ webName = request.getUserPrincipal().getName();
+ }
+
+ boolean webHasRole = request.isUserInRole("architect");
+
+ response.getWriter().write("isCustomPrincipal: " + isCustomPrincipal + "\n");
+ response.getWriter().write("web username: " + webName + "\n");
+ response.getWriter().write("web user has role \"architect\": " + webHasRole + "\n");
+
+ }
+
+}
diff --git a/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/servlet/PublicServlet.java b/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/servlet/PublicServlet.java
new file mode 100644
index 000000000..f1b2812e8
--- /dev/null
+++ b/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/servlet/PublicServlet.java
@@ -0,0 +1,46 @@
+package org.javaee7.jaspic.registersession.servlet;
+
+import java.io.IOException;
+import java.security.Principal;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.javaee7.jaspic.registersession.sam.MyPrincipal;
+
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/public/servlet")
+public class PublicServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ response.getWriter().write("This is a public servlet \n");
+
+ String webName = null;
+ boolean isCustomPrincipal = false;
+ if (request.getUserPrincipal() != null) {
+ Principal principal = request.getUserPrincipal();
+ isCustomPrincipal = principal instanceof MyPrincipal;
+ webName = principal.getName();
+ }
+
+ boolean webHasRole = request.isUserInRole("architect");
+
+ response.getWriter().write("isCustomPrincipal: " + isCustomPrincipal + "\n");
+ response.getWriter().write("web username: " + webName + "\n");
+ response.getWriter().write("web user has role \"architect\": " + webHasRole + "\n");
+
+ }
+
+}
diff --git a/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/servlet/PublicServletProtectedEJB.java b/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/servlet/PublicServletProtectedEJB.java
new file mode 100644
index 000000000..29e024207
--- /dev/null
+++ b/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/servlet/PublicServletProtectedEJB.java
@@ -0,0 +1,63 @@
+package org.javaee7.jaspic.registersession.servlet;
+import static java.util.logging.Level.SEVERE;
+
+import java.io.IOException;
+import java.util.logging.Logger;
+
+import javax.ejb.EJB;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.javaee7.jaspic.registersession.ejb.ProtectedEJB;
+
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/public/servlet-protected-ejb")
+public class PublicServletProtectedEJB extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+ private final static Logger logger = Logger.getLogger(PublicServletProtectedEJB.class.getName());
+
+ @EJB
+ private ProtectedEJB protectedEJB;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ String webName = null;
+ if (request.getUserPrincipal() != null) {
+ webName = request.getUserPrincipal().getName();
+ }
+
+ String ejbName = "";
+ try {
+ ejbName = protectedEJB.getUserName();
+ } catch (Exception e) {
+ logger.log(SEVERE, "", e);
+ }
+
+ response.getWriter().write("web username: " + webName + "\n" + "EJB username: " + ejbName + "\n");
+
+ boolean webHasRole = request.isUserInRole("architect");
+
+ boolean ejbHasRole = false;
+ try {
+ ejbHasRole = protectedEJB.isUserArchitect();
+ } catch (Exception e) {
+ logger.log(SEVERE, "", e);
+ }
+
+ response.getWriter().write(
+ "web user has role \"architect\": " + webHasRole + "\n" + "EJB user has role \"architect\": " + ejbHasRole
+ + "\n");
+
+ }
+
+}
diff --git a/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/servlet/PublicServletPublicEJB.java b/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/servlet/PublicServletPublicEJB.java
new file mode 100644
index 000000000..e509f86df
--- /dev/null
+++ b/jaspic/ejb-register-session/src/main/java/org/javaee7/jaspic/registersession/servlet/PublicServletPublicEJB.java
@@ -0,0 +1,50 @@
+package org.javaee7.jaspic.registersession.servlet;
+import static java.util.logging.Level.SEVERE;
+
+import java.io.IOException;
+import java.util.logging.Logger;
+
+import javax.ejb.EJB;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.javaee7.jaspic.registersession.ejb.PublicEJB;
+
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/public/servlet-public-ejb")
+public class PublicServletPublicEJB extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+ private final static Logger logger = Logger.getLogger(PublicServletPublicEJB.class.getName());
+
+ @EJB
+ private PublicEJB publicEJB;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ String webName = null;
+ if (request.getUserPrincipal() != null) {
+ webName = request.getUserPrincipal().getName();
+ }
+
+ String ejbName = "";
+ try {
+ ejbName = publicEJB.getUserName();
+ } catch (Exception e) {
+ logger.log(SEVERE, "", e);
+ }
+
+ response.getWriter().write("web username: " + webName + "\n" + "EJB username: " + ejbName + "\n");
+
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/ejb-register-session/src/main/webapp/WEB-INF/glassfish-web.xml b/jaspic/ejb-register-session/src/main/webapp/WEB-INF/glassfish-web.xml
new file mode 100644
index 000000000..26559e3f6
--- /dev/null
+++ b/jaspic/ejb-register-session/src/main/webapp/WEB-INF/glassfish-web.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ architect
+ architect
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/ejb-register-session/src/main/webapp/WEB-INF/ibm-application-bnd.xml b/jaspic/ejb-register-session/src/main/webapp/WEB-INF/ibm-application-bnd.xml
new file mode 100644
index 000000000..9aa892cbc
--- /dev/null
+++ b/jaspic/ejb-register-session/src/main/webapp/WEB-INF/ibm-application-bnd.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/ejb-register-session/src/main/webapp/WEB-INF/jboss-web.xml b/jaspic/ejb-register-session/src/main/webapp/WEB-INF/jboss-web.xml
new file mode 100644
index 000000000..2c14aa4f8
--- /dev/null
+++ b/jaspic/ejb-register-session/src/main/webapp/WEB-INF/jboss-web.xml
@@ -0,0 +1,4 @@
+
+
+ jaspitest
+
diff --git a/jaspic/ejb-register-session/src/main/webapp/WEB-INF/web.xml b/jaspic/ejb-register-session/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..0ed6791b4
--- /dev/null
+++ b/jaspic/ejb-register-session/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+ Test
+ /protected/*
+
+
+ architect
+
+
+
+
+ architect
+
+
+
\ No newline at end of file
diff --git a/jaspic/ejb-register-session/src/test/java/org/javaee7/jaspic/registersession/RegisterSessionCustomPrincipalEJBPropagationTest.java b/jaspic/ejb-register-session/src/test/java/org/javaee7/jaspic/registersession/RegisterSessionCustomPrincipalEJBPropagationTest.java
new file mode 100644
index 000000000..62b53298d
--- /dev/null
+++ b/jaspic/ejb-register-session/src/test/java/org/javaee7/jaspic/registersession/RegisterSessionCustomPrincipalEJBPropagationTest.java
@@ -0,0 +1,149 @@
+package org.javaee7.jaspic.registersession;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * Variant of the RegisterSessionCustomPrincipalTest, where it's tested
+ * if the authenticated identity restored by the runtime correctly propagates
+ * to EJB.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class RegisterSessionCustomPrincipalEJBPropagationTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void testRemembersSession() throws IOException, SAXException {
+
+ // -------------------- Request 1 ---------------------------
+
+ // Accessing protected page without login
+ String response = getFromServerPath("protected/servlet");
+
+ // Not logged-in thus should not be accessible.
+ assertFalse(response.contains("This is a protected servlet"));
+
+
+ // -------------------- Request 2 ---------------------------
+
+ // We access the protected page again and now login
+
+ response = getFromServerPath("protected/servlet?doLogin=true&customPrincipal=true");
+
+ // Now has to be logged-in so page is accessible
+ assertTrue(
+ "Could not access protected page, but should be able to. " +
+ "Did the container remember the previously set 'unauthenticated identity'?",
+ response.contains("This is a protected servlet")
+ );
+
+ // Check principal has right name and right type and roles are available
+ checkAuthenticatedIdentity(response);
+
+
+ // -------------------- Request 3 ---------------------------
+
+ // JASPIC is normally stateless, but for this test the SAM uses the register session feature so now
+ // we should be logged-in when doing a call without explicitly logging in again.
+
+ response = getFromServerPath("protected/servlet?continueSession=true");
+
+ // Logged-in thus should be accessible.
+ assertTrue(
+ "Could not access protected page, but should be able to. " +
+ "Did the container not remember the authenticated identity via 'javax.servlet.http.registerSession'?",
+ response.contains("This is a protected servlet")
+ );
+
+ // Both the user name and roles/groups have to be restored
+
+ // *** NOTE ***: The JASPIC 1.1 spec is NOT clear about remembering roles, but spec lead Ron Monzillo clarified that
+ // this should indeed be the case. The next JASPIC revision of the spec will have to mention this explicitly.
+ // Intuitively it should make sense though that the authenticated identity is fully restored and not partially,
+ // but again the spec should make this clear to avoid ambiguity.
+
+ checkAuthenticatedIdentity(response);
+
+
+ // -------------------- Request 4 ---------------------------
+
+ // The session should also be remembered and propagated to a public EJB
+
+ response = getFromServerPath("public/servlet-public-ejb?continueSession=true");
+
+ // Both the web (HttpServletRequest) and EJB (EJBContext) should see the same
+ // user name.
+ assertTrue(
+ "User should have been authenticated in the web layer and given name \"test\", " +
+ " but does not appear to have this name",
+ response.contains("web username: test")
+ );
+ assertTrue(
+ "Web has user principal set, but EJB not.",
+ response.contains("EJB username: test")
+ );
+
+
+ // -------------------- Request 5 ---------------------------
+
+ // The session should also be remembered and propagated to a protected EJB
+
+ response = getFromServerPath("public/servlet-protected-ejb?continueSession=true");
+
+ // Both the web (HttpServletRequest) and EJB (EJBContext) should see the same
+ // user name.
+ assertTrue(
+ "User should have been authenticated in the web layer and given name \"test\", " +
+ " but does not appear to have this name",
+ response.contains("web username: test")
+ );
+ assertTrue(
+ "Web has user principal set, but EJB not.",
+ response.contains("EJB username: test")
+ );
+
+ // Both the web (HttpServletRequest) and EJB (EJBContext) should see that the
+ // user has the role "architect".
+ assertTrue(response.contains("web user has role \"architect\": true"));
+ assertTrue("Web user principal has role \"architect\", but one in EJB doesn't.",
+ response.contains("EJB user has role \"architect\": true"));
+
+ }
+
+ private void checkAuthenticatedIdentity( String response) {
+
+ // Has to be logged-in with the right principal
+ assertTrue(
+ "Authenticated but username is not the expected one 'test'",
+ response.contains("web username: test")
+ );
+ assertTrue(
+ "Authentication succeeded and username is correct, but the expected role 'architect' is not present.",
+ response.contains("web user has role \"architect\": true"));
+
+ assertTrue(
+ "Authentication succeeded and username and roles are correct, but principal type is not the expected custom type.",
+ response.contains("isCustomPrincipal: true")
+ );
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/jaspic/ejb-register-session/src/test/java/org/javaee7/jaspic/registersession/RegisterSessionEJBPropagationTest.java b/jaspic/ejb-register-session/src/test/java/org/javaee7/jaspic/registersession/RegisterSessionEJBPropagationTest.java
new file mode 100644
index 000000000..e3378e830
--- /dev/null
+++ b/jaspic/ejb-register-session/src/test/java/org/javaee7/jaspic/registersession/RegisterSessionEJBPropagationTest.java
@@ -0,0 +1,149 @@
+package org.javaee7.jaspic.registersession;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * Variant of the RegisterSessionTest, where it's tested
+ * if the authenticated identity restored by the runtime correctly propagates
+ * to EJB.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class RegisterSessionEJBPropagationTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void testRemembersSession() throws IOException, SAXException {
+
+ // -------------------- Request 1 ---------------------------
+
+ // Accessing protected page without login
+ String response = getFromServerPath("protected/servlet");
+
+ // Not logged-in thus should not be accessible.
+ assertFalse(response.contains("This is a protected servlet"));
+
+
+ // -------------------- Request 2 ---------------------------
+
+ // We access the protected page again and now login
+
+ response = getFromServerPath("protected/servlet?doLogin=true");
+
+ // Now has to be logged-in so page is accessible
+ assertTrue(
+ "Could not access protected page, but should be able to. " +
+ "Did the container remember the previously set 'unauthenticated identity'?",
+ response.contains("This is a protected servlet")
+ );
+
+ // Check principal has right name and right type and roles are available
+ checkAuthenticatedIdentity(response);
+
+
+ // -------------------- Request 3 ---------------------------
+
+ // JASPIC is normally stateless, but for this test the SAM uses the register session feature so now
+ // we should be logged-in when doing a call without explicitly logging in again.
+
+ response = getFromServerPath("protected/servlet?continueSession=true");
+
+ // Logged-in thus should be accessible.
+ assertTrue(
+ "Could not access protected page, but should be able to. " +
+ "Did the container not remember the authenticated identity via 'javax.servlet.http.registerSession'?",
+ response.contains("This is a protected servlet")
+ );
+
+ // Both the user name and roles/groups have to be restored
+
+ // *** NOTE ***: The JASPIC 1.1 spec is NOT clear about remembering roles, but spec lead Ron Monzillo clarified that
+ // this should indeed be the case. The next JASPIC revision of the spec will have to mention this explicitly.
+ // Intuitively it should make sense though that the authenticated identity is fully restored and not partially,
+ // but again the spec should make this clear to avoid ambiguity.
+
+ checkAuthenticatedIdentity(response);
+
+
+ // -------------------- Request 4 ---------------------------
+
+ // The session should also be remembered and propagated to a public EJB
+
+ response = getFromServerPath("public/servlet-public-ejb?continueSession=true");
+
+ // Both the web (HttpServletRequest) and EJB (EJBContext) should see the same
+ // user name.
+ assertTrue(
+ "User should have been authenticated in the web layer and given name \"test\", " +
+ " but does not appear to have this name",
+ response.contains("web username: test")
+ );
+ assertTrue(
+ "Web has user principal set, but EJB not.",
+ response.contains("EJB username: test")
+ );
+
+
+ // -------------------- Request 5 ---------------------------
+
+ // The session should also be remembered and propagated to a protected EJB
+
+ response = getFromServerPath("public/servlet-protected-ejb?continueSession=true");
+
+ // Both the web (HttpServletRequest) and EJB (EJBContext) should see the same
+ // user name.
+ assertTrue(
+ "User should have been authenticated in the web layer and given name \"test\", " +
+ " but does not appear to have this name",
+ response.contains("web username: test")
+ );
+ assertTrue(
+ "Web has user principal set, but EJB not.",
+ response.contains("EJB username: test")
+ );
+
+ // Both the web (HttpServletRequest) and EJB (EJBContext) should see that the
+ // user has the role "architect".
+ assertTrue(response.contains("web user has role \"architect\": true"));
+ assertTrue("Web user principal has role \"architect\", but one in EJB doesn't.",
+ response.contains("EJB user has role \"architect\": true"));
+
+ }
+
+ private void checkAuthenticatedIdentity( String response) {
+
+ // Has to be logged-in with the right principal
+ assertTrue(
+ "Authenticated but username is not the expected one 'test'",
+ response.contains("web username: test")
+ );
+ assertTrue(
+ "Authentication succeeded and username is correct, but the expected role 'architect' is not present.",
+ response.contains("web user has role \"architect\": true"));
+
+ assertTrue(
+ "Authentication succeeded and username and roles are correct, but principal type is not the expected custom type.",
+ response.contains("isCustomPrincipal: false")
+ );
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/jaspic/invoke-ejb-cdi/pom.xml b/jaspic/invoke-ejb-cdi/pom.xml
new file mode 100644
index 000000000..864602c38
--- /dev/null
+++ b/jaspic/invoke-ejb-cdi/pom.xml
@@ -0,0 +1,36 @@
+
+
+ 4.0.0
+
+
+ org.javaee7
+ jaspic
+ 1.0-SNAPSHOT
+
+
+ jaspic-invoke-ejb-cdi
+
+ war
+
+ Java EE 7 Sample: jaspic - invoke EJB and CDI
+
+
+
+ org.javaee7
+ jaspic-common
+ 1.0-SNAPSHOT
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ ${skipEJB}
+
+
+
+
+
diff --git a/jaspic/invoke-ejb-cdi/src/main/java/org/javaee7/jaspic/invoke/bean/CDIBean.java b/jaspic/invoke-ejb-cdi/src/main/java/org/javaee7/jaspic/invoke/bean/CDIBean.java
new file mode 100644
index 000000000..88c148d1d
--- /dev/null
+++ b/jaspic/invoke-ejb-cdi/src/main/java/org/javaee7/jaspic/invoke/bean/CDIBean.java
@@ -0,0 +1,23 @@
+package org.javaee7.jaspic.invoke.bean;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.servlet.http.HttpServletRequest;
+
+@Named
+@RequestScoped
+public class CDIBean {
+
+ @Inject
+ private HttpServletRequest request;
+
+ public String getText() {
+ return "Called from CDI";
+ }
+
+ public void setTextViaInjectedRequest() {
+ request.setAttribute("text", "Called from CDI via injected request");
+ }
+
+}
diff --git a/jaspic/invoke-ejb-cdi/src/main/java/org/javaee7/jaspic/invoke/bean/EJBBean.java b/jaspic/invoke-ejb-cdi/src/main/java/org/javaee7/jaspic/invoke/bean/EJBBean.java
new file mode 100644
index 000000000..07df114cd
--- /dev/null
+++ b/jaspic/invoke-ejb-cdi/src/main/java/org/javaee7/jaspic/invoke/bean/EJBBean.java
@@ -0,0 +1,12 @@
+package org.javaee7.jaspic.invoke.bean;
+
+import javax.ejb.Stateless;
+
+@Stateless
+public class EJBBean {
+
+ public String getText() {
+ return "Called from EJB";
+ }
+
+}
diff --git a/jaspic/invoke-ejb-cdi/src/main/java/org/javaee7/jaspic/invoke/sam/SamAutoRegistrationListener.java b/jaspic/invoke-ejb-cdi/src/main/java/org/javaee7/jaspic/invoke/sam/SamAutoRegistrationListener.java
new file mode 100644
index 000000000..dc6b780ca
--- /dev/null
+++ b/jaspic/invoke-ejb-cdi/src/main/java/org/javaee7/jaspic/invoke/sam/SamAutoRegistrationListener.java
@@ -0,0 +1,22 @@
+package org.javaee7.jaspic.invoke.sam;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.annotation.WebListener;
+
+import org.javaee7.jaspic.common.BaseServletContextListener;
+import org.javaee7.jaspic.common.JaspicUtils;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebListener
+public class SamAutoRegistrationListener extends BaseServletContextListener {
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ JaspicUtils.registerSAM(sce.getServletContext(), new TestServerAuthModule());
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/invoke-ejb-cdi/src/main/java/org/javaee7/jaspic/invoke/sam/TestServerAuthModule.java b/jaspic/invoke-ejb-cdi/src/main/java/org/javaee7/jaspic/invoke/sam/TestServerAuthModule.java
new file mode 100644
index 000000000..cf5fb8325
--- /dev/null
+++ b/jaspic/invoke-ejb-cdi/src/main/java/org/javaee7/jaspic/invoke/sam/TestServerAuthModule.java
@@ -0,0 +1,132 @@
+package org.javaee7.jaspic.invoke.sam;
+
+import static java.util.logging.Level.SEVERE;
+import static javax.security.auth.message.AuthStatus.SEND_SUCCESS;
+import static javax.security.auth.message.AuthStatus.SUCCESS;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import javax.enterprise.inject.spi.CDI;
+import javax.naming.InitialContext;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.AuthStatus;
+import javax.security.auth.message.MessageInfo;
+import javax.security.auth.message.MessagePolicy;
+import javax.security.auth.message.callback.CallerPrincipalCallback;
+import javax.security.auth.message.callback.GroupPrincipalCallback;
+import javax.security.auth.message.module.ServerAuthModule;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.javaee7.jaspic.invoke.bean.CDIBean;
+import org.javaee7.jaspic.invoke.bean.EJBBean;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class TestServerAuthModule implements ServerAuthModule {
+
+ private final static Logger logger = Logger.getLogger(TestServerAuthModule.class.getName());
+
+ private CallbackHandler handler;
+ private Class>[] supportedMessageTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class };
+
+
+
+ @Override
+ public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler,
+ @SuppressWarnings("rawtypes") Map options) throws AuthException {
+ this.handler = handler;
+ }
+
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+ HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();
+
+ if ("cdi".equals(request.getParameter("tech"))) {
+ callCDIBean(request, response, "validateRequest");
+ } else if ("ejb".equals(request.getParameter("tech"))) {
+ callEJBBean(response, "validateRequest");
+ }
+
+ try {
+ handler.handle(new Callback[] {
+ new CallerPrincipalCallback(clientSubject, "test"),
+ new GroupPrincipalCallback(clientSubject, new String[] { "architect" })
+ });
+
+ return SUCCESS;
+
+ } catch (IOException | UnsupportedCallbackException e) {
+ throw (AuthException) new AuthException().initCause(e);
+ }
+ }
+
+ @Override
+ public Class>[] getSupportedMessageTypes() {
+ return supportedMessageTypes;
+ }
+
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+ HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();
+
+ if ("cdi".equals(request.getParameter("tech"))) {
+ callCDIBean(request, response, "secureResponse");
+ } else if ("ejb".equals(request.getParameter("tech"))) {
+ callEJBBean(response, "secureResponse");
+ }
+
+ return SEND_SUCCESS;
+ }
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+ HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();
+
+ if ("cdi".equals(request.getParameter("tech"))) {
+ callCDIBean(request, response, "cleanSubject");
+ } else if ("ejb".equals(request.getParameter("tech"))) {
+ callEJBBean(response, "cleanSubject");
+ }
+ }
+
+ private void callCDIBean(HttpServletRequest request, HttpServletResponse response, String phase) {
+ try {
+ CDIBean cdiBean = CDI.current().select(CDIBean.class).get();
+ response.getWriter().write(phase + ": " + cdiBean.getText() + "\n");
+
+ cdiBean.setTextViaInjectedRequest();
+
+ response.getWriter().write(phase + ": " + request.getAttribute("text")+ "\n");
+
+ } catch (Exception e) {
+ logger.log(SEVERE, "", e);
+ }
+ }
+
+ private void callEJBBean(HttpServletResponse response, String phase) {
+ try {
+ EJBBean ejbBean = (EJBBean) new InitialContext().lookup("java:module/EJBBean");
+ response.getWriter().write(phase + ": " + ejbBean.getText() + "\n");
+ } catch (Exception e) {
+ logger.log(SEVERE, "", e);
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/jaspic/invoke-ejb-cdi/src/main/java/org/javaee7/jaspic/invoke/servlet/ProtectedServlet.java b/jaspic/invoke-ejb-cdi/src/main/java/org/javaee7/jaspic/invoke/servlet/ProtectedServlet.java
new file mode 100644
index 000000000..22208d9e6
--- /dev/null
+++ b/jaspic/invoke-ejb-cdi/src/main/java/org/javaee7/jaspic/invoke/servlet/ProtectedServlet.java
@@ -0,0 +1,26 @@
+package org.javaee7.jaspic.invoke.servlet;
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/protected/servlet")
+public class ProtectedServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.getWriter().write("Resource invoked\n");
+ request.logout();
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/invoke-ejb-cdi/src/main/java/org/javaee7/jaspic/invoke/servlet/PublicServlet.java b/jaspic/invoke-ejb-cdi/src/main/java/org/javaee7/jaspic/invoke/servlet/PublicServlet.java
new file mode 100644
index 000000000..d245050d9
--- /dev/null
+++ b/jaspic/invoke-ejb-cdi/src/main/java/org/javaee7/jaspic/invoke/servlet/PublicServlet.java
@@ -0,0 +1,26 @@
+package org.javaee7.jaspic.invoke.servlet;
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/public/servlet")
+public class PublicServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.getWriter().write("Resource invoked\n");
+ request.logout();
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/invoke-ejb-cdi/src/main/webapp/WEB-INF/beans.xml b/jaspic/invoke-ejb-cdi/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 000000000..e69de29bb
diff --git a/jaspic/invoke-ejb-cdi/src/main/webapp/WEB-INF/glassfish-web.xml b/jaspic/invoke-ejb-cdi/src/main/webapp/WEB-INF/glassfish-web.xml
new file mode 100644
index 000000000..26559e3f6
--- /dev/null
+++ b/jaspic/invoke-ejb-cdi/src/main/webapp/WEB-INF/glassfish-web.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ architect
+ architect
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/invoke-ejb-cdi/src/main/webapp/WEB-INF/ibm-application-bnd.xml b/jaspic/invoke-ejb-cdi/src/main/webapp/WEB-INF/ibm-application-bnd.xml
new file mode 100644
index 000000000..9aa892cbc
--- /dev/null
+++ b/jaspic/invoke-ejb-cdi/src/main/webapp/WEB-INF/ibm-application-bnd.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/invoke-ejb-cdi/src/main/webapp/WEB-INF/jboss-web.xml b/jaspic/invoke-ejb-cdi/src/main/webapp/WEB-INF/jboss-web.xml
new file mode 100644
index 000000000..b6ab7d0ba
--- /dev/null
+++ b/jaspic/invoke-ejb-cdi/src/main/webapp/WEB-INF/jboss-web.xml
@@ -0,0 +1,5 @@
+
+
+
+ jaspitest
+
diff --git a/jaspic/invoke-ejb-cdi/src/main/webapp/WEB-INF/web.xml b/jaspic/invoke-ejb-cdi/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..ffd58ffa6
--- /dev/null
+++ b/jaspic/invoke-ejb-cdi/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Test
+ /protected/*
+
+
+ architect
+
+
+
+
+ architect
+
+
+
\ No newline at end of file
diff --git a/jaspic/invoke-ejb-cdi/src/test/java/org/javaee7/jaspictest/invoke/InvokeCDIBeanProtectedTest.java b/jaspic/invoke-ejb-cdi/src/test/java/org/javaee7/jaspictest/invoke/InvokeCDIBeanProtectedTest.java
new file mode 100644
index 000000000..74cd8c66e
--- /dev/null
+++ b/jaspic/invoke-ejb-cdi/src/test/java/org/javaee7/jaspictest/invoke/InvokeCDIBeanProtectedTest.java
@@ -0,0 +1,60 @@
+package org.javaee7.jaspictest.invoke;
+
+import static org.junit.Assert.assertTrue;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * This tests that a SAM is able to obtain and call a CDI bean when the request is to a protected resource
+ * (a resource for which security constraints have been set).
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class InvokeCDIBeanProtectedTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return tryWrapEAR(
+ defaultWebArchive()
+ .addAsWebInfResource(resource("beans.xml"))
+ );
+ }
+
+ @Test
+ public void protectedInvokeCDIFromValidateRequest() {
+ String response = getFromServerPath("protected/servlet?tech=cdi");
+
+ assertTrue(
+ "Response did not contain output from CDI bean for validateRequest for protected resource. (note: this is not required by the spec)",
+ response.contains("validateRequest: Called from CDI")
+ );
+ }
+
+ @Test
+ public void protectedInvokeCDIFromCleanSubject() {
+ String response = getFromServerPath("protected/servlet?tech=cdi");
+
+ assertTrue(
+ "Response did not contain output from CDI bean for cleanSubject for protected resource. (note: this is not required by the spec)",
+ response.contains("cleanSubject: Called from CDI")
+ );
+ }
+
+ @Test
+ public void protectedInvokeCDIFromSecureResponse() {
+ String response = getFromServerPath("protected/servlet?tech=cdi");
+
+ assertTrue(
+ "Response did not contain output from CDI bean for secureResponse for protected resource. (note: this is not required by the spec)",
+ response.contains("secureResponse: Called from CDI")
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/invoke-ejb-cdi/src/test/java/org/javaee7/jaspictest/invoke/InvokeCDIBeanPublicTest.java b/jaspic/invoke-ejb-cdi/src/test/java/org/javaee7/jaspictest/invoke/InvokeCDIBeanPublicTest.java
new file mode 100644
index 000000000..82a6057b2
--- /dev/null
+++ b/jaspic/invoke-ejb-cdi/src/test/java/org/javaee7/jaspictest/invoke/InvokeCDIBeanPublicTest.java
@@ -0,0 +1,90 @@
+package org.javaee7.jaspictest.invoke;
+
+import static org.junit.Assert.assertTrue;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * This tests that a SAM is able to obtain and call a CDI bean when the request is to a public resource
+ * (a resource for which no security constraints have been set).
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class InvokeCDIBeanPublicTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return tryWrapEAR(
+ defaultWebArchive()
+ .addAsWebInfResource(resource("beans.xml"))
+ );
+ }
+
+ @Test
+ public void publicInvokeCDIFromValidateRequest() {
+ String response = getFromServerPath("public/servlet?tech=cdi");
+
+ assertTrue(
+ "Response did not contain output from CDI bean for validateRequest for public resource. (note: this is not required by the spec)",
+ response.contains("validateRequest: Called from CDI")
+ );
+ }
+
+ @Test
+ public void publicInvokeCDIFromCleanSubject() {
+ String response = getFromServerPath("public/servlet?tech=cdi");
+
+ assertTrue(
+ "Response did not contain output from CDI bean for cleanSubject for public resource. (note: this is not required by the spec)",
+ response.contains("cleanSubject: Called from CDI")
+ );
+ }
+
+ @Test
+ public void publicInvokeCDIFromSecureResponse() {
+ String response = getFromServerPath("public/servlet?tech=cdi");
+
+ assertTrue(
+ "Response did not contain output from CDI bean for secureResponse for public resource. (note: this is not required by the spec)",
+ response.contains("secureResponse: Called from CDI")
+ );
+ }
+
+ @Test
+ public void publicInvokeCDIUseInjectedRequestFromValidateRequest() {
+ String response = getFromServerPath("public/servlet?tech=cdi");
+
+ assertTrue(
+ "Response did not contain output from CDI bean using an inject request for validateRequest for public resource. (note: this is not required by the spec)",
+ response.contains("validateRequest: Called from CDI via injected request")
+ );
+ }
+
+ @Test
+ public void publicInvokeCDIUseInjectedRequestFromCleanSubject() {
+ String response = getFromServerPath("public/servlet?tech=cdi");
+
+ assertTrue(
+ "Response did not contain output from CDI bean using an inject request for cleanSubject for public resource. (note: this is not required by the spec)",
+ response.contains("cleanSubject: Called from CDI via injected request")
+ );
+ }
+
+ @Test
+ public void publicInvokeCDIUseInjectedRequestFromSecureResponse() {
+ String response = getFromServerPath("public/servlet?tech=cdi");
+
+ assertTrue(
+ "Response did not contain output from CDI bean using an inject request for secureResponse for public resource. (note: this is not required by the spec)",
+ response.contains("secureResponse: Called from CDI via injected request")
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/invoke-ejb-cdi/src/test/java/org/javaee7/jaspictest/invoke/InvokeEJBBeanProtectedTest.java b/jaspic/invoke-ejb-cdi/src/test/java/org/javaee7/jaspictest/invoke/InvokeEJBBeanProtectedTest.java
new file mode 100644
index 000000000..81d6d0146
--- /dev/null
+++ b/jaspic/invoke-ejb-cdi/src/test/java/org/javaee7/jaspictest/invoke/InvokeEJBBeanProtectedTest.java
@@ -0,0 +1,57 @@
+package org.javaee7.jaspictest.invoke;
+
+import static org.junit.Assert.assertTrue;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * This tests that a SAM is able to obtain and call an EJB bean when the request is to a protected resource
+ * (a resource for which security constraints have been set).
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class InvokeEJBBeanProtectedTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void protectedInvokeEJBFromValidateRequest() {
+ String response = getFromServerPath("protected/servlet?tech=ejb");
+
+ assertTrue(
+ "Response did not contain output from EJB bean for validateRequest for protected resource. (note: spec is silent on this, but it should work)",
+ response.contains("validateRequest: Called from EJB")
+ );
+ }
+
+ @Test
+ public void protectedInvokeEJBFromCleanSubject() {
+ String response = getFromServerPath("protected/servlet?tech=ejb");
+
+ assertTrue(
+ "Response did not contain output from EJB bean for cleanSubject for protected resource. (note: spec is silent on this, but it should work)",
+ response.contains("cleanSubject: Called from EJB")
+ );
+ }
+
+ @Test
+ public void protectedInvokeEJBFromSecureResponse() {
+ String response = getFromServerPath("protected/servlet?tech=ejb");
+
+ assertTrue(
+ "Response did not contain output from EJB bean for secureResponse for protected resource. (note: spec is silent on this, but it should work)",
+ response.contains("secureResponse: Called from EJB")
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/invoke-ejb-cdi/src/test/java/org/javaee7/jaspictest/invoke/InvokeEJBBeanPublicTest.java b/jaspic/invoke-ejb-cdi/src/test/java/org/javaee7/jaspictest/invoke/InvokeEJBBeanPublicTest.java
new file mode 100644
index 000000000..746a61a26
--- /dev/null
+++ b/jaspic/invoke-ejb-cdi/src/test/java/org/javaee7/jaspictest/invoke/InvokeEJBBeanPublicTest.java
@@ -0,0 +1,57 @@
+package org.javaee7.jaspictest.invoke;
+
+import static org.junit.Assert.assertTrue;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * This tests that a SAM is able to obtain and call an EJB bean when the request is to a public resource
+ * (a resource for which no security constraints have been set).
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class InvokeEJBBeanPublicTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void publicInvokeEJBFromValidateRequest() {
+ String response = getFromServerPath("public/servlet?tech=ejb");
+
+ assertTrue(
+ "Response did not contain output from EJB bean for validateRequest for public resource.",
+ response.contains("validateRequest: Called from EJB")
+ );
+ }
+
+ @Test
+ public void publicInvokeEJBFromCleanSubject() {
+ String response = getFromServerPath("public/servlet?tech=ejb");
+
+ assertTrue(
+ "Response did not contain output from EJB bean for cleanSubject for public resource.",
+ response.contains("cleanSubject: Called from EJB")
+ );
+ }
+
+ @Test
+ public void publicInvokeEJBFromSecureResponse() {
+ String response = getFromServerPath("public/servlet?tech=ejb");
+
+ assertTrue(
+ "Response did not contain output from EJB bean for secureResponse for public resource.",
+ response.contains("secureResponse: Called from EJB")
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/jacc-propagation/pom.xml b/jaspic/jacc-propagation/pom.xml
new file mode 100644
index 000000000..ae84dbf2d
--- /dev/null
+++ b/jaspic/jacc-propagation/pom.xml
@@ -0,0 +1,34 @@
+
+
+ 4.0.0
+
+
+ org.javaee7
+ jaspic
+ 1.0-SNAPSHOT
+
+
+ jaspic-jacc-propagation
+ war
+ Java EE 7 Sample: jaspic - jacc-propagation
+
+
+
+ org.javaee7
+ jaspic-common
+ 1.0-SNAPSHOT
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ ${skipJACC}
+
+
+
+
+
diff --git a/jaspic/jacc-propagation/src/main/java/org/javaee7/jaspic/jaccpropagation/jacc/JACC.java b/jaspic/jacc-propagation/src/main/java/org/javaee7/jaspic/jaccpropagation/jacc/JACC.java
new file mode 100644
index 000000000..a3201c373
--- /dev/null
+++ b/jaspic/jacc-propagation/src/main/java/org/javaee7/jaspic/jaccpropagation/jacc/JACC.java
@@ -0,0 +1,45 @@
+package org.javaee7.jaspic.jaccpropagation.jacc;
+
+import static java.security.Policy.getPolicy;
+import static java.util.logging.Level.SEVERE;
+
+import java.security.CodeSource;
+import java.security.Principal;
+import java.security.ProtectionDomain;
+import java.security.cert.Certificate;
+import java.util.logging.Logger;
+
+import javax.security.auth.Subject;
+import javax.security.jacc.PolicyContext;
+import javax.security.jacc.WebResourcePermission;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class JACC {
+
+ private final static Logger logger = Logger.getLogger(JACC.class.getName());
+
+ public static Subject getSubject() {
+ try {
+ return (Subject) PolicyContext.getContext("javax.security.auth.Subject.container");
+ } catch (Exception e) {
+ logger.log(SEVERE, "", e);
+ }
+
+ return null;
+ }
+
+ public static boolean hasAccess(String uri, Subject subject) {
+ return getPolicy().implies(
+ new ProtectionDomain(
+ new CodeSource(null, (Certificate[]) null),
+ null, null,
+ subject.getPrincipals().toArray(new Principal[subject.getPrincipals().size()])
+ ),
+ new WebResourcePermission(uri, "GET")
+ );
+ }
+}
diff --git a/jaspic/jacc-propagation/src/main/java/org/javaee7/jaspic/jaccpropagation/sam/SamAutoRegistrationListener.java b/jaspic/jacc-propagation/src/main/java/org/javaee7/jaspic/jaccpropagation/sam/SamAutoRegistrationListener.java
new file mode 100644
index 000000000..09e8e240a
--- /dev/null
+++ b/jaspic/jacc-propagation/src/main/java/org/javaee7/jaspic/jaccpropagation/sam/SamAutoRegistrationListener.java
@@ -0,0 +1,22 @@
+package org.javaee7.jaspic.jaccpropagation.sam;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.annotation.WebListener;
+
+import org.javaee7.jaspic.common.BaseServletContextListener;
+import org.javaee7.jaspic.common.JaspicUtils;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebListener
+public class SamAutoRegistrationListener extends BaseServletContextListener {
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ JaspicUtils.registerSAM(sce.getServletContext(), new TestServerAuthModule());
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/jacc-propagation/src/main/java/org/javaee7/jaspic/jaccpropagation/sam/TestServerAuthModule.java b/jaspic/jacc-propagation/src/main/java/org/javaee7/jaspic/jaccpropagation/sam/TestServerAuthModule.java
new file mode 100644
index 000000000..e75b2a4a0
--- /dev/null
+++ b/jaspic/jacc-propagation/src/main/java/org/javaee7/jaspic/jaccpropagation/sam/TestServerAuthModule.java
@@ -0,0 +1,82 @@
+package org.javaee7.jaspic.jaccpropagation.sam;
+
+import static javax.security.auth.message.AuthStatus.SUCCESS;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.AuthStatus;
+import javax.security.auth.message.MessageInfo;
+import javax.security.auth.message.MessagePolicy;
+import javax.security.auth.message.callback.CallerPrincipalCallback;
+import javax.security.auth.message.callback.GroupPrincipalCallback;
+import javax.security.auth.message.module.ServerAuthModule;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Very basic SAM that returns a single hardcoded user named "test" with role "architect" when the request parameter
+ * doLogin is present.
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class TestServerAuthModule implements ServerAuthModule {
+
+ private CallbackHandler handler;
+ private Class>[] supportedMessageTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class };
+
+ @Override
+ public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler,
+ @SuppressWarnings("rawtypes") Map options) throws AuthException {
+ this.handler = handler;
+ }
+
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject)
+ throws AuthException {
+
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+
+ Callback[] callbacks;
+
+ if (request.getParameter("doLogin") != null) {
+
+ callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, "test"),
+ new GroupPrincipalCallback(clientSubject, new String[] { "architect" }) };
+ } else {
+
+ // The JASPIC protocol for "do nothing"
+ callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, (Principal) null) };
+ }
+
+ try {
+ handler.handle(callbacks);
+ } catch (IOException | UnsupportedCallbackException e) {
+ throw (AuthException) new AuthException().initCause(e);
+ }
+
+ return SUCCESS;
+ }
+
+ @Override
+ public Class>[] getSupportedMessageTypes() {
+ return supportedMessageTypes;
+ }
+
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+ return AuthStatus.SEND_SUCCESS;
+ }
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+
+ }
+}
\ No newline at end of file
diff --git a/jaspic/jacc-propagation/src/main/java/org/javaee7/jaspic/jaccpropagation/servlet/ProtectedServlet.java b/jaspic/jacc-propagation/src/main/java/org/javaee7/jaspic/jaccpropagation/servlet/ProtectedServlet.java
new file mode 100644
index 000000000..bd871917b
--- /dev/null
+++ b/jaspic/jacc-propagation/src/main/java/org/javaee7/jaspic/jaccpropagation/servlet/ProtectedServlet.java
@@ -0,0 +1,42 @@
+package org.javaee7.jaspic.jaccpropagation.servlet;
+
+import static org.javaee7.jaspic.jaccpropagation.jacc.JACC.getSubject;
+import static org.javaee7.jaspic.jaccpropagation.jacc.JACC.hasAccess;
+
+import java.io.IOException;
+
+import javax.security.auth.Subject;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/protected/servlet")
+public class ProtectedServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ // Obtain the active subject via a JACC policy handler
+ Subject subject = getSubject();
+
+ if (subject == null) {
+ response.getWriter().write("Can't get Subject. JACC doesn't seem to be available.");
+ return;
+ }
+
+ // Check with JACC if the caller has access to this Servlet. As we're
+ // currently in this very Servlet the answer can't be anything than "true" if
+ // JASPIC, JACC and role propagation all work correctly.
+ response.getWriter().write("Has access to /protected/servlet: " + hasAccess("/protected/servlet", subject));
+ }
+
+}
diff --git a/jaspic/jacc-propagation/src/main/java/org/javaee7/jaspic/jaccpropagation/servlet/PublicServlet.java b/jaspic/jacc-propagation/src/main/java/org/javaee7/jaspic/jaccpropagation/servlet/PublicServlet.java
new file mode 100644
index 000000000..8ac0bf968
--- /dev/null
+++ b/jaspic/jacc-propagation/src/main/java/org/javaee7/jaspic/jaccpropagation/servlet/PublicServlet.java
@@ -0,0 +1,49 @@
+package org.javaee7.jaspic.jaccpropagation.servlet;
+
+import static org.javaee7.jaspic.jaccpropagation.jacc.JACC.getSubject;
+import static org.javaee7.jaspic.jaccpropagation.jacc.JACC.hasAccess;
+
+import java.io.IOException;
+
+import javax.security.auth.Subject;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/public/servlet")
+public class PublicServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ // Obtain the active subject via a JACC policy handler
+ Subject subject = getSubject();
+
+ if (subject == null) {
+ response.getWriter().write("Can't get Subject. JACC doesn't seem to be available.");
+ return;
+ }
+
+ // Check with JACC if the caller has access to this Servlet. As we're
+ // currently in this very Servlet and it's a public Servlet,the answer can't be anything
+ // than "true".
+
+ response.getWriter().write("Has access to /public/servlet: " + hasAccess("/public/servlet", subject));
+
+ // Check with JACC if the caller has access to another (protected) Servlet. If JACC
+ // works correctly and we're authenticated this should be true.
+
+ response.getWriter().write(
+ "\nHas access to /protected/servlet: " + hasAccess("/protected/servlet", subject));
+ }
+
+}
diff --git a/jaspic/jacc-propagation/src/main/webapp/WEB-INF/glassfish-web.xml b/jaspic/jacc-propagation/src/main/webapp/WEB-INF/glassfish-web.xml
new file mode 100644
index 000000000..26559e3f6
--- /dev/null
+++ b/jaspic/jacc-propagation/src/main/webapp/WEB-INF/glassfish-web.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ architect
+ architect
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/jacc-propagation/src/main/webapp/WEB-INF/ibm-application-bnd.xml b/jaspic/jacc-propagation/src/main/webapp/WEB-INF/ibm-application-bnd.xml
new file mode 100644
index 000000000..9aa892cbc
--- /dev/null
+++ b/jaspic/jacc-propagation/src/main/webapp/WEB-INF/ibm-application-bnd.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/jacc-propagation/src/main/webapp/WEB-INF/jboss-web.xml b/jaspic/jacc-propagation/src/main/webapp/WEB-INF/jboss-web.xml
new file mode 100644
index 000000000..b6ab7d0ba
--- /dev/null
+++ b/jaspic/jacc-propagation/src/main/webapp/WEB-INF/jboss-web.xml
@@ -0,0 +1,5 @@
+
+
+
+ jaspitest
+
diff --git a/jaspic/jacc-propagation/src/main/webapp/WEB-INF/web.xml b/jaspic/jacc-propagation/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..ffd58ffa6
--- /dev/null
+++ b/jaspic/jacc-propagation/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Test
+ /protected/*
+
+
+ architect
+
+
+
+
+ architect
+
+
+
\ No newline at end of file
diff --git a/jaspic/jacc-propagation/src/test/java/org/javaee7/jaspic/jaccpropagation/JACCPropagationProtectedTest.java b/jaspic/jacc-propagation/src/test/java/org/javaee7/jaspic/jaccpropagation/JACCPropagationProtectedTest.java
new file mode 100644
index 000000000..8de3a35d2
--- /dev/null
+++ b/jaspic/jacc-propagation/src/test/java/org/javaee7/jaspic/jaccpropagation/JACCPropagationProtectedTest.java
@@ -0,0 +1,53 @@
+package org.javaee7.jaspic.jaccpropagation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * This tests that the established authenticated identity set from JASPIC propagates correctly
+ * to a JACC provider.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class JACCPropagationProtectedTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void callingJACCWhenAuthenticated() {
+
+ String response = getFromServerPath("protected/servlet?doLogin=true");
+
+ // This can basically only fail if JACC itself somehow doesn't work.
+ // Unfortunately this is the case for a bunch of certified servers, which
+ // either demand some activation of JACC, or don't ship with a default
+ // provider at all (which are both spec violations)
+ assertFalse(
+ "JACC doesn't seem to be available.",
+ response.contains("JACC doesn't seem to be available.")
+ );
+
+ // Test if we have access to protected/servlet from within that servlet.
+ // If this fails role propagation and/or JACC failed, since this is obviously
+ // impossible.
+ assertTrue(
+ "Did not have access to protected servlet from within that Servlet. " +
+ " Perhaps the roles did not propogate from JASPIC to JACC and the" +
+ " server didn't use JACC to grant access to invoking said Servlet?",
+ response.contains("Has access to /protected/servlet: true")
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/jacc-propagation/src/test/java/org/javaee7/jaspic/jaccpropagation/JACCPropagationPublicTest.java b/jaspic/jacc-propagation/src/test/java/org/javaee7/jaspic/jaccpropagation/JACCPropagationPublicTest.java
new file mode 100644
index 000000000..ff102fc87
--- /dev/null
+++ b/jaspic/jacc-propagation/src/test/java/org/javaee7/jaspic/jaccpropagation/JACCPropagationPublicTest.java
@@ -0,0 +1,90 @@
+package org.javaee7.jaspic.jaccpropagation;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * This tests that the established authenticated identity set from JASPIC propagates correctly
+ * to a JACC provider.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class JACCPropagationPublicTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void callingJACCWhenAuthenticated() {
+
+ String response = getFromServerPath("public/servlet?doLogin=true");
+
+ // This can basically only fail if JACC itself somehow doesn't work.
+ // Unfortunately this is the case for a bunch of certified servers, which
+ // either demand some activation of JACC, or don't ship with a default
+ // provider at all (which are both spec violations)
+ assertFalse(
+ "JACC doesn't seem to be available.",
+ response.contains("JACC doesn't seem to be available.")
+ );
+
+ // Test if we have access to public/servlet. This would be rare to fail
+ assertTrue(
+ "Did not have access to public servlet from within that Servlet. " +
+ " Something is seriously wrong.",
+ response.contains("Has access to /public/servlet: true")
+ );
+
+ // Test if we have access to protected/servlet. Since we authenticated with JASPIC
+ // with a role that this path is protected with, we should have access if those
+ // roles were indeed propagated correctly.
+ assertTrue(
+ "Did not have access to protected servlet from within public servlet. " +
+ " Perhaps the roles did not propogate from JASPIC to JACC?",
+ response.contains("Has access to /protected/servlet: true")
+ );
+ }
+
+ @Test
+ public void callingJACCWhenNotAuthenticated() {
+
+ String response = getFromServerPath("public/servlet");
+
+ // This can basically only fail if JACC itself somehow doesn't work.
+ // Unfortunately this is the case for a bunch of certified servers, which
+ // either demand some activation of JACC, or don't ship with a default
+ // provider at all (which are both spec violations)
+ assertFalse(
+ "JACC doesn't seem to be available.",
+ response.contains("JACC doesn't seem to be available.")
+ );
+
+ // Test if we have access to public/servlet. This would be rare to fail
+ assertTrue(
+ "Did not have access to public servlet from within that Servlet. " +
+ " Something is seriously wrong.",
+ response.contains("Has access to /public/servlet: true")
+ );
+
+ // Test that we do NOT have access to protected/servlet. Passing this test
+ // doesn't necessarily means JASPIC to JACC propagation works correctly, as it will also pass if
+ // JACC doesn't work at all. Failing this test does indicate that something is wrong.
+ assertTrue(
+ "Has access to protected servlet from within public servlet without being authenticated. " +
+ " This should not be the case.",
+ response.contains("Has access to /protected/servlet: false")
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/lifecycle/pom.xml b/jaspic/lifecycle/pom.xml
new file mode 100644
index 000000000..1827d8de4
--- /dev/null
+++ b/jaspic/lifecycle/pom.xml
@@ -0,0 +1,24 @@
+
+
+ 4.0.0
+
+
+ org.javaee7
+ jaspic
+ 1.0-SNAPSHOT
+ ../pom.xml
+
+ org.javaee7
+ jaspic-lifecycle
+ 1.0-SNAPSHOT
+ war
+ Java EE 7 Sample: jaspic - lifecycle
+
+
+
+ org.javaee7
+ jaspic-common
+ 1.0-SNAPSHOT
+
+
+
diff --git a/jaspic/lifecycle/src/main/java/org/javaee7/jaspic/lifecycle/sam/SamAutoRegistrationListener.java b/jaspic/lifecycle/src/main/java/org/javaee7/jaspic/lifecycle/sam/SamAutoRegistrationListener.java
new file mode 100644
index 000000000..bab879840
--- /dev/null
+++ b/jaspic/lifecycle/src/main/java/org/javaee7/jaspic/lifecycle/sam/SamAutoRegistrationListener.java
@@ -0,0 +1,22 @@
+package org.javaee7.jaspic.lifecycle.sam;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.annotation.WebListener;
+
+import org.javaee7.jaspic.common.BaseServletContextListener;
+import org.javaee7.jaspic.common.JaspicUtils;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebListener
+public class SamAutoRegistrationListener extends BaseServletContextListener {
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ JaspicUtils.registerSAM(sce.getServletContext(), new TestLifecycleAuthModule());
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/lifecycle/src/main/java/org/javaee7/jaspic/lifecycle/sam/TestLifecycleAuthModule.java b/jaspic/lifecycle/src/main/java/org/javaee7/jaspic/lifecycle/sam/TestLifecycleAuthModule.java
new file mode 100644
index 000000000..3361d0721
--- /dev/null
+++ b/jaspic/lifecycle/src/main/java/org/javaee7/jaspic/lifecycle/sam/TestLifecycleAuthModule.java
@@ -0,0 +1,92 @@
+package org.javaee7.jaspic.lifecycle.sam;
+
+import static javax.security.auth.message.AuthStatus.SEND_SUCCESS;
+import static javax.security.auth.message.AuthStatus.SUCCESS;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.AuthStatus;
+import javax.security.auth.message.MessageInfo;
+import javax.security.auth.message.MessagePolicy;
+import javax.security.auth.message.callback.CallerPrincipalCallback;
+import javax.security.auth.message.callback.GroupPrincipalCallback;
+import javax.security.auth.message.module.ServerAuthModule;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * A test SAM that always authenticates a hard-coded user "test" with role "architect" for every request.
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class TestLifecycleAuthModule implements ServerAuthModule {
+
+ private CallbackHandler handler;
+ private Class>[] supportedMessageTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class };
+
+ @Override
+ public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler,
+ @SuppressWarnings("rawtypes") Map options) throws AuthException {
+ this.handler = handler;
+ }
+
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject)
+ throws AuthException {
+
+ HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();
+
+ try {
+ response.getWriter().write("validateRequest invoked\n");
+
+ boolean isMandatory = Boolean.valueOf((String) messageInfo.getMap().get("javax.security.auth.message.MessagePolicy.isMandatory"));
+
+ response.getWriter().write("isMandatory: " + isMandatory + "\n");
+
+ handler.handle(new Callback[] {
+ new CallerPrincipalCallback(clientSubject, "test"),
+ new GroupPrincipalCallback(clientSubject, new String[] { "architect" }) });
+ } catch (IOException | UnsupportedCallbackException e) {
+ throw (AuthException) new AuthException().initCause(e);
+ }
+
+ return SUCCESS;
+ }
+
+ @Override
+ public Class>[] getSupportedMessageTypes() {
+ return supportedMessageTypes;
+ }
+
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+
+ HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();
+
+ try {
+ response.getWriter().write("secureResponse invoked\n");
+ } catch (IOException e) {
+ throw (AuthException) new AuthException().initCause(e);
+ }
+
+ return SEND_SUCCESS;
+ }
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+ HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();
+
+ try {
+ response.getWriter().write("cleanSubject invoked\n");
+ } catch (IOException e) {
+ throw (AuthException) new AuthException().initCause(e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/jaspic/lifecycle/src/main/java/org/javaee7/jaspic/lifecycle/servlet/ProtectedServlet.java b/jaspic/lifecycle/src/main/java/org/javaee7/jaspic/lifecycle/servlet/ProtectedServlet.java
new file mode 100644
index 000000000..b5fbfecd4
--- /dev/null
+++ b/jaspic/lifecycle/src/main/java/org/javaee7/jaspic/lifecycle/servlet/ProtectedServlet.java
@@ -0,0 +1,30 @@
+package org.javaee7.jaspic.lifecycle.servlet;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/protected/servlet")
+public class ProtectedServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.getWriter().write("Resource invoked\n");
+
+ if (request.getParameter("doLogout") != null) {
+ request.logout();
+ }
+ }
+
+}
diff --git a/jaspic/lifecycle/src/main/java/org/javaee7/jaspic/lifecycle/servlet/PublicServlet.java b/jaspic/lifecycle/src/main/java/org/javaee7/jaspic/lifecycle/servlet/PublicServlet.java
new file mode 100644
index 000000000..ac982795d
--- /dev/null
+++ b/jaspic/lifecycle/src/main/java/org/javaee7/jaspic/lifecycle/servlet/PublicServlet.java
@@ -0,0 +1,30 @@
+package org.javaee7.jaspic.lifecycle.servlet;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/public/servlet")
+public class PublicServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.getWriter().write("Public resource invoked\n");
+
+ if (request.getParameter("doLogout") != null) {
+ request.logout();
+ }
+ }
+
+}
diff --git a/jaspic/lifecycle/src/main/webapp/WEB-INF/glassfish-web.xml b/jaspic/lifecycle/src/main/webapp/WEB-INF/glassfish-web.xml
new file mode 100644
index 000000000..26559e3f6
--- /dev/null
+++ b/jaspic/lifecycle/src/main/webapp/WEB-INF/glassfish-web.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ architect
+ architect
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/lifecycle/src/main/webapp/WEB-INF/ibm-application-bnd.xml b/jaspic/lifecycle/src/main/webapp/WEB-INF/ibm-application-bnd.xml
new file mode 100644
index 000000000..9aa892cbc
--- /dev/null
+++ b/jaspic/lifecycle/src/main/webapp/WEB-INF/ibm-application-bnd.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/lifecycle/src/main/webapp/WEB-INF/jboss-web.xml b/jaspic/lifecycle/src/main/webapp/WEB-INF/jboss-web.xml
new file mode 100644
index 000000000..2c14aa4f8
--- /dev/null
+++ b/jaspic/lifecycle/src/main/webapp/WEB-INF/jboss-web.xml
@@ -0,0 +1,4 @@
+
+
+ jaspitest
+
diff --git a/jaspic/lifecycle/src/main/webapp/WEB-INF/web.xml b/jaspic/lifecycle/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..ffd58ffa6
--- /dev/null
+++ b/jaspic/lifecycle/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Test
+ /protected/*
+
+
+ architect
+
+
+
+
+ architect
+
+
+
\ No newline at end of file
diff --git a/jaspic/lifecycle/src/test/java/org/javaee7/jaspic/lifecycle/AuthModuleMethodInvocationTest.java b/jaspic/lifecycle/src/test/java/org/javaee7/jaspic/lifecycle/AuthModuleMethodInvocationTest.java
new file mode 100644
index 000000000..919bcddf5
--- /dev/null
+++ b/jaspic/lifecycle/src/test/java/org/javaee7/jaspic/lifecycle/AuthModuleMethodInvocationTest.java
@@ -0,0 +1,86 @@
+package org.javaee7.jaspic.lifecycle;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import javax.security.auth.message.module.ServerAuthModule;
+import javax.servlet.http.HttpServletRequest;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * This tests that the two main methods of a SAM, {@link ServerAuthModule#validateRequest} and
+ * {@link ServerAuthModule#secureResponse} are called at the right time, which is resp. before and after the resource (e.g. a
+ * Servlet) is invoked.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class AuthModuleMethodInvocationTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ /**
+ * Test that the main SAM methods are called and are called in the correct order.
+ *
+ * The rule seems simple:
+ *
+ * First call validateRequest() in the SAM.
+ * Then invoke the requested resource (e.g. a Servlet or JSP page)
+ * Finally call secureResponse() in the SAM
+ *
+ */
+ @Test
+ public void testBasicSAMMethodsCalled() throws IOException, SAXException {
+
+ String response = getFromServerPath("protected/servlet");
+
+ // First test if individual methods are called
+ assertTrue("SAM method validateRequest not called, but should have been.",
+ response.contains("validateRequest invoked"));
+ assertTrue("Resource (Servlet) not invoked, but should have been.", response.contains("Resource invoked"));
+
+ // The previous two methods are rare to not be called, but secureResponse is more likely to fail. Seemingly it's hard
+ // to understand what this method should do exactly.
+ assertTrue("SAM method secureResponse not called, but should have been.",
+ response.contains("secureResponse invoked"));
+
+ int validateRequestIndex = response.indexOf("validateRequest invoked");
+ int resourceIndex = response.indexOf("Resource invoked");
+ int secureResponseIndex = response.indexOf("secureResponse invoked");
+
+ // Finally the order should be correct. More than a few implementations call secureResponse before the resource is
+ // invoked.
+ assertTrue("SAM methods called in wrong order",
+ validateRequestIndex < resourceIndex && resourceIndex < secureResponseIndex);
+ }
+
+ /**
+ * Test that the SAM's cleanSubject method is called following a call to {@link HttpServletRequest#logout()}.
+ *
+ * Although occasionally a JASPIC 1.0 implementation indeed does this, it's only mandated that this happens in JASPIC 1.1
+ */
+ @Test
+ public void testLogout() throws IOException, SAXException {
+
+ // Note that we don't explicitly log-in; the test SAM uses for this test does that automatically before the resource
+ // (servlet)
+ // is invoked. Once we reach the Servlet we should be logged-in and can proceed to logout.
+ String response = getFromServerPath("protected/servlet?doLogout=true");
+
+ assertTrue("SAM method cleanSubject not called, but should have been.",
+ response.contains("cleanSubject invoked"));
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/lifecycle/src/test/java/org/javaee7/jaspic/lifecycle/IsMandatoryTest.java b/jaspic/lifecycle/src/test/java/org/javaee7/jaspic/lifecycle/IsMandatoryTest.java
new file mode 100644
index 000000000..8eb327ae9
--- /dev/null
+++ b/jaspic/lifecycle/src/test/java/org/javaee7/jaspic/lifecycle/IsMandatoryTest.java
@@ -0,0 +1,55 @@
+package org.javaee7.jaspic.lifecycle;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * This tests that the "javax.security.auth.message.MessagePolicy.isMandatory" key
+ * in the message info map is "true" for a protected resource, and not "true" for
+ * a public resource.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class IsMandatoryTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void testPublicIsNonMandatory() throws IOException, SAXException {
+
+ String response = getFromServerPath("public/servlet");
+
+ assertTrue("Resource (Servlet) not invoked, but should have been.", response.contains("Public resource invoked"));
+
+ assertTrue("isMandatory should be false for public resource, but was not.",
+ response.contains("isMandatory: false"));
+ }
+
+ @Test
+ public void testProtectedIsMandatory() throws IOException, SAXException {
+
+ String response = getFromServerPath("protected/servlet");
+
+ assertTrue("Resource (Servlet) not invoked, but should have been.", response.contains("Resource invoked"));
+
+ assertTrue("isMandatory should be true for protected resource, but was not.",
+ response.contains("isMandatory: true"));
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/jaspic/pom.xml b/jaspic/pom.xml
new file mode 100644
index 000000000..fe046c0b3
--- /dev/null
+++ b/jaspic/pom.xml
@@ -0,0 +1,88 @@
+
+ 4.0.0
+
+
+ org.javaee7
+ samples-parent
+ 1.0-SNAPSHOT
+
+
+ jaspic
+ pom
+
+ Java EE 7 Sample: jaspic
+
+
+
+ common
+
+
+ basic-authentication
+
+
+ custom-principal
+
+
+ programmatic-authentication
+
+
+ lifecycle
+
+
+ wrapping
+
+
+ register-session
+
+
+ async-authentication
+
+
+ status-codes
+
+
+ dispatching
+
+
+ dispatching-jsf-cdi
+
+
+ ejb-propagation
+
+
+ ejb-register-session
+
+
+ jacc-propagation
+
+
+ invoke-ejb-cdi
+
+
+
+
+
+ org.javaee7
+ test-utils
+ ${project.version}
+ test
+
+
+
+
diff --git a/jaspic/programmatic-authentication/pom.xml b/jaspic/programmatic-authentication/pom.xml
new file mode 100644
index 000000000..6530ad2ee
--- /dev/null
+++ b/jaspic/programmatic-authentication/pom.xml
@@ -0,0 +1,23 @@
+
+
+ 4.0.0
+
+
+ org.javaee7
+ jaspic
+ 1.0-SNAPSHOT
+
+
+ jaspic-programmatic-authentication
+ war
+
+ Java EE 7 Sample: jaspic - programmatic-authentication
+
+
+
+ org.javaee7
+ jaspic-common
+ 1.0-SNAPSHOT
+
+
+
diff --git a/jaspic/programmatic-authentication/src/main/java/org/javaee7/jaspic/programmaticauthentication/sam/SamAutoRegistrationListener.java b/jaspic/programmatic-authentication/src/main/java/org/javaee7/jaspic/programmaticauthentication/sam/SamAutoRegistrationListener.java
new file mode 100644
index 000000000..202575e5f
--- /dev/null
+++ b/jaspic/programmatic-authentication/src/main/java/org/javaee7/jaspic/programmaticauthentication/sam/SamAutoRegistrationListener.java
@@ -0,0 +1,22 @@
+package org.javaee7.jaspic.programmaticauthentication.sam;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.annotation.WebListener;
+
+import org.javaee7.jaspic.common.BaseServletContextListener;
+import org.javaee7.jaspic.common.JaspicUtils;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebListener
+public class SamAutoRegistrationListener extends BaseServletContextListener {
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ JaspicUtils.registerSAM(sce.getServletContext(), new TestServerAuthModule());
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/programmatic-authentication/src/main/java/org/javaee7/jaspic/programmaticauthentication/sam/TestServerAuthModule.java b/jaspic/programmatic-authentication/src/main/java/org/javaee7/jaspic/programmaticauthentication/sam/TestServerAuthModule.java
new file mode 100644
index 000000000..b4a057502
--- /dev/null
+++ b/jaspic/programmatic-authentication/src/main/java/org/javaee7/jaspic/programmaticauthentication/sam/TestServerAuthModule.java
@@ -0,0 +1,95 @@
+package org.javaee7.jaspic.programmaticauthentication.sam;
+
+import static javax.security.auth.message.AuthStatus.SEND_SUCCESS;
+import static javax.security.auth.message.AuthStatus.SUCCESS;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.AuthStatus;
+import javax.security.auth.message.MessageInfo;
+import javax.security.auth.message.MessagePolicy;
+import javax.security.auth.message.callback.CallerPrincipalCallback;
+import javax.security.auth.message.callback.GroupPrincipalCallback;
+import javax.security.auth.message.module.ServerAuthModule;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Very basic SAM that returns a single hardcoded user named "test" with role "architect" when the request *attribute*
+ * doLogin is present.
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class TestServerAuthModule implements ServerAuthModule {
+
+ private CallbackHandler handler;
+ private Class>[] supportedMessageTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class };
+
+ @Override
+ public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler,
+ @SuppressWarnings("rawtypes") Map options) throws AuthException {
+ this.handler = handler;
+ }
+
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject)
+ throws AuthException {
+
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+
+ Callback[] callbacks;
+
+ if (request.getAttribute("doLogin") != null) { // notice "getAttribute" here, this is set by the Servlet
+
+ // For the test perform a login by directly "returning" the details of the authenticated user.
+ // Normally credentials would be checked and the details fetched from some repository
+
+ callbacks = new Callback[] {
+ // The name of the authenticated user
+ new CallerPrincipalCallback(clientSubject, "test"),
+ // the roles of the authenticated user
+ new GroupPrincipalCallback(clientSubject, new String[] { "architect" })
+ };
+ } else {
+
+ // The JASPIC protocol for "do nothing"
+ callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, (Principal) null) };
+ }
+
+ try {
+
+ // Communicate the details of the authenticated user to the container. In many
+ // cases the handler will just store the details and the container will actually handle
+ // the login after we return from this method.
+ handler.handle(callbacks);
+
+ } catch (IOException | UnsupportedCallbackException e) {
+ throw (AuthException) new AuthException().initCause(e);
+ }
+
+ return SUCCESS;
+ }
+
+ @Override
+ public Class>[] getSupportedMessageTypes() {
+ return supportedMessageTypes;
+ }
+
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+ return SEND_SUCCESS;
+ }
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+
+ }
+}
\ No newline at end of file
diff --git a/jaspic/programmatic-authentication/src/main/java/org/javaee7/jaspic/programmaticauthentication/servlet/AuthenticateServlet.java b/jaspic/programmatic-authentication/src/main/java/org/javaee7/jaspic/programmaticauthentication/servlet/AuthenticateServlet.java
new file mode 100644
index 000000000..3bafb7416
--- /dev/null
+++ b/jaspic/programmatic-authentication/src/main/java/org/javaee7/jaspic/programmaticauthentication/servlet/AuthenticateServlet.java
@@ -0,0 +1,73 @@
+package org.javaee7.jaspic.programmaticauthentication.servlet;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/public/authenticate")
+public class AuthenticateServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ response.getWriter().write("This is a public servlet \n");
+
+ String webName = null;
+ if (request.getUserPrincipal() != null) {
+ webName = request.getUserPrincipal().getName();
+ }
+
+ response.getWriter().write("before web username: " + webName + "\n");
+ boolean webHasRole = request.isUserInRole("architect");
+ response.getWriter().write("before web user has role \"architect\": " + webHasRole + "\n");
+
+ // By *not* setting the "doLogin" request attribute the request.authenticate call
+ // would do nothing. request.authenticate is a mandatory authentication, so doing
+ // nothing is not allowed. But one or more initial failures should not prevent
+ // a later successful authentication.
+ if (request.getParameter("failFirst") != null) {
+ try {
+ request.authenticate(response);
+ } catch (IOException | ServletException e) {
+ // GlassFish returns false when either authentication is in progress or authentication
+ // failed (or was not done at all), but JBoss throws an exception.
+ // TODO: Get clarification what is actually expected, likely exception is most correct.
+ // Then test for the correct return value.
+ }
+ }
+
+ if ("2".equals(request.getParameter("failFirst"))) {
+ try {
+ request.authenticate(response);
+ } catch (IOException | ServletException e) {
+ }
+ }
+
+ // Programmatically trigger the authentication chain
+ request.setAttribute("doLogin", true);
+ boolean authenticateOutcome = request.authenticate(response);
+
+ if (request.getUserPrincipal() != null) {
+ webName = request.getUserPrincipal().getName();
+ }
+
+ response.getWriter().write("request.authenticate outcome: " + authenticateOutcome + "\n");
+
+ response.getWriter().write("after web username: " + webName + "\n");
+ webHasRole = request.isUserInRole("architect");
+ response.getWriter().write("after web user has role \"architect\": " + webHasRole + "\n");
+
+ }
+
+}
diff --git a/jaspic/programmatic-authentication/src/main/webapp/WEB-INF/glassfish-web.xml b/jaspic/programmatic-authentication/src/main/webapp/WEB-INF/glassfish-web.xml
new file mode 100644
index 000000000..26559e3f6
--- /dev/null
+++ b/jaspic/programmatic-authentication/src/main/webapp/WEB-INF/glassfish-web.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ architect
+ architect
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/programmatic-authentication/src/main/webapp/WEB-INF/ibm-application-bnd.xml b/jaspic/programmatic-authentication/src/main/webapp/WEB-INF/ibm-application-bnd.xml
new file mode 100644
index 000000000..0775f1279
--- /dev/null
+++ b/jaspic/programmatic-authentication/src/main/webapp/WEB-INF/ibm-application-bnd.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/programmatic-authentication/src/main/webapp/WEB-INF/jboss-web.xml b/jaspic/programmatic-authentication/src/main/webapp/WEB-INF/jboss-web.xml
new file mode 100644
index 000000000..b6ab7d0ba
--- /dev/null
+++ b/jaspic/programmatic-authentication/src/main/webapp/WEB-INF/jboss-web.xml
@@ -0,0 +1,5 @@
+
+
+
+ jaspitest
+
diff --git a/jaspic/programmatic-authentication/src/main/webapp/WEB-INF/web.xml b/jaspic/programmatic-authentication/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..ffd58ffa6
--- /dev/null
+++ b/jaspic/programmatic-authentication/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Test
+ /protected/*
+
+
+ architect
+
+
+
+
+ architect
+
+
+
\ No newline at end of file
diff --git a/jaspic/programmatic-authentication/src/test/java/org/javaee7/jaspic/programmaticauthentication/ProgrammaticAuthenticationTest.java b/jaspic/programmatic-authentication/src/test/java/org/javaee7/jaspic/programmaticauthentication/ProgrammaticAuthenticationTest.java
new file mode 100644
index 000000000..2305c8b4b
--- /dev/null
+++ b/jaspic/programmatic-authentication/src/test/java/org/javaee7/jaspic/programmaticauthentication/ProgrammaticAuthenticationTest.java
@@ -0,0 +1,85 @@
+package org.javaee7.jaspic.programmaticauthentication;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * This tests that a call from a Servlet to HttpServletRequest#authenticate can result
+ * in a successful authentication.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class ProgrammaticAuthenticationTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void testAuthenticate() throws IOException, SAXException {
+ assertAuthenticated(getFromServerPath("public/authenticate"));
+ }
+
+ @Test
+ public void testAuthenticateFailFirstOnce() throws IOException, SAXException {
+ // Before authenticating successfully, call request.authenticate which
+ // is known to fail (do nothing)
+ assertAuthenticated(getFromServerPath("public/authenticate?failFirst=1"));
+ }
+
+ @Test
+ public void testAuthenticateFailFirstTwice() throws IOException, SAXException {
+ // Before authenticating successfully, call request.authenticate twice which
+ // are both known to fail (do nothing)
+ assertAuthenticated(getFromServerPath("public/authenticate?failFirst=2"));
+ }
+
+ private void assertAuthenticated(String response) {
+
+ // Should not be authenticated in the "before" case, which is
+ // before request.authentiate is called
+ assertTrue(
+ "Should not be authenticated yet, but a username other than null was encountered. " +
+ "This is not correct.",
+ response.contains("before web username: null")
+ );
+ assertTrue(
+ "Should not be authenticated yet, but the user seems to have the role \"architect\". " +
+ "This is not correct.",
+ response.contains("before web user has role \"architect\": false")
+ );
+
+ // The main request.authenticate causes the SAM to be called which always authenticates
+ assertTrue(
+ "Calling request.authenticate should have returned true, but did not.",
+ response.contains("request.authenticate outcome: true")
+ );
+
+ // Should be authenticated in the "after" case, which is
+ // after request.authentiate is called
+ assertTrue(
+ "User should have been authenticated and given name \"test\", " +
+ " but does not appear to have this name",
+ response.contains("after web username: test")
+ );
+ assertTrue(
+ "User should have been authenticated and given role \"architect\", " +
+ " but does not appear to have this role",
+ response.contains("after web user has role \"architect\": true")
+ );
+ }
+
+
+}
\ No newline at end of file
diff --git a/jaspic/register-session/pom.xml b/jaspic/register-session/pom.xml
new file mode 100644
index 000000000..80a5a597f
--- /dev/null
+++ b/jaspic/register-session/pom.xml
@@ -0,0 +1,23 @@
+
+
+ 4.0.0
+
+
+ org.javaee7
+ jaspic
+ 1.0-SNAPSHOT
+
+
+ jaspic-register-session
+ war
+ Java EE 7 Sample: jaspic - register-session
+
+
+
+ org.javaee7
+ jaspic-common
+ 1.0-SNAPSHOT
+
+
+
+
diff --git a/jaspic/register-session/src/main/java/org/javaee7/jaspic/registersession/sam/MyPrincipal.java b/jaspic/register-session/src/main/java/org/javaee7/jaspic/registersession/sam/MyPrincipal.java
new file mode 100644
index 000000000..6cb47c75b
--- /dev/null
+++ b/jaspic/register-session/src/main/java/org/javaee7/jaspic/registersession/sam/MyPrincipal.java
@@ -0,0 +1,23 @@
+package org.javaee7.jaspic.registersession.sam;
+
+import java.security.Principal;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class MyPrincipal implements Principal {
+
+ private final String name;
+
+ public MyPrincipal(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+}
diff --git a/jaspic/register-session/src/main/java/org/javaee7/jaspic/registersession/sam/SamAutoRegistrationListener.java b/jaspic/register-session/src/main/java/org/javaee7/jaspic/registersession/sam/SamAutoRegistrationListener.java
new file mode 100644
index 000000000..2241d934c
--- /dev/null
+++ b/jaspic/register-session/src/main/java/org/javaee7/jaspic/registersession/sam/SamAutoRegistrationListener.java
@@ -0,0 +1,22 @@
+package org.javaee7.jaspic.registersession.sam;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.annotation.WebListener;
+
+import org.javaee7.jaspic.common.BaseServletContextListener;
+import org.javaee7.jaspic.common.JaspicUtils;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebListener
+public class SamAutoRegistrationListener extends BaseServletContextListener {
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ JaspicUtils.registerSAM(sce.getServletContext(), new TestServerAuthModule());
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/register-session/src/main/java/org/javaee7/jaspic/registersession/sam/TestServerAuthModule.java b/jaspic/register-session/src/main/java/org/javaee7/jaspic/registersession/sam/TestServerAuthModule.java
new file mode 100644
index 000000000..89ea01287
--- /dev/null
+++ b/jaspic/register-session/src/main/java/org/javaee7/jaspic/registersession/sam/TestServerAuthModule.java
@@ -0,0 +1,116 @@
+package org.javaee7.jaspic.registersession.sam;
+
+import static java.lang.Boolean.TRUE;
+import static javax.security.auth.message.AuthStatus.SUCCESS;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.AuthStatus;
+import javax.security.auth.message.MessageInfo;
+import javax.security.auth.message.MessagePolicy;
+import javax.security.auth.message.callback.CallerPrincipalCallback;
+import javax.security.auth.message.callback.GroupPrincipalCallback;
+import javax.security.auth.message.module.ServerAuthModule;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class TestServerAuthModule implements ServerAuthModule {
+
+ private CallbackHandler handler;
+ private Class>[] supportedMessageTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class };
+
+ @Override
+ public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler,
+ @SuppressWarnings("rawtypes") Map options) throws AuthException {
+ this.handler = handler;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject)
+ throws AuthException {
+
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+ Callback[] callbacks;
+
+ Principal userPrincipal = request.getUserPrincipal();
+ if (userPrincipal != null && request.getParameter("continueSession") != null) {
+
+ // ### If already authenticated before, continue this session
+
+ // Execute protocol to signal container registered authentication session be used.
+ callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, userPrincipal) };
+
+ } else if (request.getParameter("doLogin") != null) {
+
+ // ### If not authenticated before, do a new login if so requested
+
+ // For the test perform a login by directly "returning" the details of the authenticated user.
+ // Normally credentials would be checked and the details fetched from some repository
+
+ callbacks = new Callback[] {
+ // The name of the authenticated user
+
+ request.getParameter("customPrincipal") == null?
+ // Name based Callback
+ new CallerPrincipalCallback(clientSubject, "test") :
+
+ // Custom principal based Callback
+ new CallerPrincipalCallback(clientSubject, new MyPrincipal("test")),
+
+
+ // the roles of the authenticated user
+ new GroupPrincipalCallback(clientSubject, new String[] { "architect" }) };
+
+ // Tell container to register an authentication session.
+ messageInfo.getMap().put("javax.servlet.http.registerSession", TRUE.toString());
+ } else {
+
+ // ### If no registered session and no login request "do nothing"
+
+ // The JASPIC protocol for "do nothing"
+ callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, (Principal) null) };
+ }
+
+ try {
+
+ // Communicate the details of the authenticated user to the container. In many
+ // cases the handler will just store the details and the container will actually handle
+ // the login after we return from this method.
+ handler.handle(callbacks);
+
+ } catch (IOException | UnsupportedCallbackException e) {
+ throw (AuthException) new AuthException().initCause(e);
+ }
+
+ return SUCCESS;
+ }
+
+ @Override
+ public Class>[] getSupportedMessageTypes() {
+ return supportedMessageTypes;
+ }
+
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+ return AuthStatus.SEND_SUCCESS;
+ }
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+
+ }
+}
\ No newline at end of file
diff --git a/jaspic/register-session/src/main/java/org/javaee7/jaspic/registersession/servlet/ProtectedServlet.java b/jaspic/register-session/src/main/java/org/javaee7/jaspic/registersession/servlet/ProtectedServlet.java
new file mode 100644
index 000000000..2aaa54248
--- /dev/null
+++ b/jaspic/register-session/src/main/java/org/javaee7/jaspic/registersession/servlet/ProtectedServlet.java
@@ -0,0 +1,54 @@
+package org.javaee7.jaspic.registersession.servlet;
+
+import java.io.IOException;
+import java.security.Principal;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.javaee7.jaspic.registersession.sam.MyPrincipal;
+
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/protected/servlet")
+public class ProtectedServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ response.getWriter().write("This is a protected servlet \n");
+
+ String webName = null;
+ boolean isCustomPrincipal = false;
+ if (request.getUserPrincipal() != null) {
+ Principal principal = request.getUserPrincipal();
+ isCustomPrincipal = principal instanceof MyPrincipal;
+ webName = request.getUserPrincipal().getName();
+ }
+
+ boolean webHasRole = request.isUserInRole("architect");
+
+ response.getWriter().write("isCustomPrincipal: " + isCustomPrincipal + "\n");
+ response.getWriter().write("web username: " + webName + "\n");
+ response.getWriter().write("web user has role \"architect\": " + webHasRole + "\n");
+
+ HttpSession session = request.getSession(false);
+ if (session != null) {
+ response.getWriter().write("Session ID: " + session.getId());
+ } else {
+ response.getWriter().write("No session");
+ }
+
+ }
+
+}
diff --git a/jaspic/register-session/src/main/java/org/javaee7/jaspic/registersession/servlet/PublicServlet.java b/jaspic/register-session/src/main/java/org/javaee7/jaspic/registersession/servlet/PublicServlet.java
new file mode 100644
index 000000000..c6c022b33
--- /dev/null
+++ b/jaspic/register-session/src/main/java/org/javaee7/jaspic/registersession/servlet/PublicServlet.java
@@ -0,0 +1,54 @@
+package org.javaee7.jaspic.registersession.servlet;
+
+import java.io.IOException;
+import java.security.Principal;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.javaee7.jaspic.registersession.sam.MyPrincipal;
+
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/public/servlet")
+public class PublicServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ response.getWriter().write("This is a public servlet \n");
+
+ String webName = null;
+ boolean isCustomPrincipal = false;
+ if (request.getUserPrincipal() != null) {
+ Principal principal = request.getUserPrincipal();
+ isCustomPrincipal = principal instanceof MyPrincipal;
+ webName = principal.getName();
+ }
+
+ boolean webHasRole = request.isUserInRole("architect");
+
+ response.getWriter().write("isCustomPrincipal: " + isCustomPrincipal + "\n");
+ response.getWriter().write("web username: " + webName + "\n");
+ response.getWriter().write("web user has role \"architect\": " + webHasRole + "\n");
+
+ HttpSession session = request.getSession(false);
+ if (session != null) {
+ response.getWriter().write("Session ID: " + session.getId());
+ } else {
+ response.getWriter().write("No session");
+ }
+
+ }
+
+}
diff --git a/jaspic/register-session/src/main/webapp/WEB-INF/glassfish-web.xml b/jaspic/register-session/src/main/webapp/WEB-INF/glassfish-web.xml
new file mode 100644
index 000000000..26559e3f6
--- /dev/null
+++ b/jaspic/register-session/src/main/webapp/WEB-INF/glassfish-web.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ architect
+ architect
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/register-session/src/main/webapp/WEB-INF/ibm-application-bnd.xml b/jaspic/register-session/src/main/webapp/WEB-INF/ibm-application-bnd.xml
new file mode 100644
index 000000000..9aa892cbc
--- /dev/null
+++ b/jaspic/register-session/src/main/webapp/WEB-INF/ibm-application-bnd.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/register-session/src/main/webapp/WEB-INF/jboss-web.xml b/jaspic/register-session/src/main/webapp/WEB-INF/jboss-web.xml
new file mode 100644
index 000000000..2c14aa4f8
--- /dev/null
+++ b/jaspic/register-session/src/main/webapp/WEB-INF/jboss-web.xml
@@ -0,0 +1,4 @@
+
+
+ jaspitest
+
diff --git a/jaspic/register-session/src/main/webapp/WEB-INF/web.xml b/jaspic/register-session/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..0ed6791b4
--- /dev/null
+++ b/jaspic/register-session/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+ Test
+ /protected/*
+
+
+ architect
+
+
+
+
+ architect
+
+
+
\ No newline at end of file
diff --git a/jaspic/register-session/src/test/java/org/javaee7/jaspic/registersession/RegisterSessionCustomPrincipalTest.java b/jaspic/register-session/src/test/java/org/javaee7/jaspic/registersession/RegisterSessionCustomPrincipalTest.java
new file mode 100644
index 000000000..cc0082a92
--- /dev/null
+++ b/jaspic/register-session/src/test/java/org/javaee7/jaspic/registersession/RegisterSessionCustomPrincipalTest.java
@@ -0,0 +1,197 @@
+package org.javaee7.jaspic.registersession;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * Variant of the {@link RegisterSessionTest}, where a custom principal is used instead
+ * of a container provided one. This is particularly challenging since the SAM has to
+ * pass the principal obtained from HttpServletRequest into the CallbackHandler, which
+ * then somehow has to recognize this as the signal to continue an authenticated session.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class RegisterSessionCustomPrincipalTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void testRemembersSession() throws IOException, SAXException {
+
+ // -------------------- Request 1 ---------------------------
+
+ // Accessing protected page without login
+ String response = getFromServerPath("protected/servlet");
+
+ // Not logged-in thus should not be accessible.
+ assertFalse(response.contains("This is a protected servlet"));
+
+
+ // -------------------- Request 2 ---------------------------
+
+ // We access the protected page again and now login
+
+ response = getFromServerPath("protected/servlet?doLogin=true&customPrincipal=true");
+
+ // Now has to be logged-in so page is accessible
+ assertTrue(
+ "Could not access protected page, but should be able to. " +
+ "Did the container remember the previously set 'unauthenticated identity'?",
+ response.contains("This is a protected servlet")
+ );
+
+ // Check principal has right name and right type and roles are available
+ checkAuthenticatedIdentity(response);
+
+
+ // -------------------- Request 3 ---------------------------
+
+ // JASPIC is normally stateless, but for this test the SAM uses the register session feature so now
+ // we should be logged-in when doing a call without explicitly logging in again.
+
+ response = getFromServerPath("protected/servlet?continueSession=true");
+
+ // Logged-in thus should be accessible.
+ assertTrue(
+ "Could not access protected page, but should be able to. " +
+ "Did the container not remember the authenticated identity via 'javax.servlet.http.registerSession'?",
+ response.contains("This is a protected servlet")
+ );
+
+ // Both the user name and roles/groups have to be restored
+
+ // *** NOTE ***: The JASPIC 1.1 spec is NOT clear about remembering roles, but spec lead Ron Monzillo clarified that
+ // this should indeed be the case. The next JASPIC revision of the spec will have to mention this explicitly.
+ // Intuitively it should make sense though that the authenticated identity is fully restored and not partially,
+ // but again the spec should make this clear to avoid ambiguity.
+
+ checkAuthenticatedIdentity(response);
+
+ // -------------------- Request 4 ---------------------------
+
+ // The session should also be remembered for other resources, including public ones
+
+ response = getFromServerPath("public/servlet?continueSession=true");
+
+ // This test almost can't fail, but include for clarity
+ assertTrue(response.contains("This is a public servlet"));
+
+ // When accessing the public page, the username and roles should be restored and be available
+ // just as on protected pages
+ checkAuthenticatedIdentity(response);
+ }
+
+ @Test
+ public void testJoinSessionIsOptional() throws IOException, SAXException {
+
+ // -------------------- Request 1 ---------------------------
+
+ // We access a protected page and login
+ //
+
+ String response = getFromServerPath("protected/servlet?doLogin=true&customPrincipal=true");
+
+ // Now has to be logged-in so page is accessible
+ assertTrue(
+ "Could not access protected page, but should be able to. " +
+ "Did the container remember the previously set 'unauthenticated identity'?",
+ response.contains("This is a protected servlet")
+ );
+
+ // Check principal has right name and right type and roles are available
+ checkAuthenticatedIdentity(response);
+
+
+
+
+ // -------------------- Request 2 ---------------------------
+
+ // JASPIC is normally stateless, but for this test the SAM uses the register session feature so now
+ // we should be logged-in when doing a call without explicitly logging in again.
+
+ response = getFromServerPath("protected/servlet?continueSession=true");
+
+ // Logged-in thus should be accessible.
+ assertTrue(
+ "Could not access protected page, but should be able to. " +
+ "Did the container not remember the authenticated identity via 'javax.servlet.http.registerSession'?",
+ response.contains("This is a protected servlet")
+ );
+
+ // Both the user name and roles/groups have to be restored
+
+ // *** NOTE ***: The JASPIC 1.1 spec is NOT clear about remembering roles, but spec lead Ron Monzillo clarified that
+ // this should indeed be the case. The next JASPIC revision of the spec will have to mention this explicitly.
+ // Intuitively it should make sense though that the authenticated identity is fully restored and not partially,
+ // but again the spec should make this clear to avoid ambiguity.
+ // Check principal has right name and right type and roles are available
+ checkAuthenticatedIdentity(response);
+
+
+ // -------------------- Request 3 ---------------------------
+
+ // Although the container remembers the authentication session, the SAM needs to OPT-IN to it.
+ // If the SAM instead "does nothing", we should not have access to the protected resource anymore
+ // even within the same HTTP session.
+
+ response = getFromServerPath("protected/servlet");
+ assertFalse(response.contains("This is a protected servlet"));
+
+
+ // -------------------- Request 4 ---------------------------
+
+ // Access to a public page is unaffected by joining or not joining the session, but if we do not join the
+ // session we shouldn't see the user's name and roles.
+
+ response = getFromServerPath("public/servlet");
+
+ assertTrue(
+ "Could not access public page, but should be able to. " +
+ "Does the container have an automatic session fixation prevention?",
+ response.contains("This is a public servlet")
+ );
+ assertFalse(
+ "SAM did not join authentication session and should be anonymous, but username is name of session identity.",
+ response.contains("web username: test")
+ );
+ assertFalse(
+ "SAM did not join authentication session and should be anonymous without roles, but has role of session identity.",
+ response.contains("web user has role \"architect\": true")
+ );
+ }
+
+ private void checkAuthenticatedIdentity( String response) {
+
+ // Has to be logged-in with the right principal
+ assertTrue(
+ "Authenticated but username is not the expected one 'test'",
+ response.contains("web username: test")
+ );
+ assertTrue(
+ "Authentication succeeded and username is correct, but the expected role 'architect' is not present.",
+ response.contains("web user has role \"architect\": true"));
+
+ assertTrue(
+ "Authentication succeeded and username and roles are correct, but principal type is not the expected custom type.",
+ response.contains("isCustomPrincipal: true")
+ );
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/jaspic/register-session/src/test/java/org/javaee7/jaspic/registersession/RegisterSessionTest.java b/jaspic/register-session/src/test/java/org/javaee7/jaspic/registersession/RegisterSessionTest.java
new file mode 100644
index 000000000..254e972e5
--- /dev/null
+++ b/jaspic/register-session/src/test/java/org/javaee7/jaspic/registersession/RegisterSessionTest.java
@@ -0,0 +1,187 @@
+package org.javaee7.jaspic.registersession;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+@RunWith(Arquillian.class)
+public class RegisterSessionTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void testRemembersSession() throws IOException, SAXException {
+
+ // -------------------- Request 1 ---------------------------
+
+ // Accessing protected page without login
+ String response = getFromServerPath("protected/servlet");
+
+ // Not logged-in thus should not be accessible.
+ assertFalse(response.contains("This is a protected servlet"));
+
+
+ // -------------------- Request 2 ---------------------------
+
+ // We access the protected page again and now login
+
+ response = getFromServerPath("protected/servlet?doLogin=true");
+
+ // Now has to be logged-in so page is accessible
+ assertTrue(
+ "Could not access protected page, but should be able to. " +
+ "Did the container remember the previously set 'unauthenticated identity'?",
+ response.contains("This is a protected servlet")
+ );
+
+ // Check principal has right name and right type and roles are available
+ checkAuthenticatedIdentity(response);
+
+
+
+ // -------------------- Request 3 ---------------------------
+
+ // JASPIC is normally stateless, but for this test the SAM uses the register session feature so now
+ // we should be logged-in when doing a call without explicitly logging in again.
+
+ response = getFromServerPath("protected/servlet?continueSession=true");
+
+ // Logged-in thus should be accessible.
+ assertTrue(
+ "Could not access protected page, but should be able to. " +
+ "Did the container not remember the authenticated identity via 'javax.servlet.http.registerSession'?",
+ response.contains("This is a protected servlet")
+ );
+
+ // Both the user name and roles/groups have to be restored
+
+ // *** NOTE ***: The JASPIC 1.1 spec is NOT clear about remembering roles, but spec lead Ron Monzillo clarified that
+ // this should indeed be the case. The next JASPIC revision of the spec will have to mention this explicitly.
+ // Intuitively it should make sense though that the authenticated identity is fully restored and not partially,
+ // but again the spec should make this clear to avoid ambiguity.
+
+ // Check principal has right name and right type and roles are available
+ checkAuthenticatedIdentity(response);
+
+
+ // -------------------- Request 4 ---------------------------
+
+ // The session should also be remembered for other resources, including public ones
+
+ response = getFromServerPath("public/servlet?continueSession=true");
+
+ // This test almost can't fail, but include for clarity
+ assertTrue(response.contains("This is a public servlet"));
+
+ // When accessing the public page, the username and roles should be restored and be available
+ // just as on protected pages
+
+ // Check principal has right name and right type and roles are available
+ checkAuthenticatedIdentity(response);
+ }
+
+ @Test
+ public void testJoinSessionIsOptional() throws IOException, SAXException {
+
+ // -------------------- Request 1 ---------------------------
+
+ // We access a protected page and login
+ //
+
+ String response = getFromServerPath("protected/servlet?doLogin=true");
+
+ // Now has to be logged-in so page is accessible
+ assertTrue(
+ "Could not access protected page, but should be able to. " +
+ "Did the container remember the previously set 'unauthenticated identity'?",
+ response.contains("This is a protected servlet")
+ );
+
+
+ // -------------------- Request 2 ---------------------------
+
+ // JASPIC is normally stateless, but for this test the SAM uses the register session feature so now
+ // we should be logged-in when doing a call without explicitly logging in again.
+
+ response = getFromServerPath("protected/servlet?continueSession=true");
+
+ // Logged-in thus should be accessible.
+ assertTrue(
+ "Could not access protected page, but should be able to. " +
+ "Did the container not remember the authenticated identity via 'javax.servlet.http.registerSession'?",
+ response.contains("This is a protected servlet")
+ );
+
+ // Both the user name and roles/groups have to be restored
+
+ // *** NOTE ***: The JASPIC 1.1 spec is NOT clear about remembering roles, but spec lead Ron Monzillo clarified that
+ // this should indeed be the case. The next JASPIC revision of the spec will have to mention this explicitly.
+ // Intuitively it should make sense though that the authenticated identity is fully restored and not partially,
+ // but again the spec should make this clear to avoid ambiguity.
+
+ // Check principal has right name and right type and roles are available
+ checkAuthenticatedIdentity(response);
+
+
+ // -------------------- Request 3 ---------------------------
+
+ // Although the container remembers the authentication session, the SAM needs to OPT-IN to it.
+ // If the SAM instead "does nothing", we should not have access to the protected resource anymore
+ // even within the same HTTP session.
+
+ response = getFromServerPath("protected/servlet");
+ assertFalse(response.contains("This is a protected servlet"));
+
+
+ // -------------------- Request 4 ---------------------------
+
+ // Access to a public page is unaffected by joining or not joining the session, but if we do not join the
+ // session we shouldn't see the user's name and roles.
+
+ response = getFromServerPath("public/servlet");
+
+ assertTrue(
+ "Could not access public page, but should be able to. " +
+ "Does the container have an automatic session fixation prevention?",
+ response.contains("This is a public servlet")
+ );
+ assertFalse(
+ "SAM did not join authentication session and should be anonymous, but username is name of session identity.",
+ response.contains("web username: test")
+ );
+ assertFalse(
+ "SAM did not join authentication session and should be anonymous without roles, but has role of session identity.",
+ response.contains("web user has role \"architect\": true")
+ );
+ }
+
+ private void checkAuthenticatedIdentity(String response) {
+
+ // Has to be logged-in with the right principal
+ assertTrue(
+ "Authenticated but username is not the expected one 'test'",
+ response.contains("web username: test")
+ );
+ assertTrue(
+ "Authentication succeeded and username is correct, but the expected role 'architect' is not present.",
+ response.contains("web user has role \"architect\": true"));
+
+ // Note, for this test if the following fails if would be most likely be an error in the test setup code
+ assertTrue(
+ "Authentication succeeded and username and roles are correct, but principal type should not be the custom one",
+ response.contains("isCustomPrincipal: false")
+ );
+ }
+}
\ No newline at end of file
diff --git a/jaspic/status-codes/pom.xml b/jaspic/status-codes/pom.xml
new file mode 100644
index 000000000..85cc1d82e
--- /dev/null
+++ b/jaspic/status-codes/pom.xml
@@ -0,0 +1,23 @@
+
+
+ 4.0.0
+
+
+ org.javaee7
+ jaspic
+ 1.0-SNAPSHOT
+ ../pom.xml
+
+ jaspic-status-codes
+ war
+
+ Java EE 7 Sample: jaspic - Status codes
+
+
+
+ org.javaee7
+ jaspic-common
+ 1.0-SNAPSHOT
+
+
+
diff --git a/jaspic/status-codes/src/main/java/org/javaee7/jaspic/statuscodes/sam/SamAutoRegistrationListener.java b/jaspic/status-codes/src/main/java/org/javaee7/jaspic/statuscodes/sam/SamAutoRegistrationListener.java
new file mode 100644
index 000000000..85f3dcdcb
--- /dev/null
+++ b/jaspic/status-codes/src/main/java/org/javaee7/jaspic/statuscodes/sam/SamAutoRegistrationListener.java
@@ -0,0 +1,22 @@
+package org.javaee7.jaspic.statuscodes.sam;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.annotation.WebListener;
+
+import org.javaee7.jaspic.common.BaseServletContextListener;
+import org.javaee7.jaspic.common.JaspicUtils;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebListener
+public class SamAutoRegistrationListener extends BaseServletContextListener {
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ JaspicUtils.registerSAM(sce.getServletContext(), new TestServerAuthModule());
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/status-codes/src/main/java/org/javaee7/jaspic/statuscodes/sam/TestServerAuthModule.java b/jaspic/status-codes/src/main/java/org/javaee7/jaspic/statuscodes/sam/TestServerAuthModule.java
new file mode 100644
index 000000000..1e112e301
--- /dev/null
+++ b/jaspic/status-codes/src/main/java/org/javaee7/jaspic/statuscodes/sam/TestServerAuthModule.java
@@ -0,0 +1,62 @@
+package org.javaee7.jaspic.statuscodes.sam;
+
+import static javax.security.auth.message.AuthStatus.SEND_FAILURE;
+import static javax.security.auth.message.AuthStatus.SEND_SUCCESS;
+import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.AuthStatus;
+import javax.security.auth.message.MessageInfo;
+import javax.security.auth.message.MessagePolicy;
+import javax.security.auth.message.module.ServerAuthModule;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Very basic SAM that just sets an HTTP status code into the response and then returns SEND_FAILURE.
+ * doLogin is present.
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class TestServerAuthModule implements ServerAuthModule {
+
+ private Class>[] supportedMessageTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class };
+
+ @Override
+ public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler, @SuppressWarnings("rawtypes") Map options) throws AuthException {
+ }
+
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException {
+
+ HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();
+
+ try {
+ response.sendError(SC_NOT_FOUND);
+ return SEND_FAILURE;
+ } catch (IOException e) {
+ throw (AuthException) new AuthException().initCause(e);
+ }
+ }
+
+ @Override
+ public Class>[] getSupportedMessageTypes() {
+ return supportedMessageTypes;
+ }
+
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+ return SEND_SUCCESS;
+ }
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+
+ }
+}
\ No newline at end of file
diff --git a/jaspic/status-codes/src/main/java/org/javaee7/jaspic/statuscodes/servlet/ProtectedServlet.java b/jaspic/status-codes/src/main/java/org/javaee7/jaspic/statuscodes/servlet/ProtectedServlet.java
new file mode 100644
index 000000000..55a656398
--- /dev/null
+++ b/jaspic/status-codes/src/main/java/org/javaee7/jaspic/statuscodes/servlet/ProtectedServlet.java
@@ -0,0 +1,26 @@
+package org.javaee7.jaspic.statuscodes.servlet;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/protected/servlet")
+public class ProtectedServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.getWriter().write("This is a protected servlet \n");
+ }
+
+}
diff --git a/jaspic/status-codes/src/main/java/org/javaee7/jaspic/statuscodes/servlet/PublicServlet.java b/jaspic/status-codes/src/main/java/org/javaee7/jaspic/statuscodes/servlet/PublicServlet.java
new file mode 100644
index 000000000..0c8387c54
--- /dev/null
+++ b/jaspic/status-codes/src/main/java/org/javaee7/jaspic/statuscodes/servlet/PublicServlet.java
@@ -0,0 +1,26 @@
+package org.javaee7.jaspic.statuscodes.servlet;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/public/servlet")
+public class PublicServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.getWriter().write("This is a public servlet \n");
+ }
+
+}
diff --git a/jaspic/status-codes/src/main/webapp/WEB-INF/glassfish-web.xml b/jaspic/status-codes/src/main/webapp/WEB-INF/glassfish-web.xml
new file mode 100644
index 000000000..26559e3f6
--- /dev/null
+++ b/jaspic/status-codes/src/main/webapp/WEB-INF/glassfish-web.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ architect
+ architect
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/status-codes/src/main/webapp/WEB-INF/ibm-application-bnd.xml b/jaspic/status-codes/src/main/webapp/WEB-INF/ibm-application-bnd.xml
new file mode 100644
index 000000000..9aa892cbc
--- /dev/null
+++ b/jaspic/status-codes/src/main/webapp/WEB-INF/ibm-application-bnd.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/status-codes/src/main/webapp/WEB-INF/jboss-web.xml b/jaspic/status-codes/src/main/webapp/WEB-INF/jboss-web.xml
new file mode 100644
index 000000000..b6ab7d0ba
--- /dev/null
+++ b/jaspic/status-codes/src/main/webapp/WEB-INF/jboss-web.xml
@@ -0,0 +1,5 @@
+
+
+
+ jaspitest
+
diff --git a/jaspic/status-codes/src/main/webapp/WEB-INF/web.xml b/jaspic/status-codes/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..ffd58ffa6
--- /dev/null
+++ b/jaspic/status-codes/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Test
+ /protected/*
+
+
+ architect
+
+
+
+
+ architect
+
+
+
\ No newline at end of file
diff --git a/jaspic/status-codes/src/test/java/org/javaee7/jaspic/statuscodes/ProtectedStatusCodesTest.java b/jaspic/status-codes/src/test/java/org/javaee7/jaspic/statuscodes/ProtectedStatusCodesTest.java
new file mode 100644
index 000000000..4c2a1d088
--- /dev/null
+++ b/jaspic/status-codes/src/test/java/org/javaee7/jaspic/statuscodes/ProtectedStatusCodesTest.java
@@ -0,0 +1,43 @@
+package org.javaee7.jaspic.statuscodes;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * This tests that a SAM can set a 404 response code when a protected resource is requested.
+ * Note the resource is not actual invoked, as the SAM returns SEND_FAILURE.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class ProtectedStatusCodesTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void test404inResponse() throws IOException {
+
+ int code = getWebClient().getPage(getBase() + "protected/servlet")
+ .getWebResponse()
+ .getStatusCode();
+
+ assertEquals(
+ "Response should have 404 not found as status code, but did not.",
+ 404, code
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/status-codes/src/test/java/org/javaee7/jaspic/statuscodes/PublicStatusCodesTest.java b/jaspic/status-codes/src/test/java/org/javaee7/jaspic/statuscodes/PublicStatusCodesTest.java
new file mode 100644
index 000000000..214b6072a
--- /dev/null
+++ b/jaspic/status-codes/src/test/java/org/javaee7/jaspic/statuscodes/PublicStatusCodesTest.java
@@ -0,0 +1,43 @@
+package org.javaee7.jaspic.statuscodes;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * This tests that a SAM can set a 404 response code when a public resource is requested.
+ * Note the resource is not actual invoked, as the SAM returns SEND_FAILURE.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class PublicStatusCodesTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void test404inResponse() throws IOException {
+
+ int code = getWebClient().getPage(getBase() + "public/servlet")
+ .getWebResponse()
+ .getStatusCode();
+
+ assertEquals(
+ "Response should have 404 not found as status code, but did not.",
+ 404, code
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/wrapping/pom.xml b/jaspic/wrapping/pom.xml
new file mode 100644
index 000000000..f6da086fc
--- /dev/null
+++ b/jaspic/wrapping/pom.xml
@@ -0,0 +1,24 @@
+
+
+ 4.0.0
+
+
+ org.javaee7
+ jaspic
+ 1.0-SNAPSHOT
+ ../pom.xml
+
+ org.javaee7
+ jaspic-wrapping
+ 1.0-SNAPSHOT
+ war
+ Java EE 7 Sample: jaspic - wrapping
+
+
+
+ org.javaee7
+ jaspic-common
+ 1.0-SNAPSHOT
+
+
+
diff --git a/jaspic/wrapping/src/main/java/org/javaee7/jaspic/wrapping/sam/SamAutoRegistrationListener.java b/jaspic/wrapping/src/main/java/org/javaee7/jaspic/wrapping/sam/SamAutoRegistrationListener.java
new file mode 100644
index 000000000..271947358
--- /dev/null
+++ b/jaspic/wrapping/src/main/java/org/javaee7/jaspic/wrapping/sam/SamAutoRegistrationListener.java
@@ -0,0 +1,30 @@
+package org.javaee7.jaspic.wrapping.sam;
+
+import static java.util.EnumSet.allOf;
+
+import javax.servlet.DispatcherType;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.annotation.WebListener;
+
+import org.javaee7.jaspic.common.BaseServletContextListener;
+import org.javaee7.jaspic.common.JaspicUtils;
+import org.javaee7.jaspic.wrapping.servlet.ProgrammaticFilter;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebListener
+public class SamAutoRegistrationListener extends BaseServletContextListener {
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ JaspicUtils.registerSAM(sce.getServletContext(), new TestWrappingServerAuthModule());
+
+ sce.getServletContext()
+ .addFilter("Programmatic filter", ProgrammaticFilter.class)
+ .addMappingForUrlPatterns(allOf(DispatcherType.class), false, "/*");
+ }
+
+}
\ No newline at end of file
diff --git a/jaspic/wrapping/src/main/java/org/javaee7/jaspic/wrapping/sam/TestWrappingServerAuthModule.java b/jaspic/wrapping/src/main/java/org/javaee7/jaspic/wrapping/sam/TestWrappingServerAuthModule.java
new file mode 100644
index 000000000..05b91c59e
--- /dev/null
+++ b/jaspic/wrapping/src/main/java/org/javaee7/jaspic/wrapping/sam/TestWrappingServerAuthModule.java
@@ -0,0 +1,95 @@
+package org.javaee7.jaspic.wrapping.sam;
+
+import static javax.security.auth.message.AuthStatus.SEND_SUCCESS;
+import static javax.security.auth.message.AuthStatus.SUCCESS;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.message.AuthException;
+import javax.security.auth.message.AuthStatus;
+import javax.security.auth.message.MessageInfo;
+import javax.security.auth.message.MessagePolicy;
+import javax.security.auth.message.callback.CallerPrincipalCallback;
+import javax.security.auth.message.callback.GroupPrincipalCallback;
+import javax.security.auth.message.module.ServerAuthModule;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.javaee7.jaspic.wrapping.servlet.TestHttpServletRequestWrapper;
+import org.javaee7.jaspic.wrapping.servlet.TestHttpServletResponseWrapper;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class TestWrappingServerAuthModule implements ServerAuthModule {
+
+ private CallbackHandler handler;
+ private Class>[] supportedMessageTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class };
+
+ @Override
+ public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler,
+ @SuppressWarnings("rawtypes") Map options) throws AuthException {
+ this.handler = handler;
+ }
+
+ @Override
+ public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject)
+ throws AuthException {
+
+ try {
+ handler.handle(new Callback[] {
+ new CallerPrincipalCallback(clientSubject, "test"),
+ new GroupPrincipalCallback(clientSubject, new String[] { "architect" }) });
+ } catch (IOException | UnsupportedCallbackException e) {
+ throw (AuthException) new AuthException().initCause(e);
+ }
+
+ // Wrap the request - the resource to be invoked should get to see this
+ messageInfo.setRequestMessage(new TestHttpServletRequestWrapper(
+ (HttpServletRequest) messageInfo.getRequestMessage())
+ );
+
+ // Wrap the response - the resource to be invoked should get to see this
+ messageInfo.setResponseMessage(new TestHttpServletResponseWrapper(
+ (HttpServletResponse) messageInfo.getResponseMessage())
+ );
+
+ return SUCCESS;
+ }
+
+ @Override
+ public Class>[] getSupportedMessageTypes() {
+ return supportedMessageTypes;
+ }
+
+ @Override
+ public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException {
+
+ HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
+
+ // Unwrap the request
+ if (request instanceof TestHttpServletRequestWrapper) {
+ messageInfo.setRequestMessage(((TestHttpServletRequestWrapper) request).getRequest());
+ }
+
+ HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();
+
+ if (response instanceof TestHttpServletResponseWrapper) {
+ messageInfo.setResponseMessage(((TestHttpServletResponseWrapper) response).getResponse());
+ }
+
+ return SEND_SUCCESS;
+ }
+
+ @Override
+ public void cleanSubject(MessageInfo messageInfo, Subject subject) throws AuthException {
+
+ }
+}
\ No newline at end of file
diff --git a/jaspic/wrapping/src/main/java/org/javaee7/jaspic/wrapping/servlet/DeclaredFilter.java b/jaspic/wrapping/src/main/java/org/javaee7/jaspic/wrapping/servlet/DeclaredFilter.java
new file mode 100644
index 000000000..92735d4fa
--- /dev/null
+++ b/jaspic/wrapping/src/main/java/org/javaee7/jaspic/wrapping/servlet/DeclaredFilter.java
@@ -0,0 +1,43 @@
+package org.javaee7.jaspic.wrapping.servlet;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.annotation.WebFilter;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * This Filter tests that the request and response objects it receives are the ones marked as wrapped by the SAM that executed
+ * before the Servlet was called.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebFilter(urlPatterns="/*")
+public class DeclaredFilter implements Filter {
+
+ public void init(FilterConfig fConfig) throws ServletException {
+ }
+
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+
+ Writer writer = response.getWriter();
+
+ writer.write("declared filter request isWrapped: " + request.getAttribute("isWrapped"));
+ writer.write("\n");
+ writer.write("declared filter response isWrapped: " + ((HttpServletResponse)response).getHeader("isWrapped"));
+ writer.write("\n");
+
+ chain.doFilter(request, response);
+ }
+
+ public void destroy() {
+ }
+
+}
diff --git a/jaspic/wrapping/src/main/java/org/javaee7/jaspic/wrapping/servlet/ProgrammaticFilter.java b/jaspic/wrapping/src/main/java/org/javaee7/jaspic/wrapping/servlet/ProgrammaticFilter.java
new file mode 100644
index 000000000..13e5e342f
--- /dev/null
+++ b/jaspic/wrapping/src/main/java/org/javaee7/jaspic/wrapping/servlet/ProgrammaticFilter.java
@@ -0,0 +1,41 @@
+package org.javaee7.jaspic.wrapping.servlet;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * This Filter tests that the request and response objects it receives are the ones marked as wrapped by the SAM that executed
+ * before the Servlet was called.
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class ProgrammaticFilter implements Filter {
+
+ public void init(FilterConfig fConfig) throws ServletException {
+ }
+
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+
+ Writer writer = response.getWriter();
+
+ writer.write("programmatic filter request isWrapped: " + request.getAttribute("isWrapped"));
+ writer.write("\n");
+ writer.write("programmatic filter response isWrapped: " + ((HttpServletResponse)response).getHeader("isWrapped"));
+ writer.write("\n");
+
+ chain.doFilter(request, response);
+ }
+
+ public void destroy() {
+ }
+
+}
diff --git a/jaspic/wrapping/src/main/java/org/javaee7/jaspic/wrapping/servlet/ProtectedServlet.java b/jaspic/wrapping/src/main/java/org/javaee7/jaspic/wrapping/servlet/ProtectedServlet.java
new file mode 100644
index 000000000..7caeacdd1
--- /dev/null
+++ b/jaspic/wrapping/src/main/java/org/javaee7/jaspic/wrapping/servlet/ProtectedServlet.java
@@ -0,0 +1,34 @@
+package org.javaee7.jaspic.wrapping.servlet;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * This Servlet tests that the request and response objects it receives are the ones marked as wrapped by the SAM that executed
+ * before the Servlet was called.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@WebServlet(urlPatterns = "/protected/servlet")
+public class ProtectedServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+
+ Writer writer = response.getWriter();
+
+ writer.write("servlet request isWrapped: " + request.getAttribute("isWrapped"));
+ writer.write("\n");
+ writer.write("servlet response isWrapped: " + response.getHeader("isWrapped"));
+ }
+
+}
diff --git a/jaspic/wrapping/src/main/java/org/javaee7/jaspic/wrapping/servlet/TestHttpServletRequestWrapper.java b/jaspic/wrapping/src/main/java/org/javaee7/jaspic/wrapping/servlet/TestHttpServletRequestWrapper.java
new file mode 100644
index 000000000..e655088a5
--- /dev/null
+++ b/jaspic/wrapping/src/main/java/org/javaee7/jaspic/wrapping/servlet/TestHttpServletRequestWrapper.java
@@ -0,0 +1,27 @@
+package org.javaee7.jaspic.wrapping.servlet;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class TestHttpServletRequestWrapper extends HttpServletRequestWrapper {
+
+ public TestHttpServletRequestWrapper(HttpServletRequest request) {
+ super(request);
+ }
+
+ @Override
+ public Object getAttribute(String name) {
+
+ if ("isWrapped".equals(name)) {
+ return Boolean.TRUE;
+ }
+
+ return super.getAttribute(name);
+ }
+
+}
diff --git a/jaspic/wrapping/src/main/java/org/javaee7/jaspic/wrapping/servlet/TestHttpServletResponseWrapper.java b/jaspic/wrapping/src/main/java/org/javaee7/jaspic/wrapping/servlet/TestHttpServletResponseWrapper.java
new file mode 100644
index 000000000..d36506267
--- /dev/null
+++ b/jaspic/wrapping/src/main/java/org/javaee7/jaspic/wrapping/servlet/TestHttpServletResponseWrapper.java
@@ -0,0 +1,27 @@
+package org.javaee7.jaspic.wrapping.servlet;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+
+/**
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class TestHttpServletResponseWrapper extends HttpServletResponseWrapper {
+
+ public TestHttpServletResponseWrapper(HttpServletResponse response) {
+ super(response);
+ }
+
+ @Override
+ public String getHeader(String name) {
+
+ if ("isWrapped".equals(name)) {
+ return "true";
+ }
+
+ return super.getHeader(name);
+ }
+
+}
diff --git a/jaspic/wrapping/src/main/webapp/WEB-INF/glassfish-web.xml b/jaspic/wrapping/src/main/webapp/WEB-INF/glassfish-web.xml
new file mode 100644
index 000000000..26559e3f6
--- /dev/null
+++ b/jaspic/wrapping/src/main/webapp/WEB-INF/glassfish-web.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+ architect
+ architect
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/wrapping/src/main/webapp/WEB-INF/ibm-application-bnd.xml b/jaspic/wrapping/src/main/webapp/WEB-INF/ibm-application-bnd.xml
new file mode 100644
index 000000000..9aa892cbc
--- /dev/null
+++ b/jaspic/wrapping/src/main/webapp/WEB-INF/ibm-application-bnd.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jaspic/wrapping/src/main/webapp/WEB-INF/jboss-web.xml b/jaspic/wrapping/src/main/webapp/WEB-INF/jboss-web.xml
new file mode 100644
index 000000000..2c14aa4f8
--- /dev/null
+++ b/jaspic/wrapping/src/main/webapp/WEB-INF/jboss-web.xml
@@ -0,0 +1,4 @@
+
+
+ jaspitest
+
diff --git a/jaspic/wrapping/src/main/webapp/WEB-INF/web.xml b/jaspic/wrapping/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..ffd58ffa6
--- /dev/null
+++ b/jaspic/wrapping/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ Test
+ /protected/*
+
+
+ architect
+
+
+
+
+ architect
+
+
+
\ No newline at end of file
diff --git a/jaspic/wrapping/src/test/java/org/javaee7/jaspic/wrapping/WrappingTest.java b/jaspic/wrapping/src/test/java/org/javaee7/jaspic/wrapping/WrappingTest.java
new file mode 100644
index 000000000..d8f4cb0d3
--- /dev/null
+++ b/jaspic/wrapping/src/test/java/org/javaee7/jaspic/wrapping/WrappingTest.java
@@ -0,0 +1,90 @@
+package org.javaee7.jaspic.wrapping;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.javaee7.jaspic.common.ArquillianBase;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.Archive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xml.sax.SAXException;
+
+/**
+ * This tests that the wrapped request and response a SAM puts into the MessageInfo structure reaches the Servlet that's
+ * invoked as well as all filters executed before that.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class WrappingTest extends ArquillianBase {
+
+ @Deployment(testable = false)
+ public static Archive> createDeployment() {
+ return defaultArchive();
+ }
+
+ @Test
+ public void testProgrammaticFilterRequestWrapping() throws IOException, SAXException {
+
+ String response = getFromServerPath("protected/servlet");
+
+ // The SAM wrapped a request so that it always contains the request attribute "isWrapped" with value true.
+ assertTrue("Request wrapped by SAM did not arrive in programmatic Filter.",
+ response.contains("programmatic filter request isWrapped: true"));
+ }
+
+ @Test
+ public void testProgrammaticFilterResponseWrapping() throws IOException, SAXException {
+
+ String response = getFromServerPath("protected/servlet");
+
+ // The SAM wrapped a response so that it always contains the header "isWrapped" with value true.
+ assertTrue("Response wrapped by SAM did not arrive in programmatic Filter.",
+ response.contains("programmatic filter response isWrapped: true"));
+ }
+
+ @Test
+ public void testDeclaredFilterRequestWrapping() throws IOException, SAXException {
+
+ String response = getFromServerPath("protected/servlet");
+
+ // The SAM wrapped a request so that it always contains the request attribute "isWrapped" with value true.
+ assertTrue("Request wrapped by SAM did not arrive in declared Filter.",
+ response.contains("declared filter request isWrapped: true"));
+ }
+
+ @Test
+ public void testDeclaredFilterResponseWrapping() throws IOException, SAXException {
+
+ String response = getFromServerPath("protected/servlet");
+
+ // The SAM wrapped a response so that it always contains the header "isWrapped" with value true.
+ assertTrue("Response wrapped by SAM did not arrive in declared Filter.",
+ response.contains("declared filter response isWrapped: true"));
+ }
+
+ @Test
+ public void testRequestWrapping() throws IOException, SAXException {
+
+ String response = getFromServerPath("protected/servlet");
+
+ // The SAM wrapped a request so that it always contains the request attribute "isWrapped" with value true.
+ assertTrue("Request wrapped by SAM did not arrive in Servlet.",
+ response.contains("servlet request isWrapped: true"));
+ }
+
+ @Test
+ public void testResponseWrapping() throws IOException, SAXException {
+
+ String response = getFromServerPath("protected/servlet");
+
+ // The SAM wrapped a response so that it always contains the header "isWrapped" with value true.
+ assertTrue("Response wrapped by SAM did not arrive in Servlet.",
+ response.contains("servlet response isWrapped: true"));
+ }
+
+}
\ No newline at end of file
diff --git a/javamail/README.md b/javamail/README.md
new file mode 100644
index 000000000..1826f14f4
--- /dev/null
+++ b/javamail/README.md
@@ -0,0 +1,13 @@
+# Java EE 7 Samples: Javamail 1.5#
+
+The [JSR 919](https://jcp.org/en/jsr/detail?id=919) seeks to define a description of the new APIs that are being introduced in JavaMail.
+
+## Samples ##
+
+ - definition
+
+## How to run
+
+More information on how to run can be found at:
+
+
diff --git a/javamail/definition/pom.xml b/javamail/definition/pom.xml
index c6c2dc49f..3f6a96341 100644
--- a/javamail/definition/pom.xml
+++ b/javamail/definition/pom.xml
@@ -1,15 +1,16 @@
-
+
+
4.0.0
+
- org.javaee7.javamail
- javamail-samples
+ org.javaee7
+ javamail
1.0-SNAPSHOT
../pom.xml
-
- org.javaee7.javamail
- definition
+ org.javaee7
+ javamail-definition
1.0-SNAPSHOT
war
+ Java EE 7 Sample: javamail - definition
diff --git a/javamail/definition/src/main/java/org/javaee7/javamail/definition/AnnotatedEmailServlet.java b/javamail/definition/src/main/java/org/javaee7/javamail/definition/AnnotatedEmailServlet.java
index 93183b205..84ee3e18c 100644
--- a/javamail/definition/src/main/java/org/javaee7/javamail/definition/AnnotatedEmailServlet.java
+++ b/javamail/definition/src/main/java/org/javaee7/javamail/definition/AnnotatedEmailServlet.java
@@ -60,13 +60,13 @@
/**
* @author Arun Gupta
*/
-@WebServlet(urlPatterns = {"/AnnotatedEmailServlet"})
+@WebServlet(urlPatterns = { "/AnnotatedEmailServlet" })
@MailSessionDefinition(name = "java:comp/myMailSession",
- host = "smtp.gmail.com",
- transportProtocol = "smtps",
- properties = {
- "mail.debug=true"
- })
+ host = "smtp.gmail.com",
+ transportProtocol = "smtps",
+ properties = {
+ "mail.debug=true"
+ })
public class AnnotatedEmailServlet extends HttpServlet {
@Resource(lookup = "java:comp/myMailSession")
@@ -85,7 +85,7 @@ public class AnnotatedEmailServlet extends HttpServlet {
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
+ throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
out.println("");
@@ -98,16 +98,16 @@ protected void processRequest(HttpServletRequest request, HttpServletResponse re
try {
out.println("Sending message from \""
- + creds.getFrom()
- + "\" to \""
- + creds.getTo()
- + "\"... ");
+ + creds.getFrom()
+ + "\" to \""
+ + creds.getTo()
+ + "\"... ");
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(creds.getFrom()));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(creds.getTo()));
message.setSubject("Sending message using Annotated JavaMail "
- + Calendar.getInstance().getTime());
+ + Calendar.getInstance().getTime());
message.setText("Java EE 7 is cool!");
Transport t = session.getTransport();
@@ -136,7 +136,7 @@ protected void processRequest(HttpServletRequest request, HttpServletResponse re
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
+ throws ServletException, IOException {
processRequest(request, response);
}
@@ -150,7 +150,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response)
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
+ throws ServletException, IOException {
processRequest(request, response);
}
diff --git a/javamail/definition/src/main/java/org/javaee7/javamail/definition/Credentials.java b/javamail/definition/src/main/java/org/javaee7/javamail/definition/Credentials.java
index 0ae0d147c..1f2327c92 100644
--- a/javamail/definition/src/main/java/org/javaee7/javamail/definition/Credentials.java
+++ b/javamail/definition/src/main/java/org/javaee7/javamail/definition/Credentials.java
@@ -60,8 +60,8 @@ public Credentials() {
try {
final Properties creds = new Properties();
creds.load(new FileInputStream(System.getProperty("user.home")
- + System.getProperty("file.separator")
- + ".javamail"));
+ + System.getProperty("file.separator")
+ + ".javamail"));
from = creds.getProperty("from");
password = creds.getProperty("password");
to = creds.getProperty("to");
diff --git a/javamail/definition/src/main/java/org/javaee7/javamail/definition/ProgrammaticEmailServlet.java b/javamail/definition/src/main/java/org/javaee7/javamail/definition/ProgrammaticEmailServlet.java
index b218bf8ca..eb804e1fa 100644
--- a/javamail/definition/src/main/java/org/javaee7/javamail/definition/ProgrammaticEmailServlet.java
+++ b/javamail/definition/src/main/java/org/javaee7/javamail/definition/ProgrammaticEmailServlet.java
@@ -60,10 +60,11 @@
/**
* @author Arun Gupta
*/
-@WebServlet(urlPatterns = {"/ProgrammaticEmailServlet"})
+@WebServlet(urlPatterns = { "/ProgrammaticEmailServlet" })
public class ProgrammaticEmailServlet extends HttpServlet {
-
- @Inject Credentials creds;
+
+ @Inject
+ Credentials creds;
/**
* Processes requests for both HTTP GET and POST
@@ -75,7 +76,7 @@ public class ProgrammaticEmailServlet extends HttpServlet {
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
+ throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
out.println("");
@@ -93,34 +94,33 @@ protected void processRequest(HttpServletRequest request, HttpServletResponse re
props.put("mail.transport.protocol", "smtp");
props.put("mail.debug", "true");
-
Session session = Session.getInstance(props,
- new javax.mail.Authenticator() {
- @Override
- protected PasswordAuthentication getPasswordAuthentication() {
- return new PasswordAuthentication(creds.getFrom(), creds.getPassword());
- }
- });
-// Session session = Session.getInstance(props);
+ new javax.mail.Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(creds.getFrom(), creds.getPassword());
+ }
+ });
+ // Session session = Session.getInstance(props);
try {
- out.println("Sending message from \""
- + creds.getFrom()
- + "\" to \""
- + creds.getTo()
- + "\"... ");
+ out.println("Sending message from \""
+ + creds.getFrom()
+ + "\" to \""
+ + creds.getTo()
+ + "\"... ");
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(creds.getFrom()));
message.setRecipients(Message.RecipientType.TO,
- InternetAddress.parse(creds.getTo()));
+ InternetAddress.parse(creds.getTo()));
message.setSubject("Sending message using Programmatic JavaMail " + Calendar.getInstance().getTime());
message.setText("Java EE 7 is cool!");
-// Transport t = session.getTransport();
-// t.connect(creds.getFrom(), creds.getTo());
-// t.sendMessage(message, message.getAllRecipients());
+ // Transport t = session.getTransport();
+ // t.connect(creds.getFrom(), creds.getTo());
+ // t.sendMessage(message, message.getAllRecipients());
Transport.send(message, message.getAllRecipients());
out.println("message sent!");
@@ -145,7 +145,7 @@ protected PasswordAuthentication getPasswordAuthentication() {
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
+ throws ServletException, IOException {
processRequest(request, response);
}
@@ -159,7 +159,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response)
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
+ throws ServletException, IOException {
processRequest(request, response);
}
diff --git a/javamail/pom.xml b/javamail/pom.xml
index 42b4750fb..428c8e563 100644
--- a/javamail/pom.xml
+++ b/javamail/pom.xml
@@ -1,21 +1,27 @@
-
- 4.0.0
+
+ 4.0.0
+
org.javaee7
- javaee7-samples
+ samples-parent
1.0-SNAPSHOT
- ../pom.xml
-
- org.javaee7.javamail
- javamail-samples
- 1.0-SNAPSHOT
+
+ javamail
pom
- Java EE 7 JavaMail Samples
+
+ Java EE 7 Sample: javamail
definition
+
+
+ org.javaee7
+ test-utils
+ ${project.version}
+ test
+
+
diff --git a/jaxrpc/README.md b/jaxrpc/README.md
new file mode 100644
index 000000000..ea694ea67
--- /dev/null
+++ b/jaxrpc/README.md
@@ -0,0 +1,17 @@
+# Java EE 7 Samples: JAX-RPC 1.1 #
+
+The [JSR 101](https://jcp.org/en/jsr/detail?id=101) specification is the old generation web services API predating JAX-WS, which in fact was
+to become JAX-RPC 2.0.
+
+JAX-RPC 1.x is **pruned** from Java EE, and **should not be used** anymore. This sample is only provided for historical purposes.
+
+## Samples ##
+
+ - **jaxrpc-endpoint** - *Defines a very basic hello endpoint (as all classical JAX-RPC examples did), generates the required .wsdl and mapping files, deploys the service, and calls it via two client side approaches: dynamic proxy and DII.*
+ - **jaxrpc-security** - *Like `jaxrpc-endpoint`, but the service is protected and requires SOAP message level authentication via an encrypted username/password credential in the security header, and calls it via generated Stubs. (to keep the sample somewhat restricted in size does not sign the message)*
+
+## How to run
+
+More information on how to run can be found at:
+
+
diff --git a/jaxrpc/jaxrpc-endpoint/build.xml b/jaxrpc/jaxrpc-endpoint/build.xml
new file mode 100644
index 000000000..609bf4e59
--- /dev/null
+++ b/jaxrpc/jaxrpc-endpoint/build.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-endpoint/pom.xml b/jaxrpc/jaxrpc-endpoint/pom.xml
new file mode 100644
index 000000000..39048b97f
--- /dev/null
+++ b/jaxrpc/jaxrpc-endpoint/pom.xml
@@ -0,0 +1,87 @@
+
+
+ 4.0.0
+
+
+ org.javaee7
+ jaxrpc
+ 1.0-SNAPSHOT
+
+
+ jaxrpc-endpoint
+ war
+ Java EE 7 Sample: jaxrpc - jaxrpc-endpoint
+
+
+
+ com.sun.xml.rpc
+ jaxrpc-impl
+ 1.1.4_01
+
+
+ org.apache.ant
+ ant-launcher
+ 1.10.3
+
+
+
+
+
+ jaxrpc-endpoint
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+ 1.1
+
+
+ process-classes
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 3.0.0
+
+
+ generate-sources
+ generate-sources
+
+ add-source
+
+
+
+ ${project.build.directory}/generated-sources/antrun
+
+
+
+
+
+
+
+
diff --git a/jaxrpc/jaxrpc-endpoint/src/main/java/org/javaee7/jaxrpc/endpoint/HelloService.java b/jaxrpc/jaxrpc-endpoint/src/main/java/org/javaee7/jaxrpc/endpoint/HelloService.java
new file mode 100644
index 000000000..7582c9274
--- /dev/null
+++ b/jaxrpc/jaxrpc-endpoint/src/main/java/org/javaee7/jaxrpc/endpoint/HelloService.java
@@ -0,0 +1,8 @@
+package org.javaee7.jaxrpc.endpoint;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public interface HelloService extends Remote {
+ String sayHello(String s) throws RemoteException;
+}
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-endpoint/src/main/java/org/javaee7/jaxrpc/endpoint/HelloServiceImpl.java b/jaxrpc/jaxrpc-endpoint/src/main/java/org/javaee7/jaxrpc/endpoint/HelloServiceImpl.java
new file mode 100644
index 000000000..41e7b4db6
--- /dev/null
+++ b/jaxrpc/jaxrpc-endpoint/src/main/java/org/javaee7/jaxrpc/endpoint/HelloServiceImpl.java
@@ -0,0 +1,8 @@
+package org.javaee7.jaxrpc.endpoint;
+
+public class HelloServiceImpl implements HelloService {
+
+ public String sayHello(String input) {
+ return "Hello " + input;
+ }
+}
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-endpoint/src/main/resources/HelloService.xml b/jaxrpc/jaxrpc-endpoint/src/main/resources/HelloService.xml
new file mode 100644
index 000000000..c5784d379
--- /dev/null
+++ b/jaxrpc/jaxrpc-endpoint/src/main/resources/HelloService.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-endpoint/src/main/resources/META-INF/services/javax.xml.soap.MessageFactory b/jaxrpc/jaxrpc-endpoint/src/main/resources/META-INF/services/javax.xml.soap.MessageFactory
new file mode 100644
index 000000000..82cade269
--- /dev/null
+++ b/jaxrpc/jaxrpc-endpoint/src/main/resources/META-INF/services/javax.xml.soap.MessageFactory
@@ -0,0 +1 @@
+com.sun.xml.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-endpoint/src/main/resources/config.xml b/jaxrpc/jaxrpc-endpoint/src/main/resources/config.xml
new file mode 100644
index 000000000..b18ed4045
--- /dev/null
+++ b/jaxrpc/jaxrpc-endpoint/src/main/resources/config.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-endpoint/src/main/webapp/WEB-INF/.gitignore b/jaxrpc/jaxrpc-endpoint/src/main/webapp/WEB-INF/.gitignore
new file mode 100644
index 000000000..b712eed59
--- /dev/null
+++ b/jaxrpc/jaxrpc-endpoint/src/main/webapp/WEB-INF/.gitignore
@@ -0,0 +1 @@
+/mapping.xml
diff --git a/jaxrpc/jaxrpc-endpoint/src/main/webapp/WEB-INF/README.md b/jaxrpc/jaxrpc-endpoint/src/main/webapp/WEB-INF/README.md
new file mode 100644
index 000000000..0d111dc41
--- /dev/null
+++ b/jaxrpc/jaxrpc-endpoint/src/main/webapp/WEB-INF/README.md
@@ -0,0 +1 @@
+Generated file `mapping.xml` will be saved here.
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-endpoint/src/main/webapp/WEB-INF/web.xml b/jaxrpc/jaxrpc-endpoint/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..9254611e9
--- /dev/null
+++ b/jaxrpc/jaxrpc-endpoint/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ HelloServiceServlet
+ org.javaee7.jaxrpc.endpoint.HelloServiceImpl
+
+
+ HelloServiceServlet
+ /hello
+
+
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-endpoint/src/main/webapp/WEB-INF/webservices.xml b/jaxrpc/jaxrpc-endpoint/src/main/webapp/WEB-INF/webservices.xml
new file mode 100644
index 000000000..d3005b007
--- /dev/null
+++ b/jaxrpc/jaxrpc-endpoint/src/main/webapp/WEB-INF/webservices.xml
@@ -0,0 +1,20 @@
+
+
+
+ MyHelloService
+
+ WEB-INF/wsdl/MyHelloService.wsdl
+ WEB-INF/mapping.xml
+
+
+ HelloService
+ my:HelloServicePort
+ org.javaee7.jaxrpc.endpoint.HelloService
+
+ HelloServiceServlet
+
+
+
+
+
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-endpoint/src/main/webapp/WEB-INF/wsdl/.gitignore b/jaxrpc/jaxrpc-endpoint/src/main/webapp/WEB-INF/wsdl/.gitignore
new file mode 100644
index 000000000..b60d9c3aa
--- /dev/null
+++ b/jaxrpc/jaxrpc-endpoint/src/main/webapp/WEB-INF/wsdl/.gitignore
@@ -0,0 +1 @@
+/MyHelloService.wsdl
diff --git a/jaxrpc/jaxrpc-endpoint/src/main/webapp/WEB-INF/wsdl/README.md b/jaxrpc/jaxrpc-endpoint/src/main/webapp/WEB-INF/wsdl/README.md
new file mode 100644
index 000000000..5bc6bea50
--- /dev/null
+++ b/jaxrpc/jaxrpc-endpoint/src/main/webapp/WEB-INF/wsdl/README.md
@@ -0,0 +1 @@
+Generated file `MyHelloService.wsdl` will be saved here.
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-endpoint/src/test/java/org/javaee7/jaxrpc/endpoint/HelloTest.java b/jaxrpc/jaxrpc-endpoint/src/test/java/org/javaee7/jaxrpc/endpoint/HelloTest.java
new file mode 100644
index 000000000..c8d62cb26
--- /dev/null
+++ b/jaxrpc/jaxrpc-endpoint/src/test/java/org/javaee7/jaxrpc/endpoint/HelloTest.java
@@ -0,0 +1,99 @@
+package org.javaee7.jaxrpc.endpoint;
+
+import static javax.xml.rpc.Call.SOAPACTION_URI_PROPERTY;
+import static javax.xml.rpc.Call.SOAPACTION_USE_PROPERTY;
+import static javax.xml.rpc.ParameterMode.IN;
+import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.rmi.RemoteException;
+
+import javax.xml.namespace.QName;
+import javax.xml.rpc.Call;
+import javax.xml.rpc.ServiceException;
+import javax.xml.rpc.ServiceFactory;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.container.test.api.RunAsClient;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(Arquillian.class)
+public class HelloTest {
+
+ private static final String WEBAPP_SRC = "src/main/webapp";
+ private static final String ENCODING_STYLE_PROPERTY = "javax.xml.rpc.encodingstyle.namespace.uri";
+ private static final String NS_XSD = "http://www.w3.org/2001/XMLSchema";
+
+ @ArquillianResource
+ private URL url;
+
+
+ @Deployment(testable = false)
+ public static WebArchive createDeployment() {
+ System.out.println("************** DEPLOYING ************************************");
+
+ WebArchive war =
+ create(WebArchive.class)
+ .addClasses(HelloService.class, HelloServiceImpl.class)
+ .addAsWebInfResource(new File(WEBAPP_SRC + "/WEB-INF/wsdl", "MyHelloService.wsdl"), "wsdl/MyHelloService.wsdl")
+ .addAsWebInfResource(new File(WEBAPP_SRC + "/WEB-INF", "mapping.xml"))
+ .addAsWebInfResource(new File(WEBAPP_SRC + "/WEB-INF", "webservices.xml"))
+ .addAsWebInfResource(new File(WEBAPP_SRC + "/WEB-INF", "web.xml"))
+ ;
+
+ System.out.println(war.toString(true));
+ System.out.println("************************************************************");
+
+ return war;
+ }
+
+ @Test
+ @RunAsClient
+ public void testHelloProxy() throws MalformedURLException, ServiceException, RemoteException {
+ HelloService helloService = (HelloService)
+ ServiceFactory.newInstance()
+ .createService(
+ new URL(url, "hello?wsdl"),
+ new QName("urn:sample", "MyHelloService"))
+ .getPort(
+ new QName("urn:sample", "HelloServicePort"),
+ HelloService.class);
+
+ String result = helloService.sayHello("Sailor");
+
+ assertEquals("Hello Sailor", result);
+ }
+
+ @Test
+ @RunAsClient
+ public void testHelloDII() throws MalformedURLException, ServiceException, RemoteException {
+ Call call = ServiceFactory.newInstance()
+ .createService(new QName("MyHelloService"))
+ .createCall(new QName("HelloServicePort"));
+
+ call.setTargetEndpointAddress(url + "hello");
+
+ call.setProperty(SOAPACTION_USE_PROPERTY, true);
+ call.setProperty(SOAPACTION_URI_PROPERTY, "");
+ call.setProperty(ENCODING_STYLE_PROPERTY, "http://schemas.xmlsoap.org/soap/encoding/");
+
+ call.setReturnType(new QName(NS_XSD, "string"));
+ call.setOperationName(new QName("urn:sample", "sayHello"));
+ call.addParameter("String_1", new QName(NS_XSD, "string"), IN);
+
+ String result = (String) call.invoke(new String[] { "Captain" });
+
+ assertEquals("Hello Captain", result);
+ }
+
+
+
+
+}
diff --git a/jaxrpc/jaxrpc-security/build.xml b/jaxrpc/jaxrpc-security/build.xml
new file mode 100644
index 000000000..ac43ff1d3
--- /dev/null
+++ b/jaxrpc/jaxrpc-security/build.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+ wscompile server
+
+
+
+
+
+ wscompile client
+
+
+
+
+
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-security/pom.xml b/jaxrpc/jaxrpc-security/pom.xml
new file mode 100644
index 000000000..37c76a192
--- /dev/null
+++ b/jaxrpc/jaxrpc-security/pom.xml
@@ -0,0 +1,162 @@
+
+ 4.0.0
+
+
+ org.javaee7
+ jaxrpc
+ 1.0-SNAPSHOT
+
+
+ jaxrpc-security
+ war
+ Java EE 7 Sample: jaxrpc - jaxrpc-security
+
+
+
+
+
+ org.glassfish.metro
+ webservices-rt
+ 2.4.0
+
+
+
+
+
+ org.apache.ant
+ ant
+ 1.10.11
+
+
+
+ org.apache.ant
+ ant-launcher
+ 1.10.3
+
+
+
+
+
+ jaxrpc-security
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+ 1.8
+
+
+ process-classes
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+ Copying generated .wsdl and mapping.xml files
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Copying generated stub sources
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.7.0
+
+
+ true
+ -XDignore.symbol.file
+
+
+
+
+ default-compile
+ compile
+
+ compile
+
+
+
+
+ compile-generated
+ generate-test-sources
+
+ compile
+
+
+
+
+
+
+ maven-enforcer-plugin
+
+
+
+ $1.8
+
+
+
+
+
+
+ enforce
+
+
+
+
+
+
+
diff --git a/jaxrpc/jaxrpc-security/src/main/java/org/javaee7/jaxrpc/security/HelloService.java b/jaxrpc/jaxrpc-security/src/main/java/org/javaee7/jaxrpc/security/HelloService.java
new file mode 100644
index 000000000..9b33c4b87
--- /dev/null
+++ b/jaxrpc/jaxrpc-security/src/main/java/org/javaee7/jaxrpc/security/HelloService.java
@@ -0,0 +1,20 @@
+/** Copyright Payara Services Limited **/
+
+package org.javaee7.jaxrpc.security;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+/**
+ * The mandated interface for a JAX-RPC remote web service.
+ *
+ *
+ * Note the mandated extension from the {@link Remote} interface
+ * and the service method having to throw a {@link RemoteException}.
+ *
+ * @author Arjan Tijms
+ *
+ */
+public interface HelloService extends Remote {
+ String sayHello(String input) throws RemoteException;
+}
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-security/src/main/java/org/javaee7/jaxrpc/security/HelloServiceImpl.java b/jaxrpc/jaxrpc-security/src/main/java/org/javaee7/jaxrpc/security/HelloServiceImpl.java
new file mode 100644
index 000000000..1f3637e1d
--- /dev/null
+++ b/jaxrpc/jaxrpc-security/src/main/java/org/javaee7/jaxrpc/security/HelloServiceImpl.java
@@ -0,0 +1,16 @@
+/** Copyright Payara Services Limited **/
+
+package org.javaee7.jaxrpc.security;
+
+/**
+ * Implementation class for the JAX-RPC remote web service.
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class HelloServiceImpl implements HelloService {
+
+ public String sayHello(String input) {
+ return "Hello " + input;
+ }
+}
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-security/src/main/resources/wscompile-server-config.xml b/jaxrpc/jaxrpc-security/src/main/resources/wscompile-server-config.xml
new file mode 100644
index 000000000..46af7b63d
--- /dev/null
+++ b/jaxrpc/jaxrpc-security/src/main/resources/wscompile-server-config.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-security/src/main/webapp/WEB-INF/.gitignore b/jaxrpc/jaxrpc-security/src/main/webapp/WEB-INF/.gitignore
new file mode 100644
index 000000000..b712eed59
--- /dev/null
+++ b/jaxrpc/jaxrpc-security/src/main/webapp/WEB-INF/.gitignore
@@ -0,0 +1 @@
+/mapping.xml
diff --git a/jaxrpc/jaxrpc-security/src/main/webapp/WEB-INF/README.md b/jaxrpc/jaxrpc-security/src/main/webapp/WEB-INF/README.md
new file mode 100644
index 000000000..0d111dc41
--- /dev/null
+++ b/jaxrpc/jaxrpc-security/src/main/webapp/WEB-INF/README.md
@@ -0,0 +1 @@
+Generated file `mapping.xml` will be saved here.
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-security/src/main/webapp/WEB-INF/sun-web.xml b/jaxrpc/jaxrpc-security/src/main/webapp/WEB-INF/sun-web.xml
new file mode 100644
index 000000000..39bf241ca
--- /dev/null
+++ b/jaxrpc/jaxrpc-security/src/main/webapp/WEB-INF/sun-web.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+ HelloServiceServlet
+
+ HelloService
+ hello
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-security/src/main/webapp/WEB-INF/web.xml b/jaxrpc/jaxrpc-security/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..bb5e6c139
--- /dev/null
+++ b/jaxrpc/jaxrpc-security/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+ HelloServiceServlet
+ org.javaee7.jaxrpc.security.HelloServiceImpl
+
+
+ HelloServiceServlet
+ /hello
+
+
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-security/src/main/webapp/WEB-INF/webservices.xml b/jaxrpc/jaxrpc-security/src/main/webapp/WEB-INF/webservices.xml
new file mode 100644
index 000000000..a7e159800
--- /dev/null
+++ b/jaxrpc/jaxrpc-security/src/main/webapp/WEB-INF/webservices.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+ MyHelloService
+
+ WEB-INF/wsdl/MyHelloService.wsdl
+ WEB-INF/mapping.xml
+
+
+ HelloService
+ my:HelloServicePort
+ org.javaee7.jaxrpc.security.HelloService
+
+ HelloServiceServlet
+
+
+
+
+
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-security/src/main/webapp/WEB-INF/wsdl/.gitignore b/jaxrpc/jaxrpc-security/src/main/webapp/WEB-INF/wsdl/.gitignore
new file mode 100644
index 000000000..b60d9c3aa
--- /dev/null
+++ b/jaxrpc/jaxrpc-security/src/main/webapp/WEB-INF/wsdl/.gitignore
@@ -0,0 +1 @@
+/MyHelloService.wsdl
diff --git a/jaxrpc/jaxrpc-security/src/main/webapp/WEB-INF/wsdl/README.md b/jaxrpc/jaxrpc-security/src/main/webapp/WEB-INF/wsdl/README.md
new file mode 100644
index 000000000..5bc6bea50
--- /dev/null
+++ b/jaxrpc/jaxrpc-security/src/main/webapp/WEB-INF/wsdl/README.md
@@ -0,0 +1 @@
+Generated file `MyHelloService.wsdl` will be saved here.
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-security/src/test/java/org/javaee7/jaxrpc/security/ClientTestCallbackHandler.java b/jaxrpc/jaxrpc-security/src/test/java/org/javaee7/jaxrpc/security/ClientTestCallbackHandler.java
new file mode 100644
index 000000000..329912e85
--- /dev/null
+++ b/jaxrpc/jaxrpc-security/src/test/java/org/javaee7/jaxrpc/security/ClientTestCallbackHandler.java
@@ -0,0 +1,84 @@
+/** Copyright Payara Services Limited **/
+package org.javaee7.jaxrpc.security;
+
+import static javax.xml.rpc.Stub.PASSWORD_PROPERTY;
+import static javax.xml.rpc.Stub.USERNAME_PROPERTY;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.logging.Logger;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import com.sun.xml.wss.impl.callback.EncryptionKeyCallback;
+import com.sun.xml.wss.impl.callback.EncryptionKeyCallback.AliasX509CertificateRequest;
+import com.sun.xml.wss.impl.callback.PasswordCallback;
+import com.sun.xml.wss.impl.callback.UsernameCallback;
+
+/**
+ * Callback handler that's used by the generated client stubs to obtain the
+ * username and password to insert into the request, and the x.509 certificate
+ * to encrypt said username and password.
+ *
+ *
+ * Note that this only really gets the X.509 certificate from the file src/test/resources/s1as.cert.
+ * The username and password already come from the callback and are just being given back to it
+ * (for some reason this is required).
+ *
+ * @author Arjan Tijms
+ *
+ */
+public class ClientTestCallbackHandler implements CallbackHandler {
+
+ private static Logger log = Logger.getLogger(ClientTestCallbackHandler.class.getName());
+
+ public ClientTestCallbackHandler() throws Exception {
+ log.info("Instantiating ClientTestCallbackHandler");
+ }
+
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+
+ for (Callback callback : callbacks) {
+
+ log.info("Processing " + callback);
+
+ if (callback instanceof UsernameCallback) {
+ UsernameCallback usernameCallback = (UsernameCallback) callback;
+
+ usernameCallback.setUsername((String) (usernameCallback.getRuntimeProperties().get(USERNAME_PROPERTY)));
+ } else if (callback instanceof PasswordCallback) {
+ PasswordCallback passwordCallback = (PasswordCallback) callback;
+
+ passwordCallback.setPassword((String) (passwordCallback.getRuntimeProperties().get(PASSWORD_PROPERTY)));
+ } else if (callback instanceof EncryptionKeyCallback) {
+ EncryptionKeyCallback encryptionKeyCallback = (EncryptionKeyCallback) callback;
+
+ AliasX509CertificateRequest request = (AliasX509CertificateRequest) encryptionKeyCallback.getRequest();
+ request.setX509Certificate(getCertificate());
+ }
+
+ }
+ }
+
+ private X509Certificate getCertificate() throws FileNotFoundException, IOException {
+ try (InputStream inStream = getClass().getClassLoader().getResource("s1as.cert").openStream()) {
+ X509Certificate certificate = (X509Certificate)
+ CertificateFactory.getInstance("X.509")
+ .generateCertificate(inStream);
+
+ log.info("\nCertificate : " + certificate + "\n");
+
+ return certificate;
+
+ } catch (CertificateException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-security/src/test/java/org/javaee7/jaxrpc/security/HelloTest.java b/jaxrpc/jaxrpc-security/src/test/java/org/javaee7/jaxrpc/security/HelloTest.java
new file mode 100644
index 000000000..ebbc6068b
--- /dev/null
+++ b/jaxrpc/jaxrpc-security/src/test/java/org/javaee7/jaxrpc/security/HelloTest.java
@@ -0,0 +1,102 @@
+/** Copyright Payara Services Limited **/
+package org.javaee7.jaxrpc.security;
+
+import static javax.xml.rpc.Stub.ENDPOINT_ADDRESS_PROPERTY;
+import static javax.xml.rpc.Stub.PASSWORD_PROPERTY;
+import static javax.xml.rpc.Stub.USERNAME_PROPERTY;
+import static org.javaee7.ServerOperations.addUsersToContainerIdentityStore;
+import static org.jboss.shrinkwrap.api.ShrinkWrap.create;
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.rmi.RemoteException;
+
+import javax.xml.rpc.ServiceException;
+import javax.xml.rpc.Stub;
+
+import org.javaee7.jaxrpc.security.HelloService;
+import org.javaee7.jaxrpc.security.HelloServiceImpl;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.container.test.api.RunAsClient;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import stub.MyHelloService_Impl;
+
+
+/**
+ * This test demonstrates doing a SOAP request using client side generated stubs to a remote
+ * JAX-RPC SOAP service that is protected by an authentication mechanism that requires an
+ * encrypted username/password credential.
+ *
+ * @author Arjan Tijms
+ *
+ */
+@RunWith(Arquillian.class)
+public class HelloTest {
+
+ private static final String WEBAPP_SRC = "src/main/webapp";
+
+ @ArquillianResource
+ private URL url;
+
+
+ @Deployment(testable = false)
+ public static WebArchive createDeployment() {
+ System.out.println("************** DEPLOYING ************************************");
+
+ System.out.println("Adding test user u1 with group g1");
+
+ addUsersToContainerIdentityStore();
+
+ WebArchive war =
+ create(WebArchive.class)
+ .addClasses(HelloService.class, HelloServiceImpl.class)
+
+ // The wsdl describes the HelloService.class in xml. The .wsdl is generated from HelloService by the wscompile tool
+ // (see build.xml).
+ .addAsWebInfResource(new File(WEBAPP_SRC + "/WEB-INF/wsdl", "MyHelloService.wsdl"), "wsdl/MyHelloService.wsdl")
+
+ // The mapping.xml more precisely describes the HelloService.class in xml.
+ // It's also generated from it by the wscompile tool
+ .addAsWebInfResource(new File(WEBAPP_SRC + "/WEB-INF", "mapping.xml"))
+
+ // webservices.xml is the entry file for webservices that links to the .wsdl and mapping.xml
+ // mentioned above, and to a (virtual) servlet class.
+ .addAsWebInfResource(new File(WEBAPP_SRC + "/WEB-INF", "webservices.xml"))
+
+ // Maps the (virtual) servlet class introduced in webservices.xml to a URL pattern
+ // This thus effectively gives the webservice a path, e.g. localhost:8080/ourapp/path.
+ .addAsWebInfResource(new File(WEBAPP_SRC + "/WEB-INF", "web.xml"))
+
+ // Maps (in a SUN specific way) SOAP security constraints to the webservice.
+ .addAsWebInfResource(new File(WEBAPP_SRC + "/WEB-INF", "sun-web.xml"))
+ ;
+
+ System.out.println(war.toString(true));
+ System.out.println("************************************************************");
+
+ return war;
+ }
+
+ @Test
+ @RunAsClient
+ public void testHelloStaticStub() throws MalformedURLException, ServiceException, RemoteException {
+
+ stub.HelloService helloService = new MyHelloService_Impl().getHelloServicePort();
+
+ ((Stub) helloService)._setProperty(USERNAME_PROPERTY, "u1");
+ ((Stub) helloService)._setProperty(PASSWORD_PROPERTY, "p1");
+ ((Stub) helloService)._setProperty(ENDPOINT_ADDRESS_PROPERTY, url + "hello");
+
+ String result = helloService.sayHello("Sailor");
+
+ assertEquals("Hello Sailor", result);
+ }
+
+}
diff --git a/jaxrpc/jaxrpc-security/src/test/java/stub/.gitignore b/jaxrpc/jaxrpc-security/src/test/java/stub/.gitignore
new file mode 100644
index 000000000..d38d7117f
--- /dev/null
+++ b/jaxrpc/jaxrpc-security/src/test/java/stub/.gitignore
@@ -0,0 +1,11 @@
+/HelloService.java
+/HelloService_Stub.java
+/HelloService_sayHello_RequestStruct.java
+/HelloService_sayHello_RequestStruct_SOAPBuilder.java
+/HelloService_sayHello_RequestStruct_SOAPSerializer.java
+/HelloService_sayHello_ResponseStruct.java
+/HelloService_sayHello_ResponseStruct_SOAPBuilder.java
+/HelloService_sayHello_ResponseStruct_SOAPSerializer.java
+/MyHelloService.java
+/MyHelloService_Impl.java
+/MyHelloService_SerializerRegistry.java
diff --git a/jaxrpc/jaxrpc-security/src/test/java/stub/package-info.java b/jaxrpc/jaxrpc-security/src/test/java/stub/package-info.java
new file mode 100644
index 000000000..b5d90e5a7
--- /dev/null
+++ b/jaxrpc/jaxrpc-security/src/test/java/stub/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * Generated Client Stubs will appear in this package after the Maven build is executed.
+ * The test {@link org.javaee7.jaxrpc.security.HelloTest} depends on these stubs.
+ */
+package stub;
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-security/src/test/resources/addUsersPayara.txt b/jaxrpc/jaxrpc-security/src/test/resources/addUsersPayara.txt
new file mode 100644
index 000000000..037cdbd6f
--- /dev/null
+++ b/jaxrpc/jaxrpc-security/src/test/resources/addUsersPayara.txt
@@ -0,0 +1 @@
+create-file-user --groups g1 --passwordfile ${project.build.directory}/test-classes/password.txt u1
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-security/src/test/resources/client-security.xml b/jaxrpc/jaxrpc-security/src/test/resources/client-security.xml
new file mode 100644
index 000000000..8dfce3bcf
--- /dev/null
+++ b/jaxrpc/jaxrpc-security/src/test/resources/client-security.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}UsernameToken
+
+
+
+
+
+
+ org.javaee7.jaxrpc.security.ClientTestCallbackHandler
+
+
+
\ No newline at end of file
diff --git a/jaxrpc/jaxrpc-security/src/test/resources/password.txt b/jaxrpc/jaxrpc-security/src/test/resources/password.txt
new file mode 100644
index 000000000..c00bb4cac
--- /dev/null
+++ b/jaxrpc/jaxrpc-security/src/test/resources/password.txt
@@ -0,0 +1 @@
+AS_ADMIN_USERPASSWORD=p1
diff --git a/jaxrpc/jaxrpc-security/src/test/resources/s1as.cert b/jaxrpc/jaxrpc-security/src/test/resources/s1as.cert
new file mode 100644
index 000000000..ddeb066af
--- /dev/null
+++ b/jaxrpc/jaxrpc-security/src/test/resources/s1as.cert
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDnTCCAoWgAwIBAgIEXvcwLTANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJV
+SzEXMBUGA1UECBMOV29yY2VzdGVyc2hpcmUxFjAUBgNVBAcTDUdyZWF0IE1hbHZl
+cm4xGjAYBgNVBAoTEVBheWFyYSBGb3VuZGF0aW9uMQ8wDQYDVQQLEwZQYXlhcmEx
+EjAQBgNVBAMTCWxvY2FsaG9zdDAeFw0xODA1MjAxODU4MjBaFw0yODA1MTcxODU4
+MjBaMH8xCzAJBgNVBAYTAlVLMRcwFQYDVQQIEw5Xb3JjZXN0ZXJzaGlyZTEWMBQG
+A1UEBxMNR3JlYXQgTWFsdmVybjEaMBgGA1UEChMRUGF5YXJhIEZvdW5kYXRpb24x
+DzANBgNVBAsTBlBheWFyYTESMBAGA1UEAxMJbG9jYWxob3N0MIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjWQpZBdLfVeIPlvqyDAQElJ3fdipdVX+PkZi
+jAQF0ob3USho1Z/1gfNb60u1V4i1JBFYVkuLa5foB9NibMOU1NoDmdaSTlAdxJj2
+CrenI0u6PrBToc/wYSTXrY3XkiCmWq4PKEAyPJMKhFdqzw2dzgsuXIciW62MEKII
+wGZWNZB+EcLDLKcnq2lhjJJqa9G9Vf13JGkOFko5W6t1ZWCD7S3GHvtok6woBy5q
+5UsXNayB7j7Ikc1WYMHWyHpxGp3tFzvVusbBcYpszdZ5o+m/ngZ96xkeKFmi/Id3
+1+Y8y8DeovOjFkdbXzk48iMuw7oXRSyUkXJXZazDHfNMW50gfwIDAQABoyEwHzAd
+BgNVHQ4EFgQUX39J70I96D9VCrS3Y7sW/3v2ZucwDQYJKoZIhvcNAQELBQADggEB
+ABB0mOmyF3T96WEj2oCbFaJUYU4i9Oe+58rq5+ktIt0BYwNm1OCEIzm3sQHCnNOT
+/uibHP/bSVndsoC7FtbHmIyyPIOYnFGrLZYOkHfset6y3aCxCZ4fDRLhTu1EmScX
+bY/BEFA46I7Y1ae47wWX0QuQ9j4d4N1DzpG5nhXHp6vDMpT4cS28yOBRwCn5ZnY+
+Qh87xk1QqNrHw0TNa2cBLiSItUGLH42iPL+B+rOnWvK3ky5WR+bcdRnOIxNIYzer
+UmqTi8TKrZTX61Bvj6nWMfnnrpON0DEaHYVzqlhyXhe2ftTY0hJSgfDJYdVDBlVh
+cCOLpj4QFF7S4x+G5gbLRH0=
+-----END CERTIFICATE-----
diff --git a/jaxrpc/jaxrpc-security/src/test/resources/wscompile-client-config.xml b/jaxrpc/jaxrpc-security/src/test/resources/wscompile-client-config.xml
new file mode 100644
index 000000000..66455fd5b
--- /dev/null
+++ b/jaxrpc/jaxrpc-security/src/test/resources/wscompile-client-config.xml
@@ -0,0 +1,14 @@
+
+
+
+
\ No newline at end of file
diff --git a/jaxrpc/pom.xml b/jaxrpc/pom.xml
new file mode 100644
index 000000000..fee49f706
--- /dev/null
+++ b/jaxrpc/pom.xml
@@ -0,0 +1,27 @@
+
+ 4.0.0
+
+
+ org.javaee7
+ samples-parent
+ 1.0-SNAPSHOT
+
+
+ jaxrpc
+ pom
+ Java EE 7 Sample: jaxrpc
+
+
+ jaxrpc-endpoint
+ jaxrpc-security
+
+
+
+
+ org.javaee7
+ test-utils
+ ${project.version}
+ test
+
+
+
diff --git a/jaxrs/README.md b/jaxrs/README.md
new file mode 100644
index 000000000..5dae57a2c
--- /dev/null
+++ b/jaxrs/README.md
@@ -0,0 +1,40 @@
+# Java EE 7 Samples: JAX-RS 2.0#
+
+The [JSR 339](https://jcp.org/en/jsr/detail?id=339) specifies the next version of JAX-RS, the API for for RESTful (Representational State Transfer) Web Services in the Java Platform.
+
+## Samples ##
+
+ - async-client
+ - async-server
+ - beanvalidation
+ - beanparam
+ - client-negotiation
+ - dynamicfilter
+ - fileupload
+ - filter
+ - filter-interceptor
+ - interceptor
+ - invocation
+ - invocation-async
+ - jaxrs-client
+ - jaxrs-endpoint
+ - jsonp
+ - link
+ - mapping-exceptions
+ - paramconverter
+ - readerwriter
+ - readerwriter-json
+ - request-binding
+ - resource-validation
+ - server-negotiation
+ - singleton
+ - readerwriter-injection
+ - jaxrs-security-declarative
+ - db-access
+
+
+## How to run
+
+More information on how to run can be found at:
+
+
diff --git a/jaxrs/async-client/pom.xml b/jaxrs/async-client/pom.xml
index 8d3840d01..cf09c2039 100644
--- a/jaxrs/async-client/pom.xml
+++ b/jaxrs/async-client/pom.xml
@@ -1,15 +1,17 @@
-
+
+
4.0.0
+
- org.javaee7.jaxrs
- jaxrs-samples
+ org.javaee7
+ jaxrs
1.0-SNAPSHOT
../pom.xml
-
- org.javaee7.jaxrs
- async-client
+ org.javaee7
+ jaxrs-async-client
1.0-SNAPSHOT
war
+ Java EE 7 Sample: jaxrs - async-client
+ Invoke a JAX-RS service via an asynchronous client
diff --git a/jaxrs/async-client/src/main/java/org/javaee7/jaxrs/asyncclient/MyApplication.java b/jaxrs/async-client/src/main/java/org/javaee7/jaxrs/asyncclient/MyApplication.java
index 4fad465d3..eea898998 100644
--- a/jaxrs/async-client/src/main/java/org/javaee7/jaxrs/asyncclient/MyApplication.java
+++ b/jaxrs/async-client/src/main/java/org/javaee7/jaxrs/asyncclient/MyApplication.java
@@ -47,5 +47,5 @@
*/
@ApplicationPath("webresources")
public class MyApplication extends Application {
-
+
}
diff --git a/jaxrs/async-client/src/main/java/org/javaee7/jaxrs/asyncclient/MyResource.java b/jaxrs/async-client/src/main/java/org/javaee7/jaxrs/asyncclient/MyResource.java
index 65e737f1b..4ac98ac62 100644
--- a/jaxrs/async-client/src/main/java/org/javaee7/jaxrs/asyncclient/MyResource.java
+++ b/jaxrs/async-client/src/main/java/org/javaee7/jaxrs/asyncclient/MyResource.java
@@ -48,7 +48,7 @@
@Path("fruits")
public class MyResource {
private final String[] response = { "apple", "banana", "mango" };
-
+
@GET
public String getList() {
return response[0];
diff --git a/jaxrs/async-client/src/test/java/org/javaee7/jaxrs/asyncclient/MyResourceTest.java b/jaxrs/async-client/src/test/java/org/javaee7/jaxrs/asyncclient/MyResourceTest.java
index 34a5563a7..1d6f34048 100644
--- a/jaxrs/async-client/src/test/java/org/javaee7/jaxrs/asyncclient/MyResourceTest.java
+++ b/jaxrs/async-client/src/test/java/org/javaee7/jaxrs/asyncclient/MyResourceTest.java
@@ -1,14 +1,10 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
package org.javaee7.jaxrs.asyncclient;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.net.MalformedURLException;
+import java.net.URI;
import java.net.URL;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@@ -29,65 +25,105 @@
import org.junit.runner.RunWith;
/**
- * @author Arun Gupta
+ * In this sample we're going to explore how to communicate with a +JAX-RS+
+ * service via an asynchronous invocation from the client.
+ *
+ * First step; we need a service to invoke.
+ *
+ * Let's create a simple +GET+ method.
+ *
+ * include::MyResource#getList[]
+ *
+ * For +JAX-RS+ to expose our service we need to provide an implementation of
+ * the +JAX-RS+ +Application+ class to define our root path.
+ *
+ * include::MyApplication[]
*/
@RunWith(Arquillian.class)
public class MyResourceTest {
-
+
+ /**
+ * Since +JAX-RS+ webservices are, well, web related and require a
+ * web context, they are required to be deployed within a +web archive+.
+ * By default, +JAX-RS+ will perform autodiscovery of our services.
+ * That means there is no need to add a +web.xml+ in this scenario.
+ *
+ * Based on the definition of our +@Deployment+ method, we will be
+ * creating and deploying the following archive structure.
+ * [source,file]
+ * ----
+ * /WEB-INF/
+ * /WEB-INF/classes/
+ * /WEB-INF/classes/org/
+ * /WEB-INF/classes/org/javaee7/jaxrs/
+ * /WEB-INF/classes/org/javaee7/jaxrs/asyncclient/
+ * /WEB-INF/classes/org/javaee7/jaxrs/asyncclient/MyResource.class
+ * /WEB-INF/classes/org/javaee7/jaxrs/asyncclient/MyApplication.class
+ * ----
+ */
@Deployment(testable = false)
public static WebArchive createDeployment() {
- return ShrinkWrap.create(WebArchive.class)
- .addClasses(MyApplication.class, MyResource.class);
+ return ShrinkWrap.create(WebArchive.class)
+ .addClasses(MyApplication.class, MyResource.class);
}
@ArquillianResource
private URL base;
-
+
private static WebTarget target;
@Before
public void setUpClass() throws MalformedURLException {
Client client = ClientBuilder.newClient();
- target = client.target(new URL(base, "webresources/fruits").toExternalForm());
+ target = client.target(URI.create(new URL(base, "webresources/fruits").toExternalForm()));
}
/**
- * Test of getList method, of class MyResource.
+ * Before we can invoke our service we need to setup the client.
+ *
+ * include::MyResourceTest#setUpClass[]
+ *
+ * Now we are free to invoke our deployed service by using the +JAX-RS+
+ * client library.
+ *
+ * The asynchronous client library comes with multiple option on how
+ * to invoke the methods. First let's look at using the +Future+ option
+ * with access to the complete +Response+.
*/
@Test
public void testPollingResponse() throws InterruptedException, ExecutionException {
- Future r1 = target.request().async().get();
- String response = r1.get().readEntity(String.class);
- assertEquals("apple", response);
+ Future r1 = target.request().async().get(); // <1> Build an asynchronous request handler for the +Response+ object
+ String response = r1.get().readEntity(String.class); // <2> Read the entity from the body of the +Response+
+ assertEquals("apple", response); // <3> Validate we got the expected value
}
/**
- * Test of getList method, of class MyResource.
+ * Another possibility is to use the +Future+ option with access to only the +Response+ body.
*/
@Test
public void testPollingString() throws InterruptedException, ExecutionException {
- Future r1 = target.request().async().get(String.class);
- String response = r1.get();
- assertEquals("apple", response);
+ Future r1 = target.request().async().get(String.class); // <1> Build an asynchronous request handler for the body of the +Response+
+ String response = r1.get(); // <2> Read the entity directly from the +Future+
+ assertEquals("apple", response); // <3> Validate we got the expected value
}
/**
- * Test of getList method, of class MyResource.
+ * You can also register a +InvocationCallback+ and get a callback when the +Request+ is done.
*/
@Test
public void testInvocationCallback() throws InterruptedException, ExecutionException {
- target.request().async().get(new InvocationCallback() {
+ target.request().async().get(new InvocationCallback() { // <1> Build an asynchronous request callback for the body of the +Response+
@Override
- public void completed(String r) {
+ public void completed(String r) { // <2> Called when the +Request+ is completed and our entiy parsed
assertEquals("apple", r);
}
@Override
- public void failed(Throwable t) {
+ public void failed(Throwable t) { // <3> Called if the +Request+ failed to complete
fail(t.getMessage());
}
-
+
});
}
diff --git a/jaxrs/async-server/pom.xml b/jaxrs/async-server/pom.xml
index 7b8f69624..b5378c3ff 100644
--- a/jaxrs/async-server/pom.xml
+++ b/jaxrs/async-server/pom.xml
@@ -1,15 +1,16 @@
-
+
+
4.0.0
+
- org.javaee7.jaxrs
- jaxrs-samples
+ org.javaee7
+ jaxrs
1.0-SNAPSHOT
../pom.xml
-
- org.javaee7.jaxrs
- async-server
+ org.javaee7
+ jaxrs-async-server
1.0-SNAPSHOT
war
+ Java EE 7 Sample: jaxrs - async-server
diff --git a/jaxrs/async-server/src/main/java/org/javaee7/jaxrs/asyncserver/MyApplication.java b/jaxrs/async-server/src/main/java/org/javaee7/jaxrs/asyncserver/MyApplication.java
index d31463d9f..83f769827 100644
--- a/jaxrs/async-server/src/main/java/org/javaee7/jaxrs/asyncserver/MyApplication.java
+++ b/jaxrs/async-server/src/main/java/org/javaee7/jaxrs/asyncserver/MyApplication.java
@@ -47,5 +47,5 @@
*/
@ApplicationPath("webresources")
public class MyApplication extends Application {
-
+
}
diff --git a/jaxrs/async-server/src/main/java/org/javaee7/jaxrs/asyncserver/MyResource.java b/jaxrs/async-server/src/main/java/org/javaee7/jaxrs/asyncserver/MyResource.java
index b046baeb4..53b49806c 100644
--- a/jaxrs/async-server/src/main/java/org/javaee7/jaxrs/asyncserver/MyResource.java
+++ b/jaxrs/async-server/src/main/java/org/javaee7/jaxrs/asyncserver/MyResource.java
@@ -59,10 +59,10 @@
@Path("fruits")
public class MyResource {
private final String[] response = { "apple", "banana", "mango" };
-
-// @Resource(name = "DefaultManagedThreadFactory")
-// ManagedThreadFactory threadFactory;
-
+
+ // @Resource(name = "DefaultManagedThreadFactory")
+ // ManagedThreadFactory threadFactory;
+
@GET
public void getList(@Suspended final AsyncResponse ar) throws NamingException {
ar.setTimeoutHandler(new TimeoutHandler() {
@@ -73,13 +73,13 @@ public void handleTimeout(AsyncResponse ar) {
}
});
ar.setTimeout(4000, TimeUnit.MILLISECONDS);
-
+
ar.register(new MyCompletionCallback());
ar.register(new MyConnectionCallback());
-
+
ManagedThreadFactory threadFactory = (ManagedThreadFactory) new InitialContext()
- .lookup("java:comp/DefaultManagedThreadFactory");
-
+ .lookup("java:comp/DefaultManagedThreadFactory");
+
Executors.newSingleThreadExecutor(threadFactory).submit(new Runnable() {
@Override
@@ -88,29 +88,29 @@ public void run() {
Thread.sleep(3000);
ar.resume(response[0]);
} catch (InterruptedException ex) {
-
+
}
}
-
+
});
}
-
+
class MyCompletionCallback implements CompletionCallback {
@Override
public void onComplete(Throwable t) {
System.out.println("onComplete");
}
-
+
}
-
+
class MyConnectionCallback implements ConnectionCallback {
@Override
public void onDisconnect(AsyncResponse ar) {
System.out.println("onDisconnect");
}
-
+
}
}
diff --git a/jaxrs/async-server/src/test/java/org/javaee7/jaxrs/asyncserver/MyResourceTest.java b/jaxrs/async-server/src/test/java/org/javaee7/jaxrs/asyncserver/MyResourceTest.java
index 76abfadbe..330c0efb2 100644
--- a/jaxrs/async-server/src/test/java/org/javaee7/jaxrs/asyncserver/MyResourceTest.java
+++ b/jaxrs/async-server/src/test/java/org/javaee7/jaxrs/asyncserver/MyResourceTest.java
@@ -1,14 +1,9 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-
package org.javaee7.jaxrs.asyncserver;
import static org.junit.Assert.assertEquals;
import java.net.MalformedURLException;
+import java.net.URI;
import java.net.URL;
import javax.ws.rs.client.Client;
@@ -29,11 +24,11 @@
*/
@RunWith(Arquillian.class)
public class MyResourceTest {
-
+
@Deployment(testable = false)
public static WebArchive createDeployment() {
- return ShrinkWrap.create(WebArchive.class)
- .addClasses(MyApplication.class, MyResource.class);
+ return ShrinkWrap.create(WebArchive.class)
+ .addClasses(MyApplication.class, MyResource.class);
}
private WebTarget target;
@@ -44,9 +39,9 @@ public static WebArchive createDeployment() {
@Before
public void setUpClass() throws MalformedURLException {
Client client = ClientBuilder.newClient();
- target = client.target(new URL(base, "webresources/fruits").toExternalForm());
+ target = client.target(URI.create(new URL(base, "webresources/fruits").toExternalForm()));
}
-
+
/**
* Test of getList method, of class MyResource.
*/
@@ -55,5 +50,5 @@ public void testGetList() {
String result = target.request().get(String.class);
assertEquals("apple", result);
}
-
+
}
diff --git a/jaxrs/beanparam/README.adoc b/jaxrs/beanparam/README.adoc
new file mode 100644
index 000000000..1dc122136
--- /dev/null
+++ b/jaxrs/beanparam/README.adoc
@@ -0,0 +1,5 @@
+= JAX-RS BeanParam
+
+This example demonstrate the use of a +@BeanParam+ annotation to group some of the request parameters in a user bean, in order to avoid having too many paramaters in the method signature.
+
+The user type annotated with +@BeanParam+ may contain fields or setter methods annotated with +@MatrixParam+, +@QueryParam+, +@PathParam+, +@CookieParam+ or +@HeaderParam+.
\ No newline at end of file
diff --git a/jaxrs/beanparam/pom.xml b/jaxrs/beanparam/pom.xml
new file mode 100644
index 000000000..452ab8555
--- /dev/null
+++ b/jaxrs/beanparam/pom.xml
@@ -0,0 +1,16 @@
+
+
+ 4.0.0
+
+
+ org.javaee7
+ jaxrs
+ 1.0-SNAPSHOT
+ ../pom.xml
+
+ org.javaee7
+ jaxrs-beanparam
+ 1.0-SNAPSHOT
+ war
+ Java EE 7 Sample: jaxrs - beanparam
+
diff --git a/jaxrs/beanparam/src/main/java/org/javaee7/jaxrs/beanparam/MyApplication.java b/jaxrs/beanparam/src/main/java/org/javaee7/jaxrs/beanparam/MyApplication.java
new file mode 100644
index 000000000..fef4ba6e5
--- /dev/null
+++ b/jaxrs/beanparam/src/main/java/org/javaee7/jaxrs/beanparam/MyApplication.java
@@ -0,0 +1,12 @@
+package org.javaee7.jaxrs.beanparam;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+/**
+ * @author Arun Gupta
+ */
+@ApplicationPath("webresources")
+public class MyApplication extends Application {
+
+}
diff --git a/jaxrs/beanparam/src/main/java/org/javaee7/jaxrs/beanparam/MyPathParams.java b/jaxrs/beanparam/src/main/java/org/javaee7/jaxrs/beanparam/MyPathParams.java
new file mode 100644
index 000000000..24fb473ca
--- /dev/null
+++ b/jaxrs/beanparam/src/main/java/org/javaee7/jaxrs/beanparam/MyPathParams.java
@@ -0,0 +1,33 @@
+package org.javaee7.jaxrs.beanparam;
+
+import javax.ws.rs.PathParam;
+
+/**
+ * @author xcoulon
+ *
+ */
+public class MyPathParams {
+
+ @PathParam("id1")
+ private String id1;
+
+ private String id2;
+
+ public String getId1() {
+ return id1;
+ }
+
+ public void setId1(String id1) {
+ this.id1 = id1;
+ }
+
+ public String getId2() {
+ return id2;
+ }
+
+ @PathParam("id2")
+ public void setId2(String id2) {
+ this.id2 = id2;
+ }
+
+}
diff --git a/jaxrs/beanparam/src/main/java/org/javaee7/jaxrs/beanparam/MyQueryParams.java b/jaxrs/beanparam/src/main/java/org/javaee7/jaxrs/beanparam/MyQueryParams.java
new file mode 100644
index 000000000..04195777f
--- /dev/null
+++ b/jaxrs/beanparam/src/main/java/org/javaee7/jaxrs/beanparam/MyQueryParams.java
@@ -0,0 +1,32 @@
+package org.javaee7.jaxrs.beanparam;
+
+import javax.ws.rs.QueryParam;
+
+/**
+ * @author xcoulon
+ *
+ */
+public class MyQueryParams {
+
+ @QueryParam("param1")
+ private String param1;
+
+ @QueryParam("param2")
+ private String param2;
+
+ @QueryParam("param3")
+ private String param3;
+
+ public String getParam1() {
+ return param1;
+ }
+
+ public String getParam2() {
+ return param2;
+ }
+
+ public String getParam3() {
+ return param3;
+ }
+
+}
diff --git a/jaxrs/beanparam/src/main/java/org/javaee7/jaxrs/beanparam/MyResource.java b/jaxrs/beanparam/src/main/java/org/javaee7/jaxrs/beanparam/MyResource.java
new file mode 100644
index 000000000..ae174fa86
--- /dev/null
+++ b/jaxrs/beanparam/src/main/java/org/javaee7/jaxrs/beanparam/MyResource.java
@@ -0,0 +1,22 @@
+package org.javaee7.jaxrs.beanparam;
+
+import javax.ws.rs.BeanParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+/**
+ * @author Xavier Coulon
+ */
+@Path("/endpoint")
+public class MyResource {
+
+ @GET()
+ @Path("/{id1}/{id2}")
+ @Produces(MediaType.TEXT_PLAIN)
+ public String get(@BeanParam MyPathParams pathParams, @BeanParam MyQueryParams queryParams) {
+ return "/" + pathParams.getId1() + "/" + pathParams.getId2() + "?param1=" + queryParams.getParam1() + "¶m2="
+ + queryParams.getParam2() + "¶m3=" + queryParams.getParam3();
+ }
+}
diff --git a/jaxrs/beanparam/src/test/java/org/javaee7/jaxrs/beanparam/MyResourceTest.java b/jaxrs/beanparam/src/test/java/org/javaee7/jaxrs/beanparam/MyResourceTest.java
new file mode 100644
index 000000000..8f94e3958
--- /dev/null
+++ b/jaxrs/beanparam/src/test/java/org/javaee7/jaxrs/beanparam/MyResourceTest.java
@@ -0,0 +1,53 @@
+package org.javaee7.jaxrs.beanparam;
+
+import static org.junit.Assert.assertEquals;
+
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.WebTarget;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * @author Arun Gupta
+ * @author Xavier Coulon
+ */
+@RunWith(Arquillian.class)
+public class MyResourceTest {
+
+ @Deployment(testable = false)
+ public static WebArchive createDeployment() {
+ return ShrinkWrap.create(WebArchive.class)
+ .addClasses(MyApplication.class, MyResource.class, MyPathParams.class, MyQueryParams.class);
+ }
+
+ private static WebTarget target;
+
+ @ArquillianResource
+ private URL base;
+
+ @Before
+ public void setUpClass() throws MalformedURLException {
+ Client client = ClientBuilder.newClient();
+ target = client.target(URI.create(new URL(base, "webresources/endpoint").toExternalForm()));
+ }
+
+ @Test
+ public void testRequestWithAllParams() {
+ WebTarget t = target.path("/123").path("/abc").queryParam("param1", "foo").queryParam("param2", "bar").queryParam("param3", "baz");
+ String r = t.request().get(String.class);
+ assertEquals("/123/abc?param1=foo¶m2=bar¶m3=baz", r);
+ }
+
+}
diff --git a/jaxrs/beanvalidation/pom.xml b/jaxrs/beanvalidation/pom.xml
index 66db1a28a..6fa91f18d 100644
--- a/jaxrs/beanvalidation/pom.xml
+++ b/jaxrs/beanvalidation/pom.xml
@@ -1,15 +1,16 @@
-
+
+
4.0.0
+
- org.javaee7.jaxrs
- jaxrs-samples
+ org.javaee7
+ jaxrs
1.0-SNAPSHOT
../pom.xml
-
- org.javaee7.jaxrs
- beanvalidation
+ org.javaee7
+ jaxrs-beanvalidation
1.0-SNAPSHOT
war
+ Java EE 7 Sample: jaxrs - beanvalidation
diff --git a/jaxrs/beanvalidation/src/main/java/org/javaee7/jaxrs/beanvalidation/MyResource.java b/jaxrs/beanvalidation/src/main/java/org/javaee7/jaxrs/beanvalidation/MyResource.java
index 61b4af8d0..18c527e04 100644
--- a/jaxrs/beanvalidation/src/main/java/org/javaee7/jaxrs/beanvalidation/MyResource.java
+++ b/jaxrs/beanvalidation/src/main/java/org/javaee7/jaxrs/beanvalidation/MyResource.java
@@ -39,7 +39,12 @@
*/
package org.javaee7.jaxrs.beanvalidation;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
@@ -56,4 +61,9 @@ public class MyResource {
public String post(@Size(min = 3) String payload) {
return payload;
}
+
+ @POST
+ @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+ public void post2(@NotNull @FormParam("name") String name, @Min(1) @Max(10) @FormParam("age") int age) {
+ }
}
diff --git a/jaxrs/beanvalidation/src/test/java/org/javaee7/jaxrs/beanvalidation/MyResourceTest.java b/jaxrs/beanvalidation/src/test/java/org/javaee7/jaxrs/beanvalidation/MyResourceTest.java
index 519ad7d05..2912c918d 100644
--- a/jaxrs/beanvalidation/src/test/java/org/javaee7/jaxrs/beanvalidation/MyResourceTest.java
+++ b/jaxrs/beanvalidation/src/test/java/org/javaee7/jaxrs/beanvalidation/MyResourceTest.java
@@ -1,8 +1,3 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
package org.javaee7.jaxrs.beanvalidation;
import static org.junit.Assert.assertEquals;
@@ -10,6 +5,7 @@
import static org.junit.Assert.fail;
import java.net.MalformedURLException;
+import java.net.URI;
import java.net.URL;
import javax.ws.rs.BadRequestException;
@@ -17,6 +13,7 @@
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MultivaluedHashMap;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
@@ -35,9 +32,10 @@ public class MyResourceTest {
@Deployment(testable = false)
public static WebArchive createDeployment() {
- return ShrinkWrap.create(WebArchive.class)
- .addClasses(MyApplication.class, MyResource.class);
+ return ShrinkWrap.create(WebArchive.class)
+ .addClasses(MyApplication.class, MyResource.class);
}
+
private static WebTarget target;
@ArquillianResource
@@ -46,7 +44,7 @@ public static WebArchive createDeployment() {
@Before
public void setUpClass() throws MalformedURLException {
Client client = ClientBuilder.newClient();
- target = client.target(new URL(base, "webresources/endpoint").toExternalForm());
+ target = client.target(URI.create(new URL(base, "webresources/endpoint").toExternalForm()));
}
@Test
@@ -65,4 +63,53 @@ public void testValidRequest() {
assertEquals("foo", r);
}
+ @Test
+ public void testValidPostRequest() {
+ MultivaluedHashMap map = new MultivaluedHashMap<>();
+ map.add("name", "Penny");
+ map.add("age", "1");
+ target.request().post(Entity.form(map));
+
+ map.clear();
+ map.add("name", "Leonard");
+ map.add("age", "2");
+ target.request().post(Entity.form(map));
+ }
+
+ @Test
+ public void testInvalidPostRequest() {
+ try {
+ MultivaluedHashMap map = new MultivaluedHashMap<>();
+ map.add("name", null);
+ map.add("age", "1");
+ target.request().post(Entity.form(map));
+ } catch (BadRequestException e) {
+ assertNotNull(e);
+ }
+ }
+
+ @Test
+ public void testInvalidPostRequestLesserAge() {
+ try {
+ MultivaluedHashMap map = new MultivaluedHashMap<>();
+ map.add("name", "Penny");
+ map.add("age", "0");
+ target.request().post(Entity.form(map));
+ } catch (BadRequestException e) {
+ assertNotNull(e);
+ }
+ }
+
+ @Test
+ public void testInvalidPostRequestGreaterAge() {
+ try {
+ MultivaluedHashMap map = new MultivaluedHashMap<>();
+ map.add("name", "Penny");
+ map.add("age", "11");
+ target.request().post(Entity.form(map));
+ } catch (BadRequestException e) {
+ assertNotNull(e);
+ }
+ }
+
}
diff --git a/jaxrs/client-negotiation/pom.xml b/jaxrs/client-negotiation/pom.xml
index 1be7a4eb0..78542067c 100644
--- a/jaxrs/client-negotiation/pom.xml
+++ b/jaxrs/client-negotiation/pom.xml
@@ -1,15 +1,16 @@
-
+
+
4.0.0
+
- org.javaee7.jaxrs
- jaxrs-samples
+ org.javaee7
+ jaxrs
1.0-SNAPSHOT
../pom.xml
-
- org.javaee7.jaxrs
- client-negotiation
+ org.javaee7
+ jaxrs-client-negotiation
1.0-SNAPSHOT
war
+ Java EE 7 Sample: jaxrs - client-negotiation
diff --git a/jaxrs/client-negotiation/src/main/java/org/javaee7/jaxrs/client/negotiation/MyApplication.java b/jaxrs/client-negotiation/src/main/java/org/javaee7/jaxrs/client/negotiation/MyApplication.java
index 97c3ae169..9a8983c45 100644
--- a/jaxrs/client-negotiation/src/main/java/org/javaee7/jaxrs/client/negotiation/MyApplication.java
+++ b/jaxrs/client-negotiation/src/main/java/org/javaee7/jaxrs/client/negotiation/MyApplication.java
@@ -55,5 +55,5 @@ public Set> getClasses() {
resources.add(MyResource.class);
return resources;
}
-
+
}
diff --git a/jaxrs/client-negotiation/src/main/java/org/javaee7/jaxrs/client/negotiation/MyResource.java b/jaxrs/client-negotiation/src/main/java/org/javaee7/jaxrs/client/negotiation/MyResource.java
index 4493f778b..3180714d3 100644
--- a/jaxrs/client-negotiation/src/main/java/org/javaee7/jaxrs/client/negotiation/MyResource.java
+++ b/jaxrs/client-negotiation/src/main/java/org/javaee7/jaxrs/client/negotiation/MyResource.java
@@ -51,7 +51,7 @@
@Path("persons")
public class MyResource {
@GET
- @Produces({"application/xml", "application/json"})
+ @Produces({ "application/xml", "application/json" })
public List getList() {
People people = new People();
people.add(new Person("Penny", 1));
diff --git a/jaxrs/client-negotiation/src/main/java/org/javaee7/jaxrs/client/negotiation/People.java b/jaxrs/client-negotiation/src/main/java/org/javaee7/jaxrs/client/negotiation/People.java
index 61754651a..675d31291 100644
--- a/jaxrs/client-negotiation/src/main/java/org/javaee7/jaxrs/client/negotiation/People.java
+++ b/jaxrs/client-negotiation/src/main/java/org/javaee7/jaxrs/client/negotiation/People.java
@@ -6,13 +6,13 @@
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
-@XmlRootElement
+@XmlRootElement
public class People extends ArrayList {
- private static final long serialVersionUID = 1L;
-
- @XmlElement(name = "person")
- public List