Skip to content

Commit 97e0229

Browse files
fix(XServiceProvider): fix ebean framework race condition (datahub-project#11378)
1 parent d82e478 commit 97e0229

File tree

9 files changed

+45
-19
lines changed

9 files changed

+45
-19
lines changed

.github/workflows/docker-unified.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,7 @@ jobs:
990990
DATAHUB_VERSION: ${{ needs.setup.outputs.unique_tag }}
991991
DATAHUB_ACTIONS_IMAGE: ${{ env.DATAHUB_INGESTION_IMAGE }}
992992
ACTIONS_VERSION: ${{ needs.datahub_ingestion_slim_build.outputs.tag || 'head-slim' }}
993-
ACTIONS_EXTRA_PACKAGES: "acryl-datahub-actions[executor]==0.0.13 acryl-datahub-actions==0.0.13 acryl-datahub==0.10.5"
993+
ACTIONS_EXTRA_PACKAGES: "acryl-datahub-actions[executor] acryl-datahub-actions"
994994
ACTIONS_CONFIG: "https://raw.githubusercontent.com/acryldata/datahub-actions/main/docker/config/executor.yaml"
995995
run: |
996996
./smoke-test/run-quickstart.sh

docker/datahub-ingestion-base/Dockerfile

+2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ RUN apt-get update && apt-get upgrade -y \
4343
krb5-user \
4444
krb5-config \
4545
libkrb5-dev \
46+
librdkafka-dev \
4647
wget \
48+
curl \
4749
zip \
4850
unzip \
4951
ldap-utils \

metadata-jobs/mce-consumer-job/src/main/java/com/linkedin/metadata/restli/RestliServletConfig.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.datahub.auth.authentication.filter.AuthenticationFilter;
44
import com.linkedin.gms.factory.auth.SystemAuthenticationFactory;
5+
import com.linkedin.r2.transport.http.server.RAPJakartaServlet;
56
import com.linkedin.restli.server.RestliHandlerServlet;
67
import java.util.Collections;
78
import org.springframework.beans.factory.annotation.Qualifier;
@@ -36,8 +37,8 @@ public ServletRegistrationBean<RestliHandlerServlet> restliServletRegistration(
3637
}
3738

3839
@Bean("restliHandlerServlet")
39-
public RestliHandlerServlet restliHandlerServlet() {
40-
return new RestliHandlerServlet();
40+
public RestliHandlerServlet restliHandlerServlet(final RAPJakartaServlet r2Servlet) {
41+
return new RestliHandlerServlet(r2Servlet);
4142
}
4243

4344
@Bean

metadata-service/auth-filter/src/main/java/com/datahub/auth/authentication/filter/AuthenticationFilter.java

+1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ public class AuthenticationFilter implements Filter {
7777
public void init(FilterConfig filterConfig) throws ServletException {
7878
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
7979
buildAuthenticatorChain();
80+
log.info("AuthenticationFilter initialized.");
8081
}
8182

8283
@Override

metadata-service/factories/src/main/java/com/linkedin/metadata/boot/OnBootApplicationListener.java

+11
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,17 @@ public void onApplicationEvent(@Nonnull ContextRefreshedEvent event) {
7373
event);
7474
String schemaRegistryType = provider.getKafka().getSchemaRegistry().getType();
7575
if (ROOT_WEB_APPLICATION_CONTEXT_ID.equals(event.getApplicationContext().getId())) {
76+
77+
// Handle race condition, if ebean code is executed while waiting/bootstrapping (i.e.
78+
// AuthenticationFilter)
79+
try {
80+
Class.forName("io.ebean.XServiceProvider");
81+
} catch (ClassNotFoundException e) {
82+
log.error(
83+
"Failure to initialize required class `io.ebean.XServiceProvider` during initialization.");
84+
throw new RuntimeException(e);
85+
}
86+
7687
if (InternalSchemaRegistryFactory.TYPE.equals(schemaRegistryType)) {
7788
executorService.submit(isSchemaRegistryAPIServletReady());
7889
} else {

metadata-service/factories/src/main/java/com/linkedin/restli/server/RAPServletFactory.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import lombok.extern.slf4j.Slf4j;
1717
import org.springframework.beans.factory.annotation.Qualifier;
1818
import org.springframework.beans.factory.annotation.Value;
19+
import org.springframework.context.ApplicationContext;
1920
import org.springframework.context.annotation.Bean;
2021
import org.springframework.context.annotation.Configuration;
2122

@@ -29,8 +30,10 @@ public class RAPServletFactory {
2930
private int maxSerializedStringLength;
3031

3132
@Bean(name = "restliSpringInjectResourceFactory")
32-
public SpringInjectResourceFactory springInjectResourceFactory() {
33-
return new SpringInjectResourceFactory();
33+
public SpringInjectResourceFactory springInjectResourceFactory(final ApplicationContext ctx) {
34+
SpringInjectResourceFactory springInjectResourceFactory = new SpringInjectResourceFactory();
35+
springInjectResourceFactory.setApplicationContext(ctx);
36+
return springInjectResourceFactory;
3437
}
3538

3639
@Bean("parseqEngineThreads")

metadata-service/factories/src/main/java/com/linkedin/restli/server/RestliHandlerServlet.java

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
11
package com.linkedin.restli.server;
22

33
import com.linkedin.r2.transport.http.server.RAPJakartaServlet;
4+
import jakarta.servlet.ServletConfig;
45
import jakarta.servlet.ServletException;
56
import jakarta.servlet.http.HttpServletRequest;
67
import jakarta.servlet.http.HttpServletResponse;
78
import java.io.IOException;
89
import lombok.AllArgsConstructor;
9-
import lombok.NoArgsConstructor;
10+
import lombok.extern.slf4j.Slf4j;
1011
import org.springframework.beans.factory.annotation.Autowired;
11-
import org.springframework.stereotype.Component;
1212
import org.springframework.web.HttpRequestHandler;
1313
import org.springframework.web.context.support.HttpRequestHandlerServlet;
1414

15+
@Slf4j
1516
@AllArgsConstructor
16-
@NoArgsConstructor
17-
@Component
1817
public class RestliHandlerServlet extends HttpRequestHandlerServlet implements HttpRequestHandler {
1918
@Autowired private RAPJakartaServlet _r2Servlet;
2019

20+
@Override
21+
public void init(ServletConfig config) throws ServletException {
22+
log.info("Initializing RestliHandlerServlet");
23+
this._r2Servlet.init(config);
24+
log.info("Initialized RestliHandlerServlet");
25+
}
26+
2127
@Override
2228
public void service(HttpServletRequest req, HttpServletResponse res)
2329
throws ServletException, IOException {

metadata-service/war/src/main/java/com/linkedin/gms/WebApplicationInitializer.java

+10-8
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,13 @@ public void onStartup(ServletContext container) {
4242
// Independent dispatcher
4343
schemaRegistryServlet(container);
4444

45-
// Non-Spring servlets
46-
healthCheckServlet(container);
47-
configServlet(container);
48-
49-
// Restli non-Dispatcher
50-
servletNames.add(restliServlet(rootContext, container));
51-
5245
// Spring Dispatcher servlets
5346
DispatcherServlet dispatcherServlet = new DispatcherServlet(rootContext);
5447
servletNames.add(authServlet(rootContext, dispatcherServlet, container));
5548
servletNames.add(graphQLServlet(rootContext, dispatcherServlet, container));
5649
servletNames.add(openAPIServlet(rootContext, dispatcherServlet, container));
50+
// Restli non-Dispatcher default
51+
servletNames.add(restliServlet(rootContext, container));
5752

5853
FilterRegistration.Dynamic filterRegistration =
5954
container.addFilter("authenticationFilter", AuthenticationFilter.class);
@@ -62,6 +57,10 @@ public void onStartup(ServletContext container) {
6257
EnumSet.of(DispatcherType.ASYNC, DispatcherType.REQUEST),
6358
false,
6459
servletNames.toArray(String[]::new));
60+
61+
// Non-Spring servlets
62+
healthCheckServlet(container);
63+
configServlet(container);
6564
}
6665

6766
/*
@@ -133,10 +132,13 @@ private String restliServlet(
133132
rootContext.register(RestliServletConfig.class);
134133

135134
ServletRegistration.Dynamic registration =
136-
container.addServlet(servletName, new HttpRequestHandlerServlet());
135+
container.addServlet(servletName, HttpRequestHandlerServlet.class);
137136
registration.addMapping("/*");
138137
registration.setLoadOnStartup(10);
139138
registration.setAsyncSupported(true);
139+
registration.setInitParameter(
140+
"org.springframework.web.servlet.FrameworkServlet.ORDER",
141+
String.valueOf(Integer.MAX_VALUE - 1));
140142

141143
return servletName;
142144
}

metadata-service/war/src/main/java/com/linkedin/gms/servlet/RestliServletConfig.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
import org.springframework.context.annotation.ComponentScan;
88
import org.springframework.context.annotation.Configuration;
99
import org.springframework.context.annotation.PropertySource;
10-
import org.springframework.web.HttpRequestHandler;
10+
import org.springframework.web.context.support.HttpRequestHandlerServlet;
1111

1212
@ComponentScan(basePackages = {"com.linkedin.restli.server"})
1313
@PropertySource(value = "classpath:/application.yaml", factory = YamlPropertySourceFactory.class)
1414
@Configuration
1515
public class RestliServletConfig {
1616
@Bean("restliRequestHandler")
17-
public HttpRequestHandler restliHandlerServlet(final RAPJakartaServlet r2Servlet) {
17+
public HttpRequestHandlerServlet restliHandlerServlet(final RAPJakartaServlet r2Servlet) {
1818
return new RestliHandlerServlet(r2Servlet);
1919
}
2020
}

0 commit comments

Comments
 (0)