Skip to content

Commit

Permalink
tests for cdi current in new thread
Browse files Browse the repository at this point in the history
  • Loading branch information
benjamin-confino committed Sep 27, 2024
1 parent e8d2e66 commit 12eca61
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-2.0/
*
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
Expand Down Expand Up @@ -41,8 +41,8 @@ public class CDICurrentTestServlet extends FATServlet {

private static final long serialVersionUID = 1L;

//Must be manually cleared at the end of a test
private static Boolean wasCDICurrentFound = null;
private static volatile Boolean wasCDICurrentFoundViaMES = null;

@Inject
private SharedLibBean sharedLibBean;
Expand Down Expand Up @@ -70,27 +70,59 @@ public void testCDICurrent() {
* context onto a newly created thread. This test ensures that works correctly and CDI.current() returns a value
* when called from a new thread.
*
* Note that threads created via new Thread() will not have the required context and CDI.current() will return null
*/
@Test
public void testCDICurrentViaMES() throws Exception {
long startTime = System.nanoTime();
try {
long startTime = System.nanoTime();

assertNotNull(CDI.current()); //Test outside a new thread just for completeness.
assertNotNull(CDI.current()); //Test outside a new thread just for completeness.

LOGGER.info("calling managedExecutorService");
managedExecutorService.submit(new CallCDICurrent());
LOGGER.info("calling managedExecutorService");
managedExecutorService.submit(new CallCDICurrent());

while (System.nanoTime() - startTime < Duration.of(10, SECONDS).toNanos()) {
if (wasCDICurrentFoundViaMES != null) {
assertTrue("CDI.current returned null when called in a new Thread", wasCDICurrentFoundViaMES);
return;
while (System.nanoTime() - startTime < Duration.of(10, SECONDS).toNanos()) {
if (wasCDICurrentFound != null) {
assertTrue("CDI.current returned null when called in a new Managed Thread", wasCDICurrentFound);
return;
}
Thread.sleep(15);
}
Thread.sleep(15);

LOGGER.info("About to throw exception");
assertTrue("The thread with CDI.current never completed", false);
} finally {
wasCDICurrentFound = false;
}
}

LOGGER.info("About to throw exception");
assertTrue("The thread with CDI.current never completed", false);
/*
* We have implemented a fallback that allows CDI.current() to work if you call a new thread
* without propagating context via a ManagedExecutorService, this tests that code.
*/
@Test
public void testCDICurrentViaNewThread() throws Exception {
try {
long startTime = System.nanoTime();

assertNotNull(CDI.current()); //Test outside a new thread just for completeness.
LOGGER.info("calling managedExecutorService");
Thread thread = new Thread(new CallCDICurrent());
thread.run();

while (System.nanoTime() - startTime < Duration.of(10, SECONDS).toNanos()) {
if (wasCDICurrentFound != null) {
assertTrue("CDI.current returned null when called in a new Thread", wasCDICurrentFound);
return;
}
Thread.sleep(15);
}

LOGGER.info("About to throw exception");
assertTrue("The thread with CDI.current never completed", false);
} finally {
wasCDICurrentFound = false;
}
}

@Test
Expand All @@ -99,10 +131,8 @@ public void testCDICurrentViaSharedLib() {
}

public static void setWasCDICurrentFound(boolean b) {

wasCDICurrentFoundViaMES = b;
wasCDICurrentFound = b;
LOGGER.info("Set test variable");

}

public class CallCDICurrent implements Runnable {
Expand All @@ -113,10 +143,9 @@ public void run() {
LOGGER.info("Found CDI " + cdi);
if (cdi != null) {
CDICurrentTestServlet.setWasCDICurrentFound(true);
LOGGER.info("Calling setter for test variable");
LOGGER.info("Calling setter for test variable with true");
} else {
System.out.println("GREP 1 " + java.time.LocalDateTime.now());
LOGGER.info("Calling setter for test variable");
LOGGER.info("Calling setter for test variable with false");
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*******************************************************************************
* Copyright (c) 2024 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package com.ibm.ws.cdi.api.fat.apps.threads.extension;

import java.util.HashSet;
import java.util.Set;

import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.AfterDeploymentValidation;
import javax.enterprise.inject.spi.AfterTypeDiscovery;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.BeforeBeanDiscovery;
import javax.enterprise.inject.spi.CDI;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.ProcessAnnotatedType;
import javax.enterprise.inject.spi.ProcessBean;
import javax.enterprise.inject.spi.ProcessBeanAttributes;
import javax.enterprise.inject.spi.ProcessInjectionPoint;
import javax.enterprise.inject.spi.ProcessInjectionTarget;
import javax.enterprise.inject.spi.ProcessManagedBean;

/**
*
*/
@SuppressWarnings("rawtypes")
public class CDIExtension implements Extension {

private final Set<String> duplicatesFilter = new HashSet<String>();

public void eventListener(@Observes BeforeBeanDiscovery event) {
checkForBeanManagerInUnmanagedThread("BeforeBeanDiscovery");
}

public void eventListener(@Observes ProcessAnnotatedType event) {
checkForBeanManagerInUnmanagedThread("ProcessAnnotatedType");
}

public void eventListener(@Observes AfterTypeDiscovery event) {
checkForBeanManagerInUnmanagedThread("AfterTypeDiscovery");
}

public void eventListener(@Observes ProcessInjectionTarget event) {
checkForBeanManagerInUnmanagedThread("ProcessInjectionTarget");
}

public void eventListener(@Observes ProcessInjectionPoint event) {
checkForBeanManagerInUnmanagedThread("ProcessInjectionPoint");
}

public void eventListener(@Observes ProcessBeanAttributes event) {
checkForBeanManagerInUnmanagedThread("ProcessBeanAttributes");
}

public void eventListener(@Observes ProcessBean event) {
checkForBeanManagerInUnmanagedThread("ProcessBean");
}

public void eventListener(@Observes ProcessManagedBean event) {
checkForBeanManagerInUnmanagedThread("ProcessManagedBean");
}

public void eventListener(@Observes AfterBeanDiscovery event) {
checkForBeanManagerInUnmanagedThread("AfterBeanDiscovery");
}

public void eventListener(@Observes AfterDeploymentValidation event) {
checkForBeanManagerInUnmanagedThread("AfterDeploymentValidation");
}

private void checkForBeanManagerInUnmanagedThread(final String eventName) {
Thread thread = new Thread() {
@Override
public void run() {
try {
BeanManager bm = CDI.current().getBeanManager();
String s = "found beanmanager in " + eventName + " : " + (bm instanceof BeanManager);
if (duplicatesFilter.add(s)) {
System.out.println(s);
}
} catch (Exception e) {
String s = "failed to find beanmanager in " + eventName + " : " + e.toString();
if (duplicatesFilter.add(s)) {
System.out.println(s);
}
}
}
};

thread.start();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*******************************************************************************
* Copyright (c) 2016 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.ws.cdi.api.fat.apps.threads.extension;

import javax.enterprise.context.Dependent;

import com.ibm.ws.cdi.api.fat.apps.current.sharedLib.ISimpleBean;

/**
*
*/
@Dependent
public class SimpleBean implements ISimpleBean {

public static final String MSG = "bean exists";

/** {@inheritDoc} */
@Override
public String test() {
return MSG;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
com.ibm.ws.cdi.api.fat.apps.threads.extension.CDIExtension
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.EnterpriseArchive;
Expand Down Expand Up @@ -46,6 +48,7 @@
import com.ibm.ws.cdi.api.fat.apps.injectInjectionPointBeansXML.InjectInjectionPointBeansXMLServlet;
import com.ibm.ws.cdi.api.fat.apps.injectInjectionPointParam.InjectInjectionPointAsParamServlet;
import com.ibm.ws.cdi.api.fat.apps.injectInjectionPointXML.InjectInjectionPointXMLServlet;
import com.ibm.ws.cdi.api.fat.apps.threads.extension.CDIExtension;
import com.ibm.ws.fat.util.browser.WebBrowser;
import com.ibm.ws.fat.util.browser.WebBrowserFactory;
import com.ibm.ws.fat.util.browser.WebResponse;
Expand All @@ -71,6 +74,7 @@ public class CDIAPITests extends FATServletClient {
public static final String SERVER_NAME = "cdi12APIServer";

public static final String CDI_CURRENT_APP_NAME = "cdiCurrentTest";
public static final String CDI_CURRENT_THREADS_APP_NAME = "cdiCurrentThreadsTest";
public static final String ALTERABLE_CONTEXT_APP_NAME = "alterableContextsApp";
public static final String CONVERSATION_FILTER_APP_NAME = "appConversationFilter";
public static final String INJECT_IP_AS_PARAM_APP_NAME = "injectInjectionPointAsParam";
Expand Down Expand Up @@ -174,6 +178,34 @@ public void testConversationFilter() throws Exception {
assertEquals("Wrong status", Boolean.FALSE.toString(), status);
}

@Test
@Mode(TestMode.FULL)
public void testCDICurrentInUnmanagedThreads() throws Exception {

List<String> messages = new ArrayList<String>();
messages.add("found beanmanager in ProcessAnnotatedType : true");
messages.add("found beanmanager in BeforeBeanDiscovery : true");
messages.add("found beanmanager in ProcessInjectionTarget : true");
messages.add("found beanmanager in ProcessBeanAttributes : true");
messages.add("found beanmanager in ProcessBean : true");
messages.add("found beanmanager in ProcessManagedBean : true");
messages.add("found beanmanager in ProcessInjectionPoint : true");
messages.add("found beanmanager in AfterTypeDiscovery : true");
messages.add("found beanmanager in AfterBeanDiscovery : true");
messages.add("found beanmanager in AfterDeploymentValidation : true");

server.setMarkToEndOfLog();

WebArchive cdiCurrentTheads = ShrinkWrap.create(WebArchive.class, CDI_CURRENT_THREADS_APP_NAME + ".war")
.addPackage(CDIExtension.class.getPackage());
CDIArchiveHelper.addCDIExtensionFile(cdiCurrentTheads, CDIExtension.class.getPackage());
ShrinkHelper.exportDropinAppToServer(server, cdiCurrentTheads, DeployOptions.SERVER_ONLY);
server.waitForStringsInLogUsingMark(messages);

server.getApplicationMBean(CDI_CURRENT_THREADS_APP_NAME).stop();
server.removeInstalledAppForValidation(CDI_CURRENT_THREADS_APP_NAME);
}

@Test
@Mode(TestMode.FULL)
@ExpectedFFDC(DEFINITION_EXCEPTION)
Expand Down

0 comments on commit 12eca61

Please sign in to comment.