NIFI-12434 Upgraded Registry to Spring Framework 6.1.1

- Upgraded Spring Framework from 6.0.13 to 6.1.1
- Upgraded Spring Boot from 3.1.5 to 3.2.0
- Upgraded Spring Security from 6.1.5 to 6.2.0
- Upgraded Jetty from 11.0.18 to 12.0.3
- Upgraded Servlet API from 5.0.0 to 6.0.0
- Adjusted Registry Database Tests to streamline DataSource configuration

Signed-off-by: Pierre Villard <pierre.villard.fr@gmail.com>

This closes #8087.
This commit is contained in:
exceptionfactory 2023-11-29 14:23:53 -06:00 committed by Pierre Villard
parent f0fa38dc15
commit 429b521cb9
No known key found for this signature in database
GPG Key ID: F92A93B30C07C6D5
21 changed files with 85 additions and 527 deletions

View File

@ -22,6 +22,7 @@ import org.apache.nifi.registry.properties.NiFiRegistryProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -33,6 +34,7 @@ import javax.sql.DataSource;
* Overriding Spring Boot's normal automatic creation of a DataSource in order to use the properties
* from NiFiRegistryProperties rather than the standard application.properties/yaml.
*/
@ConditionalOnProperty("nifi.registry.db.url")
@Configuration
public class DataSourceFactory {

View File

@ -16,16 +16,13 @@
*/
package org.apache.nifi.registry.db;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import org.springframework.transaction.annotation.Transactional;
@Transactional
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = DatabaseTestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})
public abstract class DatabaseBaseTest {

View File

@ -21,8 +21,6 @@ import org.mockito.Mockito;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
/**
* Sets up the application context for database repository tests.
@ -33,12 +31,6 @@ import org.springframework.context.annotation.FilterType;
* The DataSourceFactory is excluded so that Spring Boot will load an in-memory H2 database.
*/
@SpringBootApplication
@ComponentScan(
excludeFilters = {
@ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
value = DataSourceFactory.class)
})
public class DatabaseTestApplication {
public static void main(String[] args) {

View File

@ -32,6 +32,12 @@
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-jetty-configuration</artifactId>
<version>2.0.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-server</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
@ -45,7 +51,7 @@
</dependency>
<dependency>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-server</artifactId>
<artifactId>jetty-http2-server</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
@ -56,28 +62,28 @@
<artifactId>jetty-server</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-servlet</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-webapp</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlets</artifactId>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-servlets</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>apache-jsp</artifactId>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-apache-jsp</artifactId>
<scope>compile</scope>
</dependency>
<dependency>

View File

@ -26,7 +26,6 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.webapp.WebAppContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -39,7 +38,6 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@ -114,19 +112,6 @@ public class JettyServer {
public void start() {
try {
server.start();
final Optional<Throwable> unavailableExceptionFound = Arrays.stream(server.getChildHandlers())
.filter(handler -> handler instanceof WebAppContext)
.map(handler -> (WebAppContext) handler)
.map(WebAppContext::getUnavailableException)
.filter(Objects::nonNull)
.findFirst();
if (unavailableExceptionFound.isPresent()) {
final Throwable unavailableException = unavailableExceptionFound.get();
shutdown(unavailableException);
}
final List<URI> applicationUrls = getApplicationUrls();
if (applicationUrls.isEmpty()) {
logger.warn("Started Server without connectors");

View File

@ -17,15 +17,15 @@
package org.apache.nifi.registry.jetty.handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.ScopedHandler;
import org.eclipse.jetty.server.Handler;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.util.Callback;
/**
* HTTP Response Header Writer Handler applies standard headers to HTTP responses
*/
public class HeaderWriterHandler extends ScopedHandler {
public class HeaderWriterHandler extends Handler.Wrapper {
protected static final String CONTENT_SECURITY_POLICY_HEADER = "Content-Security-Policy";
protected static final String CONTENT_SECURITY_POLICY = "frame-ancestors 'self'";
@ -41,19 +41,22 @@ public class HeaderWriterHandler extends ScopedHandler {
/**
* Handle requests and set HTTP response headers
*
* @param target Target URI
* @param request Jetty Request
* @param httpServletRequest HTTP Servlet Request
* @param httpServletResponse HTTP Servlet Response
* @param response Jetty Response
* @param callback Jetty Callback
* @return Handled status
* @throws Exception Thrown on failures from subsequent handlers
*/
@Override
public void doHandle(final String target, final Request request, final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse) {
httpServletResponse.setHeader(CONTENT_SECURITY_POLICY_HEADER, CONTENT_SECURITY_POLICY);
httpServletResponse.setHeader(FRAME_OPTIONS_HEADER, FRAME_OPTIONS);
httpServletResponse.setHeader(XSS_PROTECTION_HEADER, XSS_PROTECTION);
public boolean handle(final Request request, final Response response, final Callback callback) throws Exception {
response.getHeaders().add(CONTENT_SECURITY_POLICY_HEADER, CONTENT_SECURITY_POLICY);
response.getHeaders().add(FRAME_OPTIONS_HEADER, FRAME_OPTIONS);
response.getHeaders().add(XSS_PROTECTION_HEADER, XSS_PROTECTION);
if (httpServletRequest.isSecure()) {
httpServletResponse.setHeader(STRICT_TRANSPORT_SECURITY_HEADER, STRICT_TRANSPORT_SECURITY);
if (request.isSecure()) {
response.getHeaders().add(STRICT_TRANSPORT_SECURITY_HEADER, STRICT_TRANSPORT_SECURITY);
}
return super.handle(request, response, callback);
}
}

View File

@ -20,12 +20,12 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.registry.properties.NiFiRegistryProperties;
import org.apache.nifi.registry.security.crypto.CryptoKeyProvider;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.webapp.WebAppClassLoader;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.ee10.servlet.DefaultServlet;
import org.eclipse.jetty.ee10.servlet.ErrorPageErrorHandler;
import org.eclipse.jetty.ee10.servlet.ServletHolder;
import org.eclipse.jetty.ee10.webapp.WebAppClassLoader;
import org.eclipse.jetty.ee10.webapp.WebAppContext;
import java.io.File;
import java.io.IOException;
@ -101,7 +101,7 @@ public class StandardHandlerProvider implements HandlerProvider {
final File libDirectory = properties.getWarLibDirectory();
final File workDirectory = properties.getWebWorkingDirectory();
final HandlerCollection handlers = new HandlerCollection();
final Handler.Collection handlers = new ContextHandlerCollection();
// Add Header Writer Handler before others
handlers.addHandler(new HeaderWriterHandler());
@ -158,12 +158,8 @@ public class StandardHandlerProvider implements HandlerProvider {
final File tempDirectory = getTempDirectory(workDirectory, applicationFile.getName());
webAppContext.setTempDirectory(tempDirectory);
try {
final WebAppClassLoader webAppClassLoader = new WebAppClassLoader(parentClassLoader, webAppContext);
webAppContext.setClassLoader(webAppClassLoader);
} catch (final IOException e) {
throw new IllegalStateException(String.format("Application Context Path [%s] ClassLoader creation failed", contextPath), e);
}
final WebAppClassLoader webAppClassLoader = new WebAppClassLoader(parentClassLoader, webAppContext);
webAppContext.setClassLoader(webAppClassLoader);
return webAppContext;
}

View File

@ -42,34 +42,6 @@
Default web.xml file.
This file is applied to a Web application before it's own WEB_INF/web.xml file
</description>
<!-- ==================================================================== -->
<!-- Removes static cache of Methods from java.beans.Introspector to -->
<!-- ensure webapp classloader can be released on undeploy -->
<!-- ==================================================================== -->
<listener>
<listener-class>org.eclipse.jetty.servlet.listener.IntrospectorCleaner</listener-class>
</listener>
<!-- ==================================================================== -->
<!-- Context params to control Session Cookies -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!--
UNCOMMENT TO ACTIVATE
<context-param>
<param-name>org.eclipse.jetty.servlet.SessionDomain</param-name>
<param-value>127.0.0.1</param-value>
</context-param>
<context-param>
<param-name>org.eclipse.jetty.servlet.SessionPath</param-name>
<param-value>/</param-value>
</context-param>
<context-param>
<param-name>org.eclipse.jetty.servlet.MaxAge</param-name>
<param-value>-1</param-value>
</context-param>
-->
<!-- ==================================================================== -->
<!-- The default servlet. -->
@ -139,7 +111,7 @@
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
<servlet-class>org.eclipse.jetty.ee10.servlet.DefaultServlet</servlet-class>
<init-param>
<param-name>aliases</param-name>
<param-value>false</param-value>
@ -184,18 +156,6 @@
<param-name>useFileMappedBuffer</param-name>
<param-value>true</param-value>
</init-param>
<!--
<init-param>
<param-name>resourceCache</param-name>
<param-value>resourceCache</param-value>
</init-param>
-->
<!--
<init-param>
<param-name>cacheControl</param-name>
<param-value>max-age=3600,public</param-value>
</init-param>
-->
<load-on-startup>0</load-on-startup>
</servlet>

View File

@ -1,76 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.registry.jetty.handler;
import org.eclipse.jetty.server.Request;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class HeaderWriterHandlerTest {
private static final String TARGET = HeaderWriterHandler.class.getSimpleName();
@Mock
private Request request;
@Mock
private HttpServletRequest httpServletRequest;
@Mock
private HttpServletResponse httpServletResponse;
private HeaderWriterHandler handler;
@BeforeEach
void setHandler() {
handler = new HeaderWriterHandler();
}
@Test
void testDoHandle() {
handler.doHandle(TARGET, request, httpServletRequest, httpServletResponse);
verifyStandardHeaders();
}
@Test
void testDoHandleSecure() {
when(httpServletRequest.isSecure()).thenReturn(true);
handler.doHandle(TARGET, request, httpServletRequest, httpServletResponse);
verifyStandardHeaders();
verify(httpServletResponse).setHeader(eq(HeaderWriterHandler.STRICT_TRANSPORT_SECURITY_HEADER), any());
}
private void verifyStandardHeaders() {
verify(httpServletResponse).setHeader(eq(HeaderWriterHandler.CONTENT_SECURITY_POLICY_HEADER), any());
verify(httpServletResponse).setHeader(eq(HeaderWriterHandler.FRAME_OPTIONS_HEADER), any());
verify(httpServletResponse).setHeader(eq(HeaderWriterHandler.XSS_PROTECTION_HEADER), any());
}
}

View File

@ -1,37 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.registry.db;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.testcontainers.containers.MariaDBContainer;
@Configuration
@Profile("mariadb-10")
public class MariaDB10DataSourceFactory extends MariaDBDataSourceFactory {
private static final MariaDBContainer MARIA_DB_CONTAINER = new MariaDBCustomContainer("mariadb:10.0");
static {
MARIA_DB_CONTAINER.start();
}
@Override
protected MariaDBContainer mariaDBContainer() {
return MARIA_DB_CONTAINER;
}
}

View File

@ -1,37 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.registry.db;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.testcontainers.containers.MariaDBContainer;
@Configuration
@Profile("mariadb-10-2")
public class MariaDB10_2DataSourceFactory extends MariaDBDataSourceFactory {
private static final MariaDBContainer MARIA_DB_CONTAINER = new MariaDBCustomContainer("mariadb:10.2");
static {
MARIA_DB_CONTAINER.start();
}
@Override
protected MariaDBContainer mariaDBContainer() {
return MARIA_DB_CONTAINER;
}
}

View File

@ -400,16 +400,6 @@
<artifactId>spring-boot-starter-jetty</artifactId>
<version>${spring.boot.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-server</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>javax-websocket-server-impl</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.unboundid</groupId>

View File

@ -19,6 +19,7 @@ package org.apache.nifi.registry;
import org.apache.nifi.registry.properties.NiFiRegistryProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.web.context.ServletContextAware;
import jakarta.servlet.ServletContext;
@ -28,6 +29,7 @@ import jakarta.servlet.ServletContext;
* obtains that instance and makes it available to inject to all other places.
*
*/
@Profile("default")
@Configuration
public class NiFiRegistryPropertiesFactory implements ServletContextAware {

View File

@ -98,7 +98,7 @@ public class ResourceAuthorizationFilter extends GenericFilterBean {
final HttpMethodAuthorizationRules authorizationRules = resourceTypeAuthorizationRules.get(resourceType);
if (authorizationRules != null) {
final String httpMethodStr = httpServletRequest.getMethod().toUpperCase();
HttpMethod httpMethod = HttpMethod.resolve(httpMethodStr);
HttpMethod httpMethod = HttpMethod.valueOf(httpMethodStr);
// Only require authorization for HTTP methods included in this resource type's rule set
if (httpMethod != null && authorizationRules.requiresAuthorization(httpMethod)) {

View File

@ -16,7 +16,6 @@
*/
package org.apache.nifi.registry;
import org.apache.nifi.registry.db.DataSourceFactory;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
@ -30,12 +29,6 @@ import java.util.TimeZone;
@ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
value = SpringBootServletInitializer.class), // Avoid loading NiFiRegistryApiApplication
@ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
value = DataSourceFactory.class), // Avoid loading DataSourceFactory
@ComponentScan.Filter(
type = FilterType.REGEX,
pattern = "org\\.apache\\.nifi\\.registry\\.NiFiRegistryPropertiesFactory"), // Avoid loading NiFiRegistryPropertiesFactory
})
public class NiFiRegistryTestApiApplication extends SpringBootServletInitializer {

View File

@ -16,7 +16,6 @@
*/
package org.apache.nifi.registry;
import org.apache.nifi.registry.db.DataSourceFactory;
import org.apache.nifi.registry.security.authorization.AuthorizerFactory;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@ -30,15 +29,9 @@ import org.springframework.context.annotation.FilterType;
@ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
value = SpringBootServletInitializer.class), // Avoid loading NiFiRegistryApiApplication
@ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
value = DataSourceFactory.class), // Avoid loading DataSourceFactory
@ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
value = AuthorizerFactory.class), // Avoid loading AuthorizerFactory.getAuthorizer(), as we need to add it again with test-specific @DependsOn annotation
@ComponentScan.Filter(
type = FilterType.REGEX,
pattern = "org\\.apache\\.nifi\\.registry\\.NiFiRegistryPropertiesFactory"), // Avoid loading NiFiRegistryPropertiesFactory
})
public class SecureLdapTestApiApplication extends SpringBootServletInitializer {

View File

@ -1,173 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.registry.web;
import org.apache.nifi.registry.bucket.Bucket;
import org.apache.nifi.registry.flow.VersionedFlow;
import org.apache.nifi.registry.flow.VersionedFlowSnapshot;
import org.apache.nifi.registry.flow.VersionedFlowSnapshotMetadata;
import org.apache.nifi.flow.VersionedProcessGroup;
import org.apache.nifi.registry.revision.entity.RevisionInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.Entity;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.List;
public class TestRestAPI {
public static final Logger LOGGER = LoggerFactory.getLogger(TestRestAPI.class);
public static final String REGISTRY_API_URL = "http://localhost:18080/nifi-registry-api";
public static final String REGISTRY_API_BUCKETS_URL = REGISTRY_API_URL + "/buckets";
public static final String REGISTRY_API_FLOWS_URL = REGISTRY_API_URL + "/flows";
public static void main(String[] args) {
try {
final Client client = ClientBuilder.newClient();
// create some buckets
final int numBuckets = 20;
final List<Bucket> createdBuckets = new ArrayList<>();
for (int i=0; i < numBuckets; i++) {
final Bucket createdBucket = createBucket(client, i);
System.out.println("Created bucket # " + i + " with id " + createdBucket.getIdentifier());
createdBuckets.add(createdBucket);
}
// create some flows
final int numFlowsPerBucket = 10;
final List<VersionedFlow> allFlows = new ArrayList<>();
for (final Bucket bucket : createdBuckets) {
final List<VersionedFlow> createdFlows = createFlows(client, bucket, numFlowsPerBucket);
allFlows.addAll(createdFlows);
}
// create some snapshots
final int numSnapshotsPerFlow = 10;
for (final VersionedFlow flow : allFlows) {
createSnapshots(client, flow, numSnapshotsPerFlow);
}
// Retrieve the flow by id
// final Response flowResponse = client.target(REGISTRY_API_FLOWS_URL)
// .path("/{flowId}")
// .resolveTemplate("flowId", createdFlow.getIdentifier())
// .request()
// .get();
//
// final String flowJson = flowResponse.readEntity(String.class);
// System.out.println("Flow: " + flowJson);
} catch (WebApplicationException e) {
LOGGER.error(e.getMessage(), e);
final Response response = e.getResponse();
LOGGER.error(response.readEntity(String.class));
}
}
private static Bucket createBucket(Client client, int num) {
final Bucket bucket = new Bucket();
bucket.setName("Bucket #" + num);
bucket.setDescription("This is bucket #" + num);
bucket.setRevision(new RevisionInfo("clientId", 0L));
final Bucket createdBucket = client.target(REGISTRY_API_BUCKETS_URL)
.request()
.post(
Entity.entity(bucket, MediaType.APPLICATION_JSON),
Bucket.class
);
return createdBucket;
}
private static VersionedFlow createFlow(Client client, Bucket bucket, int num) {
final VersionedFlow versionedFlow = new VersionedFlow();
versionedFlow.setName(bucket.getName() + " Flow #" + num);
versionedFlow.setDescription("This is " + bucket.getName() + " flow #" + num);
versionedFlow.setRevision(new RevisionInfo("clientId", 0L));
final VersionedFlow createdFlow = client.target(REGISTRY_API_BUCKETS_URL)
.path("/{bucketId}/flows")
.resolveTemplate("bucketId", bucket.getIdentifier())
.request()
.post(
Entity.entity(versionedFlow, MediaType.APPLICATION_JSON),
VersionedFlow.class
);
return createdFlow;
}
private static List<VersionedFlow> createFlows(Client client, Bucket bucket, int numFlows) {
final List<VersionedFlow> createdFlows = new ArrayList<>();
for (int i=0; i < numFlows; i++) {
final VersionedFlow createdFlow = createFlow(client, bucket, i);
System.out.println("Created flow # " + i + " with id " + createdFlow.getIdentifier());
createdFlows.add(createdFlow);
}
return createdFlows;
}
private static VersionedFlowSnapshot createSnapshot(Client client, VersionedFlow flow, int num) {
final VersionedFlowSnapshotMetadata snapshotMetadata1 = new VersionedFlowSnapshotMetadata();
snapshotMetadata1.setBucketIdentifier(flow.getBucketIdentifier());
snapshotMetadata1.setFlowIdentifier(flow.getIdentifier());
snapshotMetadata1.setVersion(num);
snapshotMetadata1.setComments("This is snapshot #" + num);
final VersionedProcessGroup snapshotContents1 = new VersionedProcessGroup();
snapshotContents1.setIdentifier("pg1");
snapshotContents1.setName("Process Group 1");
final VersionedFlowSnapshot snapshot1 = new VersionedFlowSnapshot();
snapshot1.setSnapshotMetadata(snapshotMetadata1);
snapshot1.setFlowContents(snapshotContents1);
final VersionedFlowSnapshot createdSnapshot = client.target(REGISTRY_API_BUCKETS_URL)
.path("{bucketId}/flows/{flowId}/versions")
.resolveTemplate("bucketId", flow.getBucketIdentifier())
.resolveTemplate("flowId", flow.getIdentifier())
.request()
.post(
Entity.entity(snapshot1, MediaType.APPLICATION_JSON_TYPE),
VersionedFlowSnapshot.class
);
return createdSnapshot;
}
private static void createSnapshots(Client client, VersionedFlow flow, int numSnapshots) {
for (int i=1; i <= numSnapshots; i++) {
createSnapshot(client, flow, i);
System.out.println("Created snapshot # " + i + " for flow with id " + flow.getIdentifier());
}
}
}

View File

@ -57,28 +57,33 @@
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>jetty-http2-server</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-servlet</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlets</artifactId>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-webapp</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-servlets</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>apache-jsp</artifactId>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-annotations</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-apache-jsp</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
@ -137,19 +142,6 @@
</systemPropertyVariables>
</configuration>
</execution>
<execution>
<id>mariadb-10_2-test</id>
<phase>verify</phase>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<systemPropertyVariables>
<spring.profiles.active>mariadb-10-2</spring.profiles.active>
</systemPropertyVariables>
</configuration>
</execution>
<execution>
<id>mariadb-10_3-test</id>
<phase>verify</phase>

View File

@ -247,6 +247,23 @@
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</exclusion>
<!-- Exclude Jetty Server -->
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>

View File

@ -32,22 +32,6 @@
<dependencyManagement>
<dependencies>
<!-- Override jetty-server:9.4.20 -->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${jetty.version}</version>
</dependency>
<!-- Override SolrJ 8.6.3 from Ranger -->
<dependency>
<groupId>org.apache.solr</groupId>

View File

@ -37,11 +37,11 @@
<properties>
<jakarta.rs.api.version>3.1.0</jakarta.rs.api.version>
<jersey.bom.version>3.1.3</jersey.bom.version>
<spring.boot.version>3.1.5</spring.boot.version>
<spring.version>6.0.13</spring.version>
<spring.security.version>6.1.5</spring.security.version>
<servlet-api.version>5.0.0</servlet-api.version>
<jetty.version>11.0.18</jetty.version>
<spring.boot.version>3.2.0</spring.boot.version>
<spring.version>6.1.1</spring.version>
<spring.security.version>6.2.0</spring.security.version>
<servlet-api.version>6.0.0</servlet-api.version>
<jetty.version>12.0.3</jetty.version>
<flyway.version>9.22.3</flyway.version>
<flyway.tests.version>9.5.0</flyway.tests.version>
<swagger.ui.version>3.12.0</swagger.ui.version>
@ -68,37 +68,6 @@
<artifactId>jetty-server</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlets</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>apache-jsp</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-server</artifactId>
<version>${jetty.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-server</artifactId>