Skip to content

Commit

Permalink
fix(CDI) Auto-detect beans on Rest services Refs: #30187 (#30417)
Browse files Browse the repository at this point in the history
### Proposed Changes
* Jersey 2.28 works with CDI1.x 
* beans.xml were downgraded to use CDI 1.x
* A Few "Producer" classes were removed as they were generating
conflicts trying to decide what implementation had to be chosen
* Updated the Resources where there were previous attempts to introduce
injection
* Some classes were located in different projects but had identical
names like GenericBundleActivatorTest Weld didn't like that so I had to
rename one of them.
* CDI Utils has a new method that throws an exception as some people
complained about the one returning an Optional
* We have support for Integration tests through these two runners
(JUnit4WeldRunner,DataProviderWeldRunner)
* If we want to use CDI2.x we will have to wait until we move to tomcat
10+
  • Loading branch information
fabrizzio-dotCMS authored Oct 29, 2024
1 parent d4bbe1d commit fe2a36c
Show file tree
Hide file tree
Showing 36 changed files with 338 additions and 235 deletions.
13 changes: 13 additions & 0 deletions bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1154,6 +1154,19 @@
<version>3.1.9.Final</version>
</dependency>

<dependency>
<groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-cdi1x</artifactId>
<version>${jersey.version}</version>
</dependency>

<dependency>
<groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-cdi1x-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>


<dependency>
<groupId>org.glassfish.hk2.external</groupId>
<artifactId>bean-validator</artifactId>
Expand Down
12 changes: 11 additions & 1 deletion dotCMS/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1405,6 +1405,17 @@
<version>3.1.9.Final</version>
</dependency>

<dependency>
<groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-cdi1x</artifactId>
</dependency>

<!-- This is required keep one single instance of the InjectionManager across all ServletContexts -->
<dependency>
<groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-cdi1x-servlet</artifactId>
</dependency>

<dependency>
<groupId>org.glassfish.hk2.external</groupId>
<artifactId>bean-validator</artifactId>
Expand All @@ -1429,7 +1440,6 @@
<artifactId>jandex</artifactId>
<version>3.0.5</version>
</dependency>

<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,11 @@ public AnalyticsTool() {
}

private static ContentAnalyticsAPI getContentAnalyticsAPI() {
final Optional<ContentAnalyticsAPI> contentAnalyticsAPI = CDIUtils.getBean(ContentAnalyticsAPI.class);
if (!contentAnalyticsAPI.isPresent()) {
throw new DotRuntimeException("Could not instance ContentAnalyticsAPI");
}
return contentAnalyticsAPI.get();
return CDIUtils.getBeanThrows(ContentAnalyticsAPI.class);
}

private static AnalyticsQueryParser getAnalyticsQueryParser() {
final Optional<AnalyticsQueryParser> queryParserOptional = CDIUtils.getBean(AnalyticsQueryParser.class);
if (!queryParserOptional.isPresent()) {
throw new DotRuntimeException("Could not instance AnalyticsQueryParser");
}
return queryParserOptional.get();
return CDIUtils.getBeanThrows(AnalyticsQueryParser.class);
}

public AnalyticsTool(final ContentAnalyticsAPI contentAnalyticsAPI,
Expand Down

This file was deleted.

28 changes: 21 additions & 7 deletions dotCMS/src/main/java/com/dotcms/cdi/CDIUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,34 @@ private CDIUtils() {
}

/**
* Get a bean from CDI container
* Get a bean from CDI container and return an Optional with the bean if found, empty otherwise
* @param clazz the class of the bean
* @return an Optional with the bean if found, empty otherwise
*/
public static <T> Optional<T> getBean(Class<T> clazz) {
try {
return Optional.of(getBeanThrows(clazz));
} catch (Exception e) {
// Exception is already logged in getBeanThrows
}
return Optional.empty();
}


/**
* Get a bean from CDI container but throw an exception if the bean is not found
* @param clazz the class of the bean
* @return the bean
* @param <T> the type of the bean
*/
public static <T> T getBeanThrows(Class<T> clazz) {
try {
return Optional.of(CDI.current().select(clazz).get());
return CDI.current().select(clazz).get();
} catch (Exception e) {
Logger.error(CDIUtils.class,
String.format("Unable to find bean of class [%s] [%s]", clazz, e.getMessage())
);
String errorMessage = String.format("Unable to find bean of class [%s]: %s", clazz, e.getMessage());
Logger.error(CDIUtils.class, errorMessage);
throw new IllegalStateException(errorMessage, e);
}
return Optional.empty();
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
import com.dotmarketing.exception.DotSecurityException;
import com.google.common.annotations.VisibleForTesting;
import com.liferay.portal.model.User;
import javax.enterprise.context.ApplicationScoped;

/**
* Factory to create {@link CubeJSClient} instances.
*
* @author vico
*/
@ApplicationScoped
public class CubeJSClientFactoryImpl implements CubeJSClientFactory {

private static AnalyticsHelper analyticsHelper = AnalyticsHelper.get();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import java.util.function.Consumer;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;

/**
* Manages the processing of jobs in a distributed job queue system. This class is responsible for
Expand Down Expand Up @@ -138,7 +139,7 @@ public class JobQueueManagerAPIImpl implements JobQueueManagerAPI {
* - Initializes event handlers for various job state changes.
*/
@Inject
public JobQueueManagerAPIImpl(JobQueue jobQueue,
public JobQueueManagerAPIImpl(@Named("queueProducer") JobQueue jobQueue,
JobQueueConfig jobQueueConfig,
CircuitBreaker circuitBreaker,
RetryStrategy defaultRetryStrategy,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.dotmarketing.util.Config;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import javax.inject.Named;

/**
* This class is responsible for producing the JobQueue implementation used in the application. It
Expand All @@ -22,17 +23,16 @@ public class JobQueueProducer {
*
* @return A JobQueue instance
*/
@Named("queueProducer")
@Produces
@ApplicationScoped
public JobQueue produceJobQueue() {

if (JOB_QUEUE_IMPLEMENTATION_TYPE.equals("postgres")) {
return new PostgresJobQueue();
}

throw new IllegalStateException(
"Unknown job queue implementation type: " + JOB_QUEUE_IMPLEMENTATION_TYPE
);
throw new IllegalStateException("Unknown job queue implementation type: " + JOB_QUEUE_IMPLEMENTATION_TYPE);

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
* @see Job
* @see JobState
*/

public class PostgresJobQueue implements JobQueue {

private static final String CREATE_JOB_QUEUE_QUERY = "INSERT INTO job_queue "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@
import com.dotcms.analytics.model.ResultSetItem;
import com.dotcms.analytics.track.collectors.WebEventsCollectorServiceFactory;
import com.dotcms.analytics.track.matchers.UserCustomDefinedRequestMatcher;
import com.dotcms.cdi.CDIUtils;
import com.dotcms.rest.InitDataObject;
import com.dotcms.rest.ResponseEntityStringView;
import com.dotcms.rest.WebResource;
import com.dotcms.rest.annotation.NoCache;
import com.dotcms.util.DotPreconditions;
import com.dotmarketing.business.APILocator;
import com.dotmarketing.util.Logger;
import com.dotmarketing.util.UUIDUtil;
import com.google.common.annotations.VisibleForTesting;
Expand All @@ -21,8 +19,11 @@
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.glassfish.jersey.server.JSONP;

import java.io.Serializable;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
Expand All @@ -31,12 +32,7 @@
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import org.glassfish.jersey.server.JSONP;

/**
* Resource class that exposes endpoints to query content analytics data.
Expand All @@ -47,6 +43,7 @@
* @author Jose Castro
* @since Sep 13th, 2024
*/

@Path("/v1/analytics/content")
@Tag(name = "Content Analytics",
description = "Endpoints that exposes information related to how dotCMS content is accessed and interacted with by users.")
Expand All @@ -57,13 +54,7 @@ public class ContentAnalyticsResource {
private final WebResource webResource;
private final ContentAnalyticsAPI contentAnalyticsAPI;

@SuppressWarnings("unused")
public ContentAnalyticsResource() {
this(CDIUtils.getBean(ContentAnalyticsAPI.class).orElseGet(APILocator::getContentAnalyticsAPI));
}

//@Inject
@VisibleForTesting
@Inject
public ContentAnalyticsResource(final ContentAnalyticsAPI contentAnalyticsAPI) {
this(new WebResource(), contentAnalyticsAPI);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.dotcms.rest.api.v1.job;

import com.dotcms.cdi.CDIUtils;
import com.dotcms.jobs.business.job.Job;
import com.dotcms.jobs.business.job.JobPaginatedResult;
import com.dotcms.rest.ResponseEntityView;
Expand All @@ -14,6 +13,7 @@
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.BeanParam;
import javax.ws.rs.Consumes;
Expand All @@ -38,8 +38,9 @@ public class JobQueueResource {

private final JobQueueHelper helper;

public JobQueueResource() {
this(new WebResource(), CDIUtils.getBean(JobQueueHelper.class).orElseThrow(()->new IllegalStateException("JobQueueHelper Bean not found")));
@Inject
public JobQueueResource(final JobQueueHelper helper) {
this(new WebResource(), helper);
}

@VisibleForTesting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import org.glassfish.jersey.server.spi.Container;

/**
* A new Reloader will get created on each reload there can only be one container at a time
* A new Re-loader will get created on each reload there can only be one container at a time
*/
@Provider
@ApplicationScoped
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
import io.swagger.v3.jaxrs2.integration.resources.AcceptHeaderOpenApiResource;
import io.swagger.v3.jaxrs2.integration.resources.OpenApiResource;
import org.glassfish.jersey.ext.cdi1x.internal.CdiComponentProvider;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.servers.Server;
Expand Down Expand Up @@ -57,7 +58,7 @@ public DotRestApplication() {
"com.dotcms.rendering.js",
"com.dotcms.ai.rest",
"io.swagger.v3.jaxrs2"
);
).register(CdiComponentProvider.class);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1443,8 +1443,8 @@ Object create() {
case SYSTEM_API: return new SystemAPIImpl();
case ARTIFICIAL_INTELLIGENCE_API: return new DotAIAPIFacadeImpl();
case ACHECKER_API: return new ACheckerAPIImpl();
case CONTENT_ANALYTICS_API: CDIUtils.getBean(ContentAnalyticsAPI.class).orElseThrow(() -> new DotRuntimeException("Content Analytics API not found"));
case JOB_QUEUE_MANAGER_API: return CDIUtils.getBean(JobQueueManagerAPI.class).orElseThrow(() -> new DotRuntimeException("JobQueueManagerAPI not found"));
case CONTENT_ANALYTICS_API: return CDIUtils.getBeanThrows(ContentAnalyticsAPI.class);
case JOB_QUEUE_MANAGER_API: return CDIUtils.getBeanThrows(JobQueueManagerAPI.class);
}
throw new AssertionError("Unknown API index: " + this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ public static SystemTableFactory getSystemTableFactory() {
}

public static CubeJSClientFactory getCubeJSClientFactory() {
return (CubeJSClientFactory) getInstance(FactoryIndex.CUBEJS_CLIENT_FACTORY);
return CDIUtils.getBeanThrows(CubeJSClientFactory.class);
}

/**
Expand All @@ -289,7 +289,7 @@ public static LanguageVariableFactory getLanguageVariableFactory() {
* @return An instance of the {@link ContentAnalyticsFactory} object.
*/
public static ContentAnalyticsFactory getContentAnalyticsFactory() {
return (ContentAnalyticsFactory) getInstance(FactoryIndex.CONTENT_ANALYTICS_FACTORY);
return CDIUtils.getBeanThrows(ContentAnalyticsFactory.class);
}

/**
Expand Down Expand Up @@ -378,9 +378,7 @@ enum FactoryIndex
VARIANT_FACTORY,
EXPERIMENTS_FACTORY,
SYSTEM_TABLE_FACTORY,
CUBEJS_CLIENT_FACTORY,
LANGUAGE_VARIABLE_FACTORY,
CONTENT_ANALYTICS_FACTORY,
PORTLET_FACTORY;

Object create() {
Expand Down Expand Up @@ -423,9 +421,7 @@ Object create() {
case VARIANT_FACTORY : return new VariantFactoryImpl();
case EXPERIMENTS_FACTORY: return new ExperimentsFactoryImpl();
case SYSTEM_TABLE_FACTORY: return new SystemTableFactoryImpl();
case CUBEJS_CLIENT_FACTORY: return new CubeJSClientFactoryImpl();
case LANGUAGE_VARIABLE_FACTORY: return new LanguageVariableFactoryImpl();
case CONTENT_ANALYTICS_FACTORY: CDIUtils.getBean(ContentAnalyticsFactory.class).orElseThrow(() -> new DotRuntimeException("ContentAnalyticsFactory not found"));
case PORTLET_FACTORY: return new PortletFactoryImpl();
}
throw new AssertionError("Unknown Factory Index: " + this);
Expand Down
8 changes: 8 additions & 0 deletions dotCMS/src/main/resources/META-INF/beans.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
version="2.0" bean-discovery-mode="annotated">
<scan>
<exclude name="org.apache.**"/>
</scan>
</beans>
9 changes: 0 additions & 9 deletions dotCMS/src/main/webapp/WEB-INF/beans.xml

This file was deleted.

Loading

0 comments on commit fe2a36c

Please sign in to comment.