Skip to content

Commit

Permalink
Introduce a build time optimized FastComponentNameResolver
Browse files Browse the repository at this point in the history
Fixes #892
  • Loading branch information
jamesnetherton committed Jul 29, 2021
1 parent b0688c9 commit f29161a
Show file tree
Hide file tree
Showing 12 changed files with 379 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.apache.camel.quarkus.core.CamelContextRecorder;
import org.apache.camel.quarkus.core.CamelRuntime;
import org.apache.camel.quarkus.core.deployment.main.spi.CamelMainEnabled;
import org.apache.camel.quarkus.core.deployment.spi.CamelComponentNameResolverBuildItem;
import org.apache.camel.quarkus.core.deployment.spi.CamelContextBuildItem;
import org.apache.camel.quarkus.core.deployment.spi.CamelContextCustomizerBuildItem;
import org.apache.camel.quarkus.core.deployment.spi.CamelFactoryFinderResolverBuildItem;
Expand Down Expand Up @@ -74,6 +75,7 @@ CamelContextBuildItem context(
CamelFactoryFinderResolverBuildItem factoryFinderResolver,
List<CamelContextCustomizerBuildItem> customizers,
CamelStartupStepRecorderBuildItem startupStepRecorder,
CamelComponentNameResolverBuildItem componentNameResolver,
CamelConfig config) {

RuntimeValue<CamelContext> context = recorder.createContext(
Expand All @@ -83,6 +85,7 @@ CamelContextBuildItem context(
modelDumper.getValue(),
factoryFinderResolver.getFactoryFinderResolver(),
startupStepRecorder.getValue(),
componentNameResolver.getComponentNameResolver(),
beanContainer.getValue(),
CamelSupport.getCamelVersion(),
config);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Predicate;
import java.util.stream.Collectors;

Expand All @@ -50,6 +51,11 @@
import org.apache.camel.quarkus.core.CamelProducers;
import org.apache.camel.quarkus.core.CamelRecorder;
import org.apache.camel.quarkus.core.FastFactoryFinderResolver.Builder;
import org.apache.camel.quarkus.core.deployment.catalog.BuildTimeCamelCatalog;
import org.apache.camel.quarkus.core.deployment.catalog.BuildTimeJsonSchemaResolver;
import org.apache.camel.quarkus.core.deployment.catalog.SchemaResource;
import org.apache.camel.quarkus.core.deployment.spi.BuildTimeCamelCatalogBuildItem;
import org.apache.camel.quarkus.core.deployment.spi.CamelComponentNameResolverBuildItem;
import org.apache.camel.quarkus.core.deployment.spi.CamelFactoryFinderResolverBuildItem;
import org.apache.camel.quarkus.core.deployment.spi.CamelModelJAXBContextFactoryBuildItem;
import org.apache.camel.quarkus.core.deployment.spi.CamelModelToXMLDumperBuildItem;
Expand Down Expand Up @@ -378,6 +384,21 @@ public List<CamelRoutesBuilderClassBuildItem> discoverRoutesBuilderClassNames(
.collect(Collectors.toList());
}

@Record(ExecutionTime.STATIC_INIT)
@BuildStep
CamelComponentNameResolverBuildItem componentNameResolver(
BuildTimeCamelCatalogBuildItem camelCatalog,
CamelRecorder recorder) {
BuildTimeCamelCatalog catalog = camelCatalog.getCatalog();
BuildTimeJsonSchemaResolver jSonSchemaResolver = catalog.getJSonSchemaResolver();
Set<String> componentNames = jSonSchemaResolver.getSchemaResources()
.stream()
.filter(resource -> resource.getType().equals("component"))
.map(SchemaResource::getName)
.collect(Collectors.collectingAndThen(Collectors.toUnmodifiableSet(), TreeSet::new));
return new CamelComponentNameResolverBuildItem(recorder.createComponentNameResolver(componentNames));
}

@BuildStep
NativeImageResourceBuildItem initResources() {
return new NativeImageResourceBuildItem(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* 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.camel.quarkus.core.deployment.spi;

import io.quarkus.builder.item.SimpleBuildItem;
import io.quarkus.runtime.RuntimeValue;
import org.apache.camel.spi.ComponentNameResolver;

/**
* Holds the {@link ComponentNameResolver} {@link RuntimeValue}.
*/
public final class CamelComponentNameResolverBuildItem extends SimpleBuildItem {

private final RuntimeValue<ComponentNameResolver> value;

public CamelComponentNameResolverBuildItem(RuntimeValue<ComponentNameResolver> value) {
this.value = value;
}

public RuntimeValue<ComponentNameResolver> getComponentNameResolver() {
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.catalog.RuntimeCamelCatalog;
import org.apache.camel.spi.CamelContextCustomizer;
import org.apache.camel.spi.ComponentNameResolver;
import org.apache.camel.spi.FactoryFinderResolver;
import org.apache.camel.spi.ModelJAXBContextFactory;
import org.apache.camel.spi.ModelToXMLDumper;
Expand All @@ -42,6 +43,7 @@ public RuntimeValue<CamelContext> createContext(
RuntimeValue<ModelToXMLDumper> xmlModelDumper,
RuntimeValue<FactoryFinderResolver> factoryFinderResolver,
RuntimeValue<StartupStepRecorder> startupStepRecorder,
RuntimeValue<ComponentNameResolver> componentNameResolver,
BeanContainer beanContainer,
String version,
CamelConfig config) {
Expand All @@ -63,6 +65,7 @@ public RuntimeValue<CamelContext> createContext(
context.build();
context.addLifecycleStrategy(new CamelLifecycleEventBridge());
context.getManagementStrategy().addEventNotifier(new CamelManagementEventBridge());
context.setComponentNameResolver(componentNameResolver.getValue());

// register to the container
beanContainer.instance(CamelProducers.class).setContext(context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.apache.camel.reifier.ProcessorReifier;
import org.apache.camel.reifier.validator.ValidatorReifier;
import org.apache.camel.spi.BeanProxyFactory;
import org.apache.camel.spi.ComponentNameResolver;
import org.apache.camel.spi.FactoryFinderResolver;
import org.apache.camel.spi.ModelJAXBContextFactory;
import org.apache.camel.spi.ModelToXMLDumper;
Expand Down Expand Up @@ -185,4 +186,7 @@ public Supplier<?> produceProxy(Class<?> clazz, String uri) {
};
}

public RuntimeValue<ComponentNameResolver> createComponentNameResolver(Set<String> componentNames) {
return new RuntimeValue<>(new FastComponentNameResolver(componentNames));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.apache.camel.model.ModelCamelContext;
import org.apache.camel.spi.CamelBeanPostProcessor;
import org.apache.camel.spi.ClassResolver;
import org.apache.camel.spi.ComponentNameResolver;
import org.apache.camel.spi.ComponentResolver;
import org.apache.camel.spi.DataFormat;
import org.apache.camel.spi.FactoryFinderResolver;
Expand Down Expand Up @@ -99,6 +100,12 @@ protected ComponentResolver createComponentResolver() {
return (name, context) -> context.getRegistry().lookupByNameAndType(name, Component.class);
}

@Override
protected ComponentNameResolver createComponentNameResolver() {
// Component names are discovered at build time
throw new UnsupportedOperationException();
}

@Override
protected TypeConverter createTypeConverter() {
// TypeConverter impls are resolved at build time
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* 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.camel.quarkus.core;

import java.util.Set;

import org.apache.camel.CamelContext;
import org.apache.camel.spi.ComponentNameResolver;

/**
* A fast {@link ComponentNameResolver} implementation, returning a fixed set of component names that were
* discovered at build time
*/
public class FastComponentNameResolver implements ComponentNameResolver {

private final Set<String> componentNames;

public FastComponentNameResolver(Set<String> componentNames) {
this.componentNames = componentNames;
}

@Override
public Set<String> resolveNames(CamelContext camelContext) {
return componentNames;
}
}
134 changes: 134 additions & 0 deletions integration-test-groups/foundation/component-name-resolver/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-integration-tests-foundation</artifactId>
<version>2.2.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>camel-quarkus-integration-test-component-name-resolver</artifactId>
<name>Camel Quarkus :: Integration Tests :: Component Name Resolver :: Tests</name>

<dependencies>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-direct</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-log</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-mock</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>

<!-- test dependencies -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>

<!-- The following dependencies guarantee that this module is built after them. You can update them by running `mvn process-resources -Pformat -N` from the source tree root directory -->
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-direct-deployment</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-log-deployment</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-mock-deployment</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

<profiles>
<profile>
<id>native</id>
<activation>
<property>
<name>native</name>
</property>
</activation>
<properties>
<quarkus.package.type>native</quarkus.package.type>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* 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.camel.quarkus.core.component.name.resolver;

import java.util.stream.Collectors;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.apache.camel.CamelContext;
import org.apache.camel.ExtendedCamelContext;
import org.apache.camel.spi.ComponentNameResolver;

@Path("/component-name-resolver")
public class ComponentNameResolverResource {

@Inject
CamelContext context;

@Path("/class")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String configuredComponentNameResolverClass() {
ComponentNameResolver resolver = context.getExtension(ExtendedCamelContext.class).getComponentNameResolver();
return resolver.getClass().getName();
}

@Path("/resolve")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String fastResolveComponentNames() {
ComponentNameResolver resolver = context.getExtension(ExtendedCamelContext.class).getComponentNameResolver();
return resolver.resolveNames(context)
.stream()
.collect(Collectors.joining(","));
}
}

0 comments on commit f29161a

Please sign in to comment.