org.apache.camel.impl.engine.AbstractCamelContext Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of camel-base-engine Show documentation
Show all versions of camel-base-engine Show documentation
The Base Engine Camel Framework
The newest version!
/*
* 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.impl.engine;
import java.io.IOException;
import java.io.InputStream;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.StringJoiner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Predicate;
import org.apache.camel.CamelContext;
import org.apache.camel.CamelContextAware;
import org.apache.camel.CatalogCamelContext;
import org.apache.camel.Component;
import org.apache.camel.ConsumerTemplate;
import org.apache.camel.ContextEvents;
import org.apache.camel.Endpoint;
import org.apache.camel.ExtendedCamelContext;
import org.apache.camel.FailedToStartComponentException;
import org.apache.camel.FluentProducerTemplate;
import org.apache.camel.GlobalEndpointConfiguration;
import org.apache.camel.LoggingLevel;
import org.apache.camel.NoSuchEndpointException;
import org.apache.camel.Processor;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.ResolveEndpointFailedException;
import org.apache.camel.Route;
import org.apache.camel.RouteConfigurationsBuilder;
import org.apache.camel.RoutesBuilder;
import org.apache.camel.RuntimeCamelException;
import org.apache.camel.Service;
import org.apache.camel.ServiceStatus;
import org.apache.camel.ShutdownRoute;
import org.apache.camel.ShutdownRunningTask;
import org.apache.camel.StartupListener;
import org.apache.camel.StartupStep;
import org.apache.camel.StartupSummaryLevel;
import org.apache.camel.Suspendable;
import org.apache.camel.SuspendableService;
import org.apache.camel.TypeConverter;
import org.apache.camel.VetoCamelContextStartException;
import org.apache.camel.api.management.JmxSystemPropertyKeys;
import org.apache.camel.catalog.RuntimeCamelCatalog;
import org.apache.camel.clock.Clock;
import org.apache.camel.clock.ContextClock;
import org.apache.camel.clock.EventClock;
import org.apache.camel.console.DevConsoleRegistry;
import org.apache.camel.console.DevConsoleResolver;
import org.apache.camel.health.HealthCheckRegistry;
import org.apache.camel.health.HealthCheckResolver;
import org.apache.camel.impl.debugger.DefaultBacklogDebugger;
import org.apache.camel.spi.AnnotationBasedProcessorFactory;
import org.apache.camel.spi.AnnotationScanTypeConverters;
import org.apache.camel.spi.AsyncProcessorAwaitManager;
import org.apache.camel.spi.BacklogDebugger;
import org.apache.camel.spi.BeanIntrospection;
import org.apache.camel.spi.BeanProcessorFactory;
import org.apache.camel.spi.BeanProxyFactory;
import org.apache.camel.spi.BootstrapCloseable;
import org.apache.camel.spi.CamelBeanPostProcessor;
import org.apache.camel.spi.CamelContextNameStrategy;
import org.apache.camel.spi.CamelContextTracker;
import org.apache.camel.spi.CamelDependencyInjectionAnnotationFactory;
import org.apache.camel.spi.CamelLogger;
import org.apache.camel.spi.ClassResolver;
import org.apache.camel.spi.CliConnector;
import org.apache.camel.spi.CliConnectorFactory;
import org.apache.camel.spi.ComponentNameResolver;
import org.apache.camel.spi.ComponentResolver;
import org.apache.camel.spi.ConfigurerResolver;
import org.apache.camel.spi.DataFormat;
import org.apache.camel.spi.DataFormatResolver;
import org.apache.camel.spi.DataType;
import org.apache.camel.spi.Debugger;
import org.apache.camel.spi.DebuggerFactory;
import org.apache.camel.spi.DeferServiceFactory;
import org.apache.camel.spi.DumpRoutesStrategy;
import org.apache.camel.spi.EndpointRegistry;
import org.apache.camel.spi.EndpointServiceRegistry;
import org.apache.camel.spi.EndpointStrategy;
import org.apache.camel.spi.EventNotifier;
import org.apache.camel.spi.ExchangeFactory;
import org.apache.camel.spi.ExchangeFactoryManager;
import org.apache.camel.spi.ExecutorServiceManager;
import org.apache.camel.spi.FactoryFinder;
import org.apache.camel.spi.FactoryFinderResolver;
import org.apache.camel.spi.HeadersMapFactory;
import org.apache.camel.spi.InflightRepository;
import org.apache.camel.spi.Injector;
import org.apache.camel.spi.InterceptEndpointFactory;
import org.apache.camel.spi.InterceptSendToEndpoint;
import org.apache.camel.spi.InternalProcessorFactory;
import org.apache.camel.spi.Language;
import org.apache.camel.spi.LanguageResolver;
import org.apache.camel.spi.LifecycleStrategy;
import org.apache.camel.spi.ManagementNameStrategy;
import org.apache.camel.spi.ManagementStrategy;
import org.apache.camel.spi.MessageHistoryFactory;
import org.apache.camel.spi.ModelJAXBContextFactory;
import org.apache.camel.spi.ModelToXMLDumper;
import org.apache.camel.spi.ModelToYAMLDumper;
import org.apache.camel.spi.ModelineFactory;
import org.apache.camel.spi.NodeIdFactory;
import org.apache.camel.spi.NormalizedEndpointUri;
import org.apache.camel.spi.PackageScanClassResolver;
import org.apache.camel.spi.PackageScanResourceResolver;
import org.apache.camel.spi.PeriodTaskResolver;
import org.apache.camel.spi.PeriodTaskScheduler;
import org.apache.camel.spi.ProcessorExchangeFactory;
import org.apache.camel.spi.ProcessorFactory;
import org.apache.camel.spi.PropertiesComponent;
import org.apache.camel.spi.ReactiveExecutor;
import org.apache.camel.spi.Registry;
import org.apache.camel.spi.ResourceLoader;
import org.apache.camel.spi.RestBindingJaxbDataFormatFactory;
import org.apache.camel.spi.RestConfiguration;
import org.apache.camel.spi.RestRegistry;
import org.apache.camel.spi.RestRegistryFactory;
import org.apache.camel.spi.RouteController;
import org.apache.camel.spi.RouteError.Phase;
import org.apache.camel.spi.RouteFactory;
import org.apache.camel.spi.RoutePolicyFactory;
import org.apache.camel.spi.RouteStartupOrder;
import org.apache.camel.spi.RouteTemplateParameterSource;
import org.apache.camel.spi.RoutesLoader;
import org.apache.camel.spi.RuntimeEndpointRegistry;
import org.apache.camel.spi.ShutdownStrategy;
import org.apache.camel.spi.StartupConditionStrategy;
import org.apache.camel.spi.StartupStepRecorder;
import org.apache.camel.spi.StreamCachingStrategy;
import org.apache.camel.spi.Tracer;
import org.apache.camel.spi.Transformer;
import org.apache.camel.spi.TransformerKey;
import org.apache.camel.spi.TransformerRegistry;
import org.apache.camel.spi.TypeConverterRegistry;
import org.apache.camel.spi.UnitOfWorkFactory;
import org.apache.camel.spi.UriFactoryResolver;
import org.apache.camel.spi.UuidGenerator;
import org.apache.camel.spi.Validator;
import org.apache.camel.spi.ValidatorKey;
import org.apache.camel.spi.ValidatorRegistry;
import org.apache.camel.spi.VariableRepository;
import org.apache.camel.spi.VariableRepositoryFactory;
import org.apache.camel.support.CamelContextHelper;
import org.apache.camel.support.EndpointHelper;
import org.apache.camel.support.EventHelper;
import org.apache.camel.support.LRUCacheFactory;
import org.apache.camel.support.NormalizedUri;
import org.apache.camel.support.OrderedComparator;
import org.apache.camel.support.PluginHelper;
import org.apache.camel.support.ProcessorEndpoint;
import org.apache.camel.support.ResetableClock;
import org.apache.camel.support.ResolverHelper;
import org.apache.camel.support.jsse.SSLContextParameters;
import org.apache.camel.support.service.BaseService;
import org.apache.camel.support.service.ServiceHelper;
import org.apache.camel.util.IOHelper;
import org.apache.camel.util.ObjectHelper;
import org.apache.camel.util.StopWatch;
import org.apache.camel.util.StringHelper;
import org.apache.camel.util.TimeUtils;
import org.apache.camel.util.URISupport;
import org.apache.camel.vault.VaultConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import static org.apache.camel.spi.UnitOfWork.MDC_CAMEL_CONTEXT_ID;
/**
* Represents the context used to configure routes and the policies to use.
*/
public abstract class AbstractCamelContext extends BaseService
implements CamelContext, CatalogCamelContext, Suspendable {
private static final Logger LOG = LoggerFactory.getLogger(AbstractCamelContext.class);
private final InternalServiceManager internalServiceManager;
private final DefaultCamelContextExtension camelContextExtension = new DefaultCamelContextExtension(this);
private final AtomicInteger endpointKeyCounter = new AtomicInteger();
private final Set endpointStrategies = ConcurrentHashMap.newKeySet();
private final GlobalEndpointConfiguration globalEndpointConfiguration = new DefaultGlobalEndpointConfiguration();
private final Map components = new ConcurrentHashMap<>();
private final Set routes = new LinkedHashSet<>();
private final List startupListeners = new CopyOnWriteArrayList<>();
private final Map languages = new ConcurrentHashMap<>();
private final Map dataformats = new ConcurrentHashMap<>();
private final List lifecycleStrategies = new CopyOnWriteArrayList<>();
private final ThreadLocal isStartingRoutes = new ThreadLocal<>();
private final ThreadLocal isLockModel = new ThreadLocal<>();
private final Map routeServices = new LinkedHashMap<>();
private final Map suspendedRouteServices = new LinkedHashMap<>();
private final InternalRouteStartupManager internalRouteStartupManager = new InternalRouteStartupManager();
private final List routeStartupOrder = new ArrayList<>();
private final StopWatch stopWatch = new StopWatch(false);
private final ThreadLocal> componentsInCreation = ThreadLocal.withInitial(HashSet::new);
private final Lock routesLock = new ReentrantLock();
private final Lock lock = new ReentrantLock();
private VetoCamelContextStartException vetoed;
private String managementName;
private ClassLoader applicationContextClassLoader;
private boolean autoCreateComponents = true;
private VaultConfiguration vaultConfiguration = new VaultConfiguration();
private final List routePolicyFactories = new ArrayList<>();
// special flags to control the first startup which can are special
private volatile boolean firstStartDone;
private volatile boolean doNotStartRoutesOnFirstStart;
private Boolean autoStartup = Boolean.TRUE;
private Boolean backlogTrace = Boolean.FALSE;
private Boolean backlogTraceStandby = Boolean.FALSE;
private Boolean backlogTraceTemplates = Boolean.FALSE;
private Boolean trace = Boolean.FALSE;
private Boolean traceStandby = Boolean.FALSE;
private Boolean traceTemplates = Boolean.FALSE;
private String tracePattern;
private String tracingLoggingFormat;
private Boolean modeline = Boolean.FALSE;
private Boolean debug = Boolean.FALSE;
private Boolean debugStandby = Boolean.FALSE;
private String debugBreakpoints;
private Boolean messageHistory = Boolean.FALSE;
private Boolean logMask = Boolean.FALSE;
private Boolean logExhaustedMessageBody = Boolean.FALSE;
private Boolean streamCache = Boolean.TRUE;
private Boolean disableJMX = Boolean.FALSE;
private Boolean loadTypeConverters = Boolean.FALSE;
private Boolean loadHealthChecks = Boolean.FALSE;
private Boolean devConsole = Boolean.FALSE;
private Boolean sourceLocationEnabled = Boolean.FALSE;
private Boolean typeConverterStatisticsEnabled = Boolean.FALSE;
private String dumpRoutes;
private Boolean useMDCLogging = Boolean.FALSE;
private String mdcLoggingKeysPattern;
private Boolean useDataType = Boolean.FALSE;
private Boolean useBreadcrumb = Boolean.FALSE;
private Boolean allowUseOriginalMessage = Boolean.FALSE;
private Boolean caseInsensitiveHeaders = Boolean.TRUE;
private Boolean autowiredEnabled = Boolean.TRUE;
private Long delay;
private Map globalOptions = new HashMap<>();
private EndpointRegistry endpoints;
private RuntimeEndpointRegistry runtimeEndpointRegistry;
private ShutdownRoute shutdownRoute = ShutdownRoute.Default;
private ShutdownRunningTask shutdownRunningTask = ShutdownRunningTask.CompleteCurrentTaskOnly;
private Debugger debugger;
private long buildTaken;
private long initTaken;
private final ContextClock clock = new ContextClock();
private SSLContextParameters sslContextParameters;
private StartupSummaryLevel startupSummaryLevel = StartupSummaryLevel.Default;
/**
* Creates the {@link CamelContext} using {@link org.apache.camel.support.DefaultRegistry} as registry.
*
* Use one of the other constructors to force use an explicit registry.
*/
protected AbstractCamelContext() {
this(true);
}
/**
* Creates the {@link CamelContext} using the given registry
*
* @param registry the registry
*/
protected AbstractCamelContext(Registry registry) {
this();
camelContextExtension.setRegistry(registry);
}
protected AbstractCamelContext(boolean build) {
// create a provisional (temporary) endpoint registry at first since end
// users may access endpoints before CamelContext is started
// we will later transfer the endpoints to the actual
// DefaultEndpointRegistry later, but we do this to startup Camel faster.
this.endpoints = new ProvisionalEndpointRegistry();
// add a default LifecycleStrategy that discover strategies on the registry and invoke them
this.lifecycleStrategies.add(new OnCamelContextLifecycleStrategy());
// add a default LifecycleStrategy to customize services using customizers from registry
this.lifecycleStrategies.add(new CustomizersLifecycleStrategy(this));
// add a default autowired strategy
this.lifecycleStrategies.add(new DefaultAutowiredLifecycleStrategy(this));
// add the default bootstrap closer
camelContextExtension.addBootstrap(new DefaultServiceBootstrapCloseable(this));
this.internalServiceManager = new InternalServiceManager(internalRouteStartupManager, startupListeners);
initPlugins();
if (build) {
try {
build();
} catch (Exception e) {
throw new RuntimeException("Error initializing CamelContext", e);
}
}
}
/**
* Called during object construction to initialize context plugins
*/
protected void initPlugins() {
camelContextExtension.addContextPlugin(StartupConditionStrategy.class, createStartupConditionStrategy());
camelContextExtension.addContextPlugin(CamelBeanPostProcessor.class, createBeanPostProcessor());
camelContextExtension.addContextPlugin(CamelDependencyInjectionAnnotationFactory.class,
createDependencyInjectionAnnotationFactory());
camelContextExtension.addContextPlugin(ComponentResolver.class, createComponentResolver());
camelContextExtension.addContextPlugin(ComponentNameResolver.class, createComponentNameResolver());
camelContextExtension.addContextPlugin(LanguageResolver.class, createLanguageResolver());
camelContextExtension.addContextPlugin(ConfigurerResolver.class, createConfigurerResolver());
camelContextExtension.addContextPlugin(UriFactoryResolver.class, createUriFactoryResolver());
camelContextExtension.addContextPlugin(FactoryFinderResolver.class, createFactoryFinderResolver());
camelContextExtension.addContextPlugin(PackageScanClassResolver.class, createPackageScanClassResolver());
camelContextExtension.addContextPlugin(PackageScanResourceResolver.class, createPackageScanResourceResolver());
camelContextExtension.addContextPlugin(VariableRepositoryFactory.class, createVariableRepositoryFactory());
camelContextExtension.lazyAddContextPlugin(ModelineFactory.class, this::createModelineFactory);
camelContextExtension.lazyAddContextPlugin(ModelJAXBContextFactory.class, this::createModelJAXBContextFactory);
camelContextExtension.addContextPlugin(DataFormatResolver.class, createDataFormatResolver());
camelContextExtension.lazyAddContextPlugin(PeriodTaskResolver.class, this::createPeriodTaskResolver);
camelContextExtension.lazyAddContextPlugin(PeriodTaskScheduler.class, this::createPeriodTaskScheduler);
camelContextExtension.lazyAddContextPlugin(HealthCheckResolver.class, this::createHealthCheckResolver);
camelContextExtension.lazyAddContextPlugin(DevConsoleResolver.class, this::createDevConsoleResolver);
camelContextExtension.lazyAddContextPlugin(ProcessorFactory.class, this::createProcessorFactory);
camelContextExtension.lazyAddContextPlugin(InternalProcessorFactory.class, this::createInternalProcessorFactory);
camelContextExtension.lazyAddContextPlugin(InterceptEndpointFactory.class, this::createInterceptEndpointFactory);
camelContextExtension.lazyAddContextPlugin(RouteFactory.class, this::createRouteFactory);
camelContextExtension.lazyAddContextPlugin(RoutesLoader.class, this::createRoutesLoader);
camelContextExtension.lazyAddContextPlugin(AsyncProcessorAwaitManager.class, this::createAsyncProcessorAwaitManager);
camelContextExtension.lazyAddContextPlugin(RuntimeCamelCatalog.class, this::createRuntimeCamelCatalog);
camelContextExtension.lazyAddContextPlugin(RestBindingJaxbDataFormatFactory.class,
this::createRestBindingJaxbDataFormatFactory);
camelContextExtension.lazyAddContextPlugin(BeanProxyFactory.class, this::createBeanProxyFactory);
camelContextExtension.lazyAddContextPlugin(UnitOfWorkFactory.class, this::createUnitOfWorkFactory);
camelContextExtension.lazyAddContextPlugin(BeanIntrospection.class, this::createBeanIntrospection);
camelContextExtension.lazyAddContextPlugin(ResourceLoader.class, this::createResourceLoader);
camelContextExtension.lazyAddContextPlugin(BeanProcessorFactory.class, this::createBeanProcessorFactory);
camelContextExtension.lazyAddContextPlugin(ModelToXMLDumper.class, this::createModelToXMLDumper);
camelContextExtension.lazyAddContextPlugin(ModelToYAMLDumper.class, this::createModelToYAMLDumper);
camelContextExtension.lazyAddContextPlugin(DeferServiceFactory.class, this::createDeferServiceFactory);
camelContextExtension.lazyAddContextPlugin(AnnotationBasedProcessorFactory.class,
this::createAnnotationBasedProcessorFactory);
camelContextExtension.lazyAddContextPlugin(DumpRoutesStrategy.class, this::createDumpRoutesStrategy);
}
protected static T lookup(CamelContext context, String ref, Class type) {
try {
return context.getRegistry().lookupByNameAndType(ref, type);
} catch (Exception e) {
// need to ignore not same type and return it as null
return null;
}
}
public void close() throws IOException {
try {
stop();
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new IOException(e);
}
}
public CamelContext getCamelContextReference() {
return this;
}
/**
* Whether to eager create {@link TypeConverter} during initialization of CamelContext. This is enabled by default
* to optimize camel-core.
*/
protected boolean eagerCreateTypeConverter() {
return true;
}
@Override
public boolean isVetoStarted() {
return vetoed != null;
}
@Override
public CamelContextNameStrategy getNameStrategy() {
return camelContextExtension.getNameStrategy();
}
@Override
public void setNameStrategy(CamelContextNameStrategy nameStrategy) {
camelContextExtension.setNameStrategy(nameStrategy);
}
@Override
public ManagementNameStrategy getManagementNameStrategy() {
return camelContextExtension.getManagementNameStrategy();
}
@Override
public void setManagementNameStrategy(ManagementNameStrategy managementNameStrategy) {
camelContextExtension.setManagementNameStrategy(managementNameStrategy);
}
@Override
public String getManagementName() {
return managementName;
}
@Override
public void setManagementName(String managementName) {
this.managementName = managementName;
}
@Override
public Component hasComponent(String componentName) {
if (components.isEmpty()) {
return null;
}
return components.get(componentName);
}
@Override
public void addComponent(String componentName, final Component component) {
ObjectHelper.notNull(component, "component");
component.setCamelContext(getCamelContextReference());
if (isStarted()) {
// start component if context is already started (camel will start components when it starts)
ServiceHelper.startService(component);
} else {
// otherwise init the component
ServiceHelper.initService(component);
}
Component oldValue = components.putIfAbsent(componentName, component);
if (oldValue != null) {
throw new IllegalArgumentException("Cannot add component as its already previously added: " + componentName);
}
postInitComponent(componentName, component);
}
private void postInitComponent(String componentName, final Component component) {
for (LifecycleStrategy strategy : lifecycleStrategies) {
strategy.onComponentAdd(componentName, component);
}
}
@Override
public Component getComponent(String name) {
return getComponent(name, autoCreateComponents, true);
}
@Override
public Component getComponent(String name, boolean autoCreateComponents) {
return getComponent(name, autoCreateComponents, true);
}
@Override
public Component getComponent(String name, boolean autoCreateComponents, boolean autoStart) {
// ensure CamelContext are initialized before we can get a component
build();
// Check if the named component is already being created, that would mean
// that the initComponent has triggered a new getComponent
if (componentsInCreation.get().contains(name)) {
throw new IllegalStateException(
"Circular dependency detected, the component " + name + " is already being created");
}
try {
// Flag used to mark a component of being created.
final AtomicBoolean created = new AtomicBoolean();
// atomic operation to get/create a component. Avoid global locks.
final Component component = components.computeIfAbsent(name, comp -> {
created.set(true);
return initComponent(name, autoCreateComponents);
});
// Start the component after its creation as if it is a component proxy
// that creates/start a delegated component, we may end up in a deadlock
if (component != null && created.get() && autoStart && (isStarted() || isStarting())) {
// If the component is looked up after the context is started,
// lets start it up.
final StartupStepRecorder startupStepRecorder = camelContextExtension.getStartupStepRecorder();
StartupStep step = startupStepRecorder.beginStep(Component.class, name, "Start Component");
startService(component);
startupStepRecorder.endStep(step);
}
return component;
} catch (Exception e) {
throw new RuntimeCamelException("Cannot auto create component: " + name, e);
} finally {
// remove the reference to the component being created
componentsInCreation.get().remove(name);
}
}
/**
* Function to initialize a component and auto start. Returns null if the autoCreateComponents is disabled
*/
private Component initComponent(String name, boolean autoCreateComponents) {
Component component = null;
if (autoCreateComponents) {
final StartupStepRecorder startupStepRecorder = camelContextExtension.getStartupStepRecorder();
StartupStep step = startupStepRecorder.beginStep(Component.class, name, "Resolve Component");
try {
if (LOG.isDebugEnabled()) {
LOG.debug("Using ComponentResolver: {} to resolve component with name: {}",
PluginHelper.getComponentResolver(camelContextExtension), name);
}
// Mark the component as being created so we can detect circular
// requests.
//
// In spring apps, the component resolver may trigger a new
// getComponent because of the underlying bean factory and as
// the endpoints are registered as singleton, the spring factory
// creates the bean and then check the type so the getComponent
// is always triggered.
//
// This would freeze the app (lock or infinite loop).
//
// See https://issues.apache.org/jira/browse/CAMEL-11225
componentsInCreation.get().add(name);
component = ResolverHelper.lookupComponentInRegistryWithFallback(getCamelContextReference(), name);
if (component == null) {
component = PluginHelper.getComponentResolver(camelContextExtension).resolveComponent(name,
getCamelContextReference());
}
if (component != null) {
component.setCamelContext(getCamelContextReference());
ServiceHelper.buildService(component);
postInitComponent(name, component);
}
} catch (Exception e) {
throw new RuntimeCamelException("Cannot auto create component: " + name, e);
}
startupStepRecorder.endStep(step);
}
return component;
}
@Override
public T getComponent(String name, Class componentType) {
Component component = getComponent(name);
if (componentType.isInstance(component)) {
return componentType.cast(component);
}
final String message = invalidComponentMessage(name, componentType, component);
throw new IllegalArgumentException(message);
}
private static <
T extends Component> String invalidComponentMessage(String name, Class componentType, Component component) {
if (component == null) {
return "Did not find component given by the name: " + name;
} else {
return "Found component of type: " + component.getClass() + " instead of expected: " + componentType;
}
}
// Endpoint Management Methods
// -----------------------------------------------------------------------
@Override
public Component removeComponent(String componentName) {
Component oldComponent = components.remove(componentName);
if (oldComponent != null) {
try {
stopServices(oldComponent);
} catch (Exception e) {
LOG.warn("Error stopping component {}. This exception will be ignored.", oldComponent, e);
}
for (LifecycleStrategy strategy : lifecycleStrategies) {
strategy.onComponentRemove(componentName, oldComponent);
}
}
return oldComponent;
}
@Override
public EndpointRegistry getEndpointRegistry() {
return endpoints;
}
@Override
public Collection getEndpoints() {
return endpoints.getReadOnlyValues();
}
@Override
public Endpoint hasEndpoint(String uri) {
if (endpoints.isEmpty()) {
return null;
}
return endpoints.get(getEndpointKey(uri));
}
@Override
public Endpoint addEndpoint(String uri, Endpoint endpoint) throws Exception {
Endpoint oldEndpoint;
startService(endpoint);
oldEndpoint = endpoints.remove(getEndpointKey(uri));
for (LifecycleStrategy strategy : lifecycleStrategies) {
strategy.onEndpointAdd(endpoint);
}
addEndpointToRegistry(uri, endpoint);
if (oldEndpoint != null && oldEndpoint != endpoint) {
stopServices(oldEndpoint);
}
return oldEndpoint;
}
@Override
public void removeEndpoint(Endpoint endpoint) {
Endpoint oldEndpoint = null;
NormalizedEndpointUri oldKey = null;
for (Map.Entry entry : endpoints.entrySet()) {
if (endpoint == entry.getValue()) {
oldKey = entry.getKey();
oldEndpoint = endpoint;
break;
}
}
if (oldEndpoint != null) {
endpoints.remove(oldKey);
try {
stopServices(oldEndpoint);
} catch (Exception e) {
LOG.warn("Error stopping endpoint {}. This exception will be ignored.", oldEndpoint, e);
}
for (LifecycleStrategy strategy : lifecycleStrategies) {
strategy.onEndpointRemove(oldEndpoint);
}
}
}
@Override
public Collection removeEndpoints(String uri) {
Collection answer = new ArrayList<>();
Endpoint oldEndpoint = endpoints.remove(getEndpointKey(uri));
if (oldEndpoint != null) {
answer.add(oldEndpoint);
stopServices(oldEndpoint);
} else {
final String decodeUri = URISupport.getDecodeQuery(uri);
if (decodeUri != null) {
oldEndpoint = endpoints.remove(getEndpointKey(decodeUri));
}
if (oldEndpoint != null) {
answer.add(oldEndpoint);
stopServices(oldEndpoint);
} else {
tryMatchingEndpoints(uri, answer);
}
}
// notify lifecycle its being removed
for (Endpoint endpoint : answer) {
for (LifecycleStrategy strategy : lifecycleStrategies) {
strategy.onEndpointRemove(endpoint);
}
}
return answer;
}
private void tryMatchingEndpoints(String uri, Collection answer) {
Endpoint oldEndpoint;
List toRemove = new ArrayList<>();
for (Map.Entry entry : endpoints.entrySet()) {
oldEndpoint = entry.getValue();
if (EndpointHelper.matchEndpoint(this, oldEndpoint.getEndpointUri(), uri)) {
try {
stopServices(oldEndpoint);
} catch (Exception e) {
LOG.warn("Error stopping endpoint {}. This exception will be ignored.", oldEndpoint, e);
}
answer.add(oldEndpoint);
toRemove.add(entry.getKey());
}
}
for (NormalizedEndpointUri key : toRemove) {
endpoints.remove(key);
}
}
@Override
public Endpoint getEndpoint(String uri) {
final StartupStepRecorder startupStepRecorder = camelContextExtension.getStartupStepRecorder();
StartupStep step = null;
// only record startup step during startup (not started)
if (!isStarted() && startupStepRecorder.isEnabled()) {
String u = URISupport.sanitizeUri(uri);
step = startupStepRecorder.beginStep(Endpoint.class, u, "Get Endpoint");
}
Endpoint answer = doGetEndpoint(uri, null, false, false);
if (step != null) {
startupStepRecorder.endStep(step);
}
return answer;
}
@Override
public Endpoint getEndpoint(String uri, Map parameters) {
return doGetEndpoint(uri, parameters, false, false);
}
protected Endpoint doGetEndpoint(String uri, Map parameters, boolean normalized, boolean prototype) {
// ensure CamelContext are initialized before we can get an endpoint
build();
StringHelper.notEmpty(uri, "uri");
LOG.trace("Getting endpoint with uri: {} and parameters: {}", uri, parameters);
if (!normalized) {
// java 17 text blocks to single line uri
uri = URISupport.textBlockToSingleLine(uri);
// in case path has property placeholders then try to let property component resolve those
uri = EndpointHelper.resolveEndpointUriPropertyPlaceholders(this, uri);
}
final String rawUri = uri;
// normalize uri so we can do endpoint hits with minor mistakes and
// parameters is not in the same order
if (!normalized) {
uri = EndpointHelper.normalizeEndpointUri(uri);
}
LOG.trace("Getting endpoint with raw uri: {}, normalized uri: {}", rawUri, uri);
String scheme;
Endpoint answer = null;
if (!prototype) {
// use optimized method to get the endpoint uri
NormalizedUri key = NormalizedUri.newNormalizedUri(uri, true);
// only lookup and reuse existing endpoints if not prototype scoped
answer = endpoints.get(key);
}
if (answer == null) {
try {
scheme = StringHelper.before(uri, ":");
if (scheme == null) {
// it may refer to a logical endpoint
answer = camelContextExtension.getRegistry().lookupByNameAndType(uri, Endpoint.class);
if (answer != null) {
return answer;
} else {
throw new NoSuchEndpointException(uri);
}
}
LOG.trace("Endpoint uri: {} is from component with name: {}", uri, scheme);
Component component = getComponent(scheme);
ServiceHelper.initService(component);
// Ask the component to resolve the endpoint.
if (component != null) {
LOG.trace("Creating endpoint from uri: {} using component: {}", uri, component);
// Have the component create the endpoint if it can.
answer = component.createEndpoint(
component.useRawUri() ? rawUri : uri,
parameters);
if (answer != null && LOG.isDebugEnabled()) {
LOG.debug("{} converted to endpoint: {} by component: {}", URISupport.sanitizeUri(uri), answer,
component);
}
}
if (answer == null) {
// no component then try in registry and elsewhere
answer = createEndpoint(uri);
LOG.trace("No component to create endpoint from uri: {} fallback lookup in registry -> {}", uri, answer);
}
if (answer != null) {
if (!prototype) {
addService(answer);
// register in registry
answer = addEndpointToRegistry(uri, answer);
} else {
addPrototypeService(answer);
// if there is endpoint strategies, then use the endpoints they return
// as this allows to intercept endpoints etc.
for (EndpointStrategy strategy : endpointStrategies) {
answer = strategy.registerEndpoint(uri, answer);
}
}
}
} catch (NoSuchEndpointException e) {
// throw as-is
throw e;
} catch (Exception e) {
throw new ResolveEndpointFailedException(uri, e);
}
}
// unknown scheme
if (answer == null) {
throw new NoSuchEndpointException(uri);
}
return answer;
}
@Override
public T getEndpoint(String name, Class endpointType) {
Endpoint endpoint = getEndpoint(name);
if (endpoint == null) {
throw new NoSuchEndpointException(name);
}
if (endpoint instanceof InterceptSendToEndpoint interceptSendToEndpoint) {
endpoint = interceptSendToEndpoint.getOriginalEndpoint();
}
if (endpointType.isInstance(endpoint)) {
return endpointType.cast(endpoint);
} else {
throw new IllegalArgumentException(
"The endpoint is not of type: " + endpointType + " but is: " + endpoint.getClass().getCanonicalName());
}
}
/**
* Strategy to add the given endpoint to the internal endpoint registry
*
* @param uri uri of the endpoint
* @param endpoint the endpoint to add
* @return the added endpoint
*/
protected Endpoint addEndpointToRegistry(String uri, Endpoint endpoint) {
StringHelper.notEmpty(uri, "uri");
ObjectHelper.notNull(endpoint, "endpoint");
// if there is endpoint strategies, then use the endpoints they return
// as this allows to intercept endpoints etc.
for (EndpointStrategy strategy : endpointStrategies) {
endpoint = strategy.registerEndpoint(uri, endpoint);
}
endpoints.put(getEndpointKey(uri, endpoint), endpoint);
return endpoint;
}
/**
* Gets the endpoint key to use for lookup or whe adding endpoints to the {@link DefaultEndpointRegistry}
*
* @param uri the endpoint uri
* @return the key
*/
protected NormalizedUri getEndpointKey(String uri) {
return NormalizedUri.newNormalizedUri(uri, false);
}
/**
* Gets the endpoint key to use for lookup or whe adding endpoints to the {@link DefaultEndpointRegistry}
*
* @param uri the endpoint uri
* @param endpoint the endpoint
* @return the key
*/
protected NormalizedUri getEndpointKey(String uri, Endpoint endpoint) {
if (endpoint != null && !endpoint.isSingleton()) {
int counter = endpointKeyCounter.incrementAndGet();
return NormalizedUri.newNormalizedUri(uri + ":" + counter, false);
} else {
return NormalizedUri.newNormalizedUri(uri, false);
}
}
// Route Management Methods
// -----------------------------------------------------------------------
@Override
public GlobalEndpointConfiguration getGlobalEndpointConfiguration() {
return globalEndpointConfiguration;
}
@Override
public RouteController getRouteController() {
return camelContextExtension.getRouteController();
}
@Override
public void setRouteController(RouteController routeController) {
camelContextExtension.setRouteController(routeController);
}
@Override
public List getRoutes() {
// let's return a copy of the collection as objects are removed later
// when services are stopped
if (routes.isEmpty()) {
return Collections.emptyList();
} else {
routesLock.lock();
try {
return new ArrayList<>(routes);
} finally {
routesLock.unlock();
}
}
}
@Override
public int getRoutesSize() {
return routes.size();
}
@Override
public Route getRoute(String id) {
if (id != null) {
for (Route route : getRoutes()) {
if (route.getId().equals(id)) {
return route;
}
}
}
return null;
}
@Override
public Processor getProcessor(String id) {
for (Route route : getRoutes()) {
List list = route.filter(id);
if (list.size() == 1) {
return list.get(0);
}
}
return null;
}
@Override
public T getProcessor(String id, Class type) {
Processor answer = getProcessor(id);
if (answer != null) {
return type.cast(answer);
}
return null;
}
@Override
public void addRoutes(RoutesBuilder builder) throws Exception {
// in case the builder is also a route configuration builder
// then we need to add the configuration first
if (builder instanceof RouteConfigurationsBuilder rcBuilder) {
addRoutesConfigurations(rcBuilder);
}
try (LifecycleHelper helper = new LifecycleHelper()) {
build();
LOG.debug("Adding routes from builder: {}", builder);
builder.addRoutesToCamelContext(this);
}
}
@Override
public void addTemplatedRoutes(RoutesBuilder builder) throws Exception {
try (LifecycleHelper helper = new LifecycleHelper()) {
build();
LOG.debug("Adding templated routes from builder: {}", builder);
builder.addTemplatedRoutesToCamelContext(this);
}
}
@Override
public void addRoutesConfigurations(RouteConfigurationsBuilder builder) throws Exception {
try (LifecycleHelper helper = new LifecycleHelper()) {
build();
LOG.debug("Adding route configurations from builder: {}", builder);
builder.addRouteConfigurationsToCamelContext(this);
}
}
public ServiceStatus getRouteStatus(String key) {
RouteService routeService = routeServices.get(key);
if (routeService != null) {
return routeService.getStatus();
}
return null;
}
public boolean isStartingRoutes() {
Boolean answer = isStartingRoutes.get();
return answer != null && answer;
}
public void setStartingRoutes(boolean starting) {
if (starting) {
isStartingRoutes.set(true);
} else {
isStartingRoutes.remove();
}
}
public boolean isLockModel() {
Boolean answer = isLockModel.get();
return answer != null && answer;
}
public void setLockModel(boolean lockModel) {
if (lockModel) {
isLockModel.set(true);
} else {
isLockModel.remove();
}
}
public void startAllRoutes() throws Exception {
internalRouteStartupManager.doStartOrResumeRoutes(this, routeServices, true, true, false, false);
if (startupSummaryLevel != StartupSummaryLevel.Oneline
&& startupSummaryLevel != StartupSummaryLevel.Off) {
logRouteStartSummary(LoggingLevel.INFO);
}
}
private void doStopRoutes(RouteController controller, Comparator comparator) throws Exception {
List routesOrdered = new ArrayList<>(camelContextExtension.getRouteStartupOrder());
routesOrdered.sort(comparator);
for (RouteStartupOrder order : routesOrdered) {
Route route = order.getRoute();
var status = controller.getRouteStatus(route.getRouteId());
boolean stopped = status == null || status.isStopped();
if (!stopped) {
stopRoute(route.getRouteId(), LoggingLevel.DEBUG);
}
}
// stop any remainder routes
for (Route route : getRoutes()) {
var status = controller.getRouteStatus(route.getRouteId());
boolean stopped = status == null || status.isStopped();
if (!stopped) {
stopRoute(route.getRouteId(), LoggingLevel.DEBUG);
}
}
}
public void stopAllRoutes() throws Exception {
RouteController controller = getRouteController();
if (controller == null) {
// in case we are called during shutdown and controller is null
return;
}
// stop all routes in reverse order that they were started
Comparator comparator = Comparator.comparingInt(RouteStartupOrder::getStartupOrder);
final ShutdownStrategy shutdownStrategy = camelContextExtension.getShutdownStrategy();
if (shutdownStrategy == null || shutdownStrategy.isShutdownRoutesInReverseOrder()) {
comparator = comparator.reversed();
}
doStopRoutes(controller, comparator);
if (startupSummaryLevel != StartupSummaryLevel.Oneline
&& startupSummaryLevel != StartupSummaryLevel.Off) {
logRouteStopSummary(LoggingLevel.INFO);
}
}
public void removeAllRoutes() throws Exception {
// stop all routes in reverse order that they were started
Comparator comparator = Comparator.comparingInt(RouteStartupOrder::getStartupOrder);
final ShutdownStrategy shutdownStrategy = getShutdownStrategy();
if (shutdownStrategy == null || shutdownStrategy.isShutdownRoutesInReverseOrder()) {
comparator = comparator.reversed();
}
doStopRoutes(getRouteController(), comparator);
// do not be noisy when removing routes
// as this is used by route-reload functionality, so lets be brief
logRouteStopSummary(LoggingLevel.DEBUG);
// remove all routes
for (Route route : getRoutes()) {
removeRoute(route.getRouteId(), LoggingLevel.DEBUG);
}
}
public void startRoute(String routeId) throws Exception {
startRoute(routeId, LoggingLevel.INFO);
}
public void startRoute(String routeId, LoggingLevel loggingLevel) throws Exception {
lock.lock();
try {
DefaultRouteError.reset(this, routeId);
RouteService routeService = routeServices.get(routeId);
if (routeService != null) {
try {
startRouteService(routeService, false);
logRouteState(routeService.getRoute(), "Started", loggingLevel);
} catch (Exception e) {
DefaultRouteError.set(this, routeId, Phase.START, e);
throw e;
}
}
} finally {
lock.unlock();
}
}
public void resumeRoute(String routeId) throws Exception {
resumeRoute(routeId, LoggingLevel.INFO);
}
public void resumeRoute(String routeId, LoggingLevel loggingLevel) throws Exception {
lock.lock();
try {
DefaultRouteError.reset(this, routeId);
try {
if (!routeSupportsSuspension(routeId)) {
// start route if suspension is not supported
startRoute(routeId, loggingLevel);
return;
}
RouteService routeService = routeServices.get(routeId);
if (routeService != null) {
resumeRouteService(routeService);
// must resume the route as well
Route route = getRoute(routeId);
ServiceHelper.resumeService(route);
logRouteState(routeService.getRoute(), "Resumed", loggingLevel);
}
} catch (Exception e) {
DefaultRouteError.set(this, routeId, Phase.RESUME, e);
throw e;
}
} finally {
lock.unlock();
}
}
public boolean stopRoute(
String routeId, long timeout, TimeUnit timeUnit, boolean abortAfterTimeout, LoggingLevel loggingLevel)
throws Exception {
lock.lock();
try {
DefaultRouteError.reset(this, routeId);
RouteService routeService = routeServices.get(routeId);
if (routeService != null) {
try {
RouteStartupOrder route = new DefaultRouteStartupOrder(1, routeService.getRoute(), routeService);
boolean completed = camelContextExtension.getShutdownStrategy()
.shutdown(this, route, timeout, timeUnit, abortAfterTimeout);
if (completed) {
// must stop route service as well
stopRouteService(routeService, false, loggingLevel);
} else {
// shutdown was aborted, make sure route is re-started properly
startRouteService(routeService, false);
}
return completed;
} catch (Exception e) {
DefaultRouteError.set(this, routeId, Phase.STOP, e);
throw e;
}
}
return false;
} finally {
lock.unlock();
}
}
public void stopRoute(String routeId) throws Exception {
stopRoute(routeId, LoggingLevel.INFO);
}
public void stopRoute(String routeId, LoggingLevel loggingLevel) throws Exception {
doShutdownRoute(routeId, getShutdownStrategy().getTimeout(), getShutdownStrategy().getTimeUnit(), false, loggingLevel);
}
public void stopRoute(String routeId, long timeout, TimeUnit timeUnit) throws Exception {
doShutdownRoute(routeId, timeout, timeUnit, false, LoggingLevel.INFO);
}
protected void doShutdownRoute(
String routeId, long timeout, TimeUnit timeUnit, boolean removingRoutes, LoggingLevel loggingLevel)
throws Exception {
lock.lock();
try {
DefaultRouteError.reset(this, routeId);
RouteService routeService = routeServices.get(routeId);
if (routeService != null) {
try {
List routeList = new ArrayList<>(1);
RouteStartupOrder order = new DefaultRouteStartupOrder(1, routeService.getRoute(), routeService);
routeList.add(order);
getShutdownStrategy().shutdown(this, routeList, timeout, timeUnit);
// must stop route service as well (and remove the routes from
// management)
stopRouteService(routeService, removingRoutes, loggingLevel);
} catch (Exception e) {
DefaultRouteError.set(this, routeId, removingRoutes ? Phase.SHUTDOWN : Phase.STOP, e);
throw e;
}
}
} finally {
lock.unlock();
}
}
@Override
public boolean removeRoute(String routeId) throws Exception {
lock.lock();
try {
return removeRoute(routeId, LoggingLevel.INFO);
} finally {
lock.unlock();
}
}
protected boolean removeRoute(String routeId, LoggingLevel loggingLevel) throws Exception {
lock.lock();
try {
DefaultRouteError.reset(this, routeId);
// gather a map of all the endpoints in use by the routes, so we can
// known if a given endpoints is in use
// by one or more routes, when we remove the route
Map> endpointsInUse = new HashMap<>();
for (Map.Entry entry : routeServices.entrySet()) {
endpointsInUse.put(entry.getKey(), entry.getValue().gatherEndpoints());
}
RouteService routeService = routeServices.get(routeId);
if (routeService != null) {
if (getRouteStatus(routeId).isStopped()) {
try {
doRemove(routeId, loggingLevel, routeService, endpointsInUse);
} catch (Exception e) {
DefaultRouteError.set(this, routeId, Phase.REMOVE, e);
throw e;
}
return true;
} else {
return false;
}
}
return false;
} finally {
lock.unlock();
}
}
private void doRemove(
String routeId, LoggingLevel loggingLevel, RouteService routeService, Map> endpointsInUse) {
routeService.setRemovingRoutes(true);
shutdownRouteService(routeService, loggingLevel);
routeServices.remove(routeId);
// remove route from startup order as well, as it was
// removed
routeStartupOrder.removeIf(order -> order.getRoute().getId().equals(routeId));
// from the route which we have removed, then remove all its
// private endpoints
// (eg the endpoints which are not in use by other routes)
Set toRemove = new LinkedHashSet<>();
for (Endpoint endpoint : endpointsInUse.get(routeId)) {
// how many times is the endpoint in use
int count = 0;
for (Set endpointSet : endpointsInUse.values()) {
if (endpointSet.contains(endpoint)) {
count++;
}
}
// notice we will count ourselves so if there is only 1
// then its safe to remove
if (count <= 1) {
toRemove.add(endpoint);
}
}
for (Endpoint endpoint : toRemove) {
LOG.debug("Removing: {} which was only in use by route: {}", endpoint, routeId);
removeEndpoint(endpoint);
}
}
public void suspendRoute(String routeId) throws Exception {
suspendRoute(routeId, getShutdownStrategy().getTimeout(), getShutdownStrategy().getTimeUnit());
}
public void suspendRoute(String routeId, long timeout, TimeUnit timeUnit) throws Exception {
lock.lock();
try {
DefaultRouteError.reset(this, routeId);
try {
if (!routeSupportsSuspension(routeId)) {
stopRoute(routeId, timeout, timeUnit);
return;
}
RouteService routeService = routeServices.get(routeId);
if (routeService != null) {
List routeList = new ArrayList<>(1);
Route route = routeService.getRoute();
RouteStartupOrder order = new DefaultRouteStartupOrder(1, route, routeService);
routeList.add(order);
getShutdownStrategy().suspend(this, routeList, timeout, timeUnit);
// must suspend route service as well
suspendRouteService(routeService);
// must suspend the route as well
if (route instanceof SuspendableService suspendableService) {
suspendableService.suspend();
}
}
} catch (Exception e) {
DefaultRouteError.set(this, routeId, Phase.SUSPEND, e);
throw e;
}
} finally {
lock.unlock();
}
}
@Override
public void addService(Object object) throws Exception {
addService(object, true);
}
@Override
public void addService(Object object, boolean stopOnShutdown) throws Exception {
addService(object, stopOnShutdown, false);
}
@Override
public void addService(Object object, boolean stopOnShutdown, boolean forceStart) throws Exception {
internalServiceManager.doAddService(this, object, stopOnShutdown, forceStart, true);
}
@Override
public void addPrototypeService(Object object) {
internalServiceManager.addService(this, object, false, true, false);
}
@Override
public boolean removeService(Object object) throws Exception {
if (object instanceof Endpoint endpoint) {
removeEndpoint(endpoint);
return true;
}
if (object instanceof Service service) {
for (LifecycleStrategy strategy : lifecycleStrategies) {
strategy.onServiceRemove(this, service, null);
}
return internalServiceManager.removeService(service);
}
return false;
}
@Override
public boolean hasService(Object object) {
return internalServiceManager.hasService(object);
}
@Override
public T hasService(Class type) {
return internalServiceManager.hasService(type);
}
@Override
public Set hasServices(Class type) {
return internalServiceManager.hasServices(type);
}
@Override
public Service hasService(Predicate filter) {
return internalServiceManager.getServices().stream().filter(filter).findFirst().orElse(null);
}
@Override
public void deferStartService(Object object, boolean stopOnShutdown) {
internalServiceManager.deferStartService(this, object, stopOnShutdown, false);
}
protected List getStartupListeners() {
return startupListeners;
}
@Override
public void addStartupListener(StartupListener listener) throws Exception {
// either add to listener so we can invoke then later when CamelContext
// has been started
// or invoke the callback right now
if (isStarted()) {
listener.onCamelContextStarted(this, true);
} else {
startupListeners.add(listener);
}
}
private static String toResourcePath(Package clazz, String languageName) {
String packageName = clazz.getName();
packageName = packageName.replace('.', '/');
return "META-INF/" + packageName + "/" + languageName + ".json";
}
private String doLoadResource(String resourceName, String path, String resourceType) throws IOException {
final ClassResolver resolver = getClassResolver();
try (InputStream inputStream = resolver.loadResourceAsStream(path)) {
LOG.debug("Loading {} JSON Schema for: {} using class resolver: {} -> {}", resourceType, resourceName, resolver,
inputStream);
if (inputStream != null) {
return IOHelper.loadText(inputStream);
}
}
return null;
}
@Override
public String getComponentParameterJsonSchema(String componentName) throws IOException {
// use the component factory finder to find the package name of the
// component class, which is the location
// where the documentation exists as well
FactoryFinder finder = camelContextExtension.getFactoryFinder(DefaultComponentResolver.RESOURCE_PATH);
Class> clazz = finder.findClass(componentName).orElse(null);
if (clazz == null) {
// fallback and find existing component
Component existing = hasComponent(componentName);
if (existing != null) {
clazz = existing.getClass();
} else {
return null;
}
}
String path = toResourcePath(clazz.getPackage(), componentName);
String inputStream = doLoadResource(componentName, path, "component");
if (inputStream != null) {
return inputStream;
}
return null;
}
@Override
public String getDataFormatParameterJsonSchema(String dataFormatName) throws IOException {
// use the dataformat factory finder to find the package name of the
// dataformat class, which is the location
// where the documentation exists as well
FactoryFinder finder = camelContextExtension.getFactoryFinder(DefaultDataFormatResolver.DATAFORMAT_RESOURCE_PATH);
Class> clazz = finder.findClass(dataFormatName).orElse(null);
if (clazz == null) {
return null;
}
String path = toResourcePath(clazz.getPackage(), dataFormatName);
String inputStream = doLoadResource(dataFormatName, path, "dataformat");
if (inputStream != null) {
return inputStream;
}
return null;
}
@Override
public String getLanguageParameterJsonSchema(String languageName) throws IOException {
// use the language factory finder to find the package name of the
// language class, which is the location
// where the documentation exists as well
FactoryFinder finder = camelContextExtension.getFactoryFinder(DefaultLanguageResolver.LANGUAGE_RESOURCE_PATH);
Class> clazz = finder.findClass(languageName).orElse(null);
if (clazz == null) {
return null;
}
String path = toResourcePath(clazz.getPackage(), languageName);
String inputStream = doLoadResource(languageName, path, "language");
if (inputStream != null) {
return inputStream;
}
return null;
}
@Override
public String getTransformerParameterJsonSchema(String transformerName) throws IOException {
String name = sanitizeFileName(transformerName) + ".json";
String path = DefaultTransformerResolver.DATA_TYPE_TRANSFORMER_RESOURCE_PATH + name;
String inputStream = doLoadResource(transformerName, path, "transformer");
if (inputStream != null) {
return inputStream;
}
return null;
}
@Override
public String getDevConsoleParameterJsonSchema(String devConsoleName) throws IOException {
String name = sanitizeFileName(devConsoleName) + ".json";
String path = DefaultDevConsoleResolver.DEV_CONSOLE_RESOURCE_PATH + name;
String inputStream = doLoadResource(devConsoleName, path, "console");
if (inputStream != null) {
return inputStream;
}
return null;
}
@Override
public String getPojoBeanParameterJsonSchema(String beanName) throws IOException {
String name = sanitizeFileName(beanName) + ".json";
String path = "META-INF/services/org/apache/camel/bean/" + name;
return doLoadResource(beanName, path, "bean");
}
// Helper methods
// -----------------------------------------------------------------------
private String sanitizeFileName(String fileName) {
return fileName.replaceAll("[^A-Za-z0-9-]", "-");
}
@Override
public String getEipParameterJsonSchema(String eipName) throws IOException {
// the eip json schema may be in some of the sub-packages so look until
// we find it
String[] subPackages = new String[] {
"", "cloud/", "config/", "dataformat/", "errorhandler/", "language/", "loadbalancer/", "rest/", "transformer/",
"validator/" };
for (String sub : subPackages) {
String path = CamelContextHelper.MODEL_DOCUMENTATION_PREFIX + sub + eipName + ".json";
String inputStream = doLoadResource(eipName, path, "eip");
if (inputStream != null) {
return inputStream;
}
}
return null;
}
@Override
public Language resolveLanguage(String name) {
LOG.debug("Resolving language: {}", name);
return languages.computeIfAbsent(name, s -> doResolveLanguage(name));
}
private Language doResolveLanguage(String name) {
final StartupStepRecorder startupStepRecorder = camelContextExtension.getStartupStepRecorder();
StartupStep step = null;
// only record startup step during startup (not started)
if (!isStarted() && startupStepRecorder.isEnabled()) {
step = startupStepRecorder.beginStep(Language.class, name, "Resolve Language");
}
final CamelContext camelContext = getCamelContextReference();
// as first iteration, check if there is a language instance for the given name
// bound to the registry
Language language = ResolverHelper.lookupLanguageInRegistryWithFallback(camelContext, name);
if (language == null) {
// language not known, then use resolver
language = PluginHelper.getLanguageResolver(camelContextExtension).resolveLanguage(name, camelContext);
}
if (language != null) {
if (language instanceof Service service) {
try {
// init service first
CamelContextAware.trySetCamelContext(service, camelContext);
ServiceHelper.initService(service);
startService(service);
} catch (Exception e) {
throw RuntimeCamelException.wrapRuntimeCamelException(e);
}
}
// inject CamelContext if aware
CamelContextAware.trySetCamelContext(language, camelContext);
for (LifecycleStrategy strategy : lifecycleStrategies) {
strategy.onLanguageCreated(name, language);
}
}
if (step != null) {
startupStepRecorder.endStep(step);
}
return language;
}
// Properties
// -----------------------------------------------------------------------
@Override
public String resolvePropertyPlaceholders(String text) {
return camelContextExtension.resolvePropertyPlaceholders(text, false);
}
@Override
public Object getVariable(String name) {
String id = StringHelper.before(name, ":", "global");
name = StringHelper.after(name, ":", name);
VariableRepository repo
= camelContextExtension.getContextPlugin(VariableRepositoryFactory.class).getVariableRepository(id);
if (repo != null) {
return repo.getVariable(name);
}
return null;
}
@Override
public T getVariable(String name, Class type) {
Object value = getVariable(name);
if (value != null) {
return getTypeConverter().convertTo(type, value);
}
return null;
}
@Override
public void setVariable(String name, Object value) {
String id = StringHelper.before(name, ":", "global");
name = StringHelper.after(name, ":", name);
VariableRepository repo
= camelContextExtension.getContextPlugin(VariableRepositoryFactory.class).getVariableRepository(id);
if (repo != null) {
repo.setVariable(name, value);
}
}
@Override
public TypeConverter getTypeConverter() {
return camelContextExtension.getTypeConverter();
}
@Override
public TypeConverterRegistry getTypeConverterRegistry() {
return camelContextExtension.getTypeConverterRegistry();
}
@Override
public void setTypeConverterRegistry(TypeConverterRegistry typeConverterRegistry) {
camelContextExtension.setTypeConverterRegistry(typeConverterRegistry);
}
@Override
public Injector getInjector() {
return camelContextExtension.getInjector();
}
@Override
public void setInjector(Injector injector) {
camelContextExtension.setInjector(injector);
}
@Override
public PropertiesComponent getPropertiesComponent() {
return camelContextExtension.getPropertiesComponent();
}
@Override
public void setPropertiesComponent(PropertiesComponent propertiesComponent) {
camelContextExtension.setPropertiesComponent(propertiesComponent);
}
public void setAutoCreateComponents(boolean autoCreateComponents) {
this.autoCreateComponents = autoCreateComponents;
}
@Override
public T getRegistry(Class type) {
Registry reg = camelContextExtension.getRegistry();
if (type.isAssignableFrom(reg.getClass())) {
return type.cast(reg);
}
return null;
}
@Override
public List getLifecycleStrategies() {
return lifecycleStrategies;
}
@Override
public void addLifecycleStrategy(LifecycleStrategy lifecycleStrategy) {
// ensure camel context is injected in factory
CamelContextAware.trySetCamelContext(lifecycleStrategy, this);
// avoid adding double which can happen with spring xml on spring boot
if (!getLifecycleStrategies().contains(lifecycleStrategy)) {
getLifecycleStrategies().add(lifecycleStrategy);
}
}
@Override
public RestConfiguration getRestConfiguration() {
return camelContextExtension.getRestConfiguration();
}
@Override
public void setRestConfiguration(RestConfiguration restConfiguration) {
camelContextExtension.setRestConfiguration(restConfiguration);
}
@Override
public VaultConfiguration getVaultConfiguration() {
return vaultConfiguration;
}
@Override
public void setVaultConfiguration(VaultConfiguration vaultConfiguration) {
this.vaultConfiguration = vaultConfiguration;
}
@Override
public List getRoutePolicyFactories() {
return routePolicyFactories;
}
@Override
public void addRoutePolicyFactory(RoutePolicyFactory routePolicyFactory) {
// ensure camel context is injected in factory
CamelContextAware.trySetCamelContext(routePolicyFactory, this);
// avoid adding double which can happen with spring xml on spring boot
if (!getRoutePolicyFactories().contains(routePolicyFactory)) {
getRoutePolicyFactories().add(routePolicyFactory);
}
}
@Override
public void setStreamCaching(Boolean cache) {
this.streamCache = cache;
}
@Override
public Boolean isStreamCaching() {
return streamCache;
}
@Override
public void setTracing(Boolean tracing) {
this.trace = tracing;
}
@Override
public Boolean isTracing() {
return trace;
}
@Override
public String getTracingPattern() {
return tracePattern;
}
@Override
public void setTracingPattern(String tracePattern) {
this.tracePattern = tracePattern;
}
@Override
public String getTracingLoggingFormat() {
return tracingLoggingFormat;
}
@Override
public void setTracingLoggingFormat(String format) {
this.tracingLoggingFormat = format;
}
@Override
public Boolean isBacklogTracing() {
return backlogTrace;
}
@Override
public void setBacklogTracing(Boolean backlogTrace) {
this.backlogTrace = backlogTrace;
}
@Override
public void setDebugging(Boolean debug) {
this.debug = debug;
}
@Override
public Boolean isDebugging() {
return debug;
}
@Override
public void setDebugStandby(boolean debugStandby) {
this.debugStandby = debugStandby;
}
@Override
public boolean isDebugStandby() {
return debugStandby != null && debugStandby;
}
public void setDebuggingBreakpoints(String debugBreakpoints) {
this.debugBreakpoints = debugBreakpoints;
}
public String getDebuggingBreakpoints() {
return debugBreakpoints;
}
@Override
public void setMessageHistory(Boolean messageHistory) {
this.messageHistory = messageHistory;
}
@Override
public Boolean isMessageHistory() {
return messageHistory;
}
@Override
public void setLogMask(Boolean logMask) {
this.logMask = logMask;
}
@Override
public Boolean isLogMask() {
return logMask != null && logMask;
}
@Override
public Boolean isLogExhaustedMessageBody() {
return logExhaustedMessageBody;
}
@Override
public void setLogExhaustedMessageBody(Boolean logExhaustedMessageBody) {
this.logExhaustedMessageBody = logExhaustedMessageBody;
}
@Override
public Long getDelayer() {
return delay;
}
@Override
public void setDelayer(Long delay) {
this.delay = delay;
}
@Override
public ProducerTemplate createProducerTemplate() {
return createProducerTemplate(0);
}
@Override
public ProducerTemplate createProducerTemplate(int maximumCacheSize) {
DefaultProducerTemplate answer = new DefaultProducerTemplate(getCamelContextReference());
answer.setMaximumCacheSize(maximumCacheSize);
// start it so its ready to use
try {
startService(answer);
} catch (Exception e) {
throw RuntimeCamelException.wrapRuntimeCamelException(e);
}
return answer;
}
@Override
public FluentProducerTemplate createFluentProducerTemplate() {
return createFluentProducerTemplate(0);
}
@Override
public FluentProducerTemplate createFluentProducerTemplate(int maximumCacheSize) {
DefaultFluentProducerTemplate answer = new DefaultFluentProducerTemplate(getCamelContextReference());
answer.setMaximumCacheSize(maximumCacheSize);
// start it so its ready to use
try {
startService(answer);
} catch (Exception e) {
throw RuntimeCamelException.wrapRuntimeCamelException(e);
}
return answer;
}
@Override
public ConsumerTemplate createConsumerTemplate() {
return createConsumerTemplate(0);
}
@Override
public ConsumerTemplate createConsumerTemplate(int maximumCacheSize) {
DefaultConsumerTemplate answer = new DefaultConsumerTemplate(getCamelContextReference());
answer.setMaximumCacheSize(maximumCacheSize);
// start it so its ready to use
try {
startService(answer);
} catch (Exception e) {
throw RuntimeCamelException.wrapRuntimeCamelException(e);
}
return answer;
}
protected ScheduledExecutorService createErrorHandlerExecutorService() {
return getExecutorServiceManager().newDefaultScheduledThreadPool("ErrorHandlerRedeliveryThreadPool",
"ErrorHandlerRedeliveryTask");
}
@Override
public RuntimeEndpointRegistry getRuntimeEndpointRegistry() {
return runtimeEndpointRegistry;
}
@Override
public void setRuntimeEndpointRegistry(RuntimeEndpointRegistry runtimeEndpointRegistry) {
this.runtimeEndpointRegistry = internalServiceManager.addService(this, runtimeEndpointRegistry);
}
@Override
public Duration getUptime() {
EventClock contextClock = getClock();
final Clock startClock = contextClock.get(ContextEvents.START);
if (startClock == null) {
return Duration.ZERO;
}
return startClock.asDuration();
}
@Override
public String getVersion() {
return VersionHolder.VERSION;
}
@Override
public EventClock getClock() {
return clock;
}
@Override
protected void doSuspend() throws Exception {
EventHelper.notifyCamelContextSuspending(this);
LOG.info("Apache Camel {} ({}) is suspending", getVersion(), camelContextExtension.getName());
StopWatch watch = new StopWatch();
// update list of started routes to be suspended
// because we only want to suspend started routes
// (so when we resume we only resume the routes which actually was
// suspended)
for (Map.Entry entry : getRouteServices().entrySet()) {
if (entry.getValue().getStatus().isStarted()) {
suspendedRouteServices.put(entry.getKey(), entry.getValue());
}
}
// assemble list of startup ordering so routes can be shutdown
// accordingly
List orders = new ArrayList<>();
for (Map.Entry entry : suspendedRouteServices.entrySet()) {
Route route = entry.getValue().getRoute();
Integer order = route.getStartupOrder();
if (order == null) {
order = internalRouteStartupManager.incrementRouteStartupOrder();
}
orders.add(new DefaultRouteStartupOrder(order, route, entry.getValue()));
}
// suspend routes using the shutdown strategy so it can shutdown in
// correct order
// routes which doesn't support suspension will be stopped instead
getShutdownStrategy().suspend(this, orders);
// mark the route services as suspended or stopped
for (RouteService service : suspendedRouteServices.values()) {
if (routeSupportsSuspension(service.getId())) {
service.suspend();
} else {
service.stop();
}
}
watch.taken();
if (LOG.isInfoEnabled()) {
LOG.info("Apache Camel {} ({}) is suspended in {}", getVersion(), camelContextExtension.getName(),
TimeUtils.printDuration(watch.taken(), true));
}
EventHelper.notifyCamelContextSuspended(this);
}
// Implementation methods
// -----------------------------------------------------------------------
@Override
protected void doResume() throws Exception {
try {
EventHelper.notifyCamelContextResuming(this);
LOG.info("Apache Camel {} ({}) is resuming", getVersion(), camelContextExtension.getName());
StopWatch watch = new StopWatch();
// start the suspended routes (do not check for route clashes, and
// indicate)
internalRouteStartupManager.doStartOrResumeRoutes(this, suspendedRouteServices, false, true, true, false);
// mark the route services as resumed (will be marked as started) as
// well
for (RouteService service : suspendedRouteServices.values()) {
if (routeSupportsSuspension(service.getId())) {
service.resume();
} else {
service.start();
}
}
if (LOG.isInfoEnabled()) {
LOG.info("Resumed {} routes", suspendedRouteServices.size());
LOG.info("Apache Camel {} ({}) resumed in {}", getVersion(), camelContextExtension.getName(),
TimeUtils.printDuration(watch.taken(), true));
}
// and clear the list as they have been resumed
suspendedRouteServices.clear();
EventHelper.notifyCamelContextResumed(this);
} catch (Exception e) {
EventHelper.notifyCamelContextResumeFailed(this, e);
throw e;
}
}
@Override
protected AutoCloseable doLifecycleChange() {
return new LifecycleHelper();
}
@Override
public void init() {
try {
super.init();
} catch (RuntimeCamelException e) {
if (e.getCause() instanceof VetoCamelContextStartException veto) {
vetoed = veto;
} else {
throw e;
}
}
// was the initialization vetoed?
if (vetoed != null) {
LOG.warn("CamelContext ({}) vetoed to not initialize due to: {}", camelContextExtension.getName(),
vetoed.getMessage());
failOnStartup(vetoed);
}
}
@Override
public void start() {
super.start();
//
// We need to perform the following actions after the {@link #start()} method
// is called, so that the state of the {@link CamelContext} is Started.
//
// did the start veto?
if (vetoed != null) {
LOG.warn("CamelContext ({}) vetoed to not start due to: {}", camelContextExtension.getName(), vetoed.getMessage());
failOnStartup(vetoed);
stop();
return;
}
for (LifecycleStrategy strategy : lifecycleStrategies) {
try {
strategy.onContextStarted(this);
} catch (Exception e) {
LOG.warn("Lifecycle strategy {} failed on CamelContext ({}) due to: {}. This exception will be ignored",
strategy,
camelContextExtension.getName(),
e.getMessage());
}
}
// okay the routes has been started so emit event that CamelContext
// has started (here at the end)
EventHelper.notifyCamelContextStarted(this);
// now call the startup listeners where the routes has been started
for (StartupListener startup : startupListeners) {
try {
startup.onCamelContextFullyStarted(this, isStarted());
} catch (Exception e) {
throw RuntimeCamelException.wrapRuntimeException(e);
}
}
}
@Override
public void stop() {
for (LifecycleStrategy strategy : lifecycleStrategies) {
try {
strategy.onContextStopping(this);
} catch (Exception e) {
LOG.warn("Lifecycle strategy {} failed on CamelContext ({}) due to: {}. This exception will be ignored",
strategy,
camelContextExtension.getName(),
e.getMessage());
}
}
super.stop();
}
@Override
public void doBuild() throws Exception {
final StopWatch watch = new StopWatch();
getCamelContextExtension().addContextPlugin(NodeIdFactory.class, createNodeIdFactory());
// auto-detect step recorder from classpath if none has been explicit configured
StartupStepRecorder startupStepRecorder = camelContextExtension.getStartupStepRecorder();
if (startupStepRecorder.getClass().getSimpleName().equals("DefaultStartupStepRecorder")) {
StartupStepRecorder fr = camelContextExtension.getBootstrapFactoryFinder()
.newInstance(StartupStepRecorder.FACTORY, StartupStepRecorder.class).orElse(null);
if (fr != null) {
LOG.debug("Discovered startup recorder: {} from classpath", fr);
camelContextExtension.setStartupStepRecorder(fr);
startupStepRecorder = fr;
}
}
startupStepRecorder.start();
StartupStep step = startupStepRecorder.beginStep(CamelContext.class, null, "Build CamelContext");
// Initialize LRUCacheFactory as eager as possible,
// to let it warm up concurrently while Camel is startup up
StartupStep subStep = startupStepRecorder.beginStep(CamelContext.class, null, "Setup LRUCacheFactory");
LRUCacheFactory.init();
startupStepRecorder.endStep(subStep);
// Setup management first since end users may use it to add event
// notifiers using the management strategy before the CamelContext has been started
StartupStep step3 = startupStepRecorder.beginStep(CamelContext.class, null, "Setup Management");
camelContextExtension.setupManagement(null);
startupStepRecorder.endStep(step3);
// setup health-check registry as its needed this early phase for 3rd party to register custom repositories
HealthCheckRegistry hcr = getCamelContextExtension().getContextPlugin(HealthCheckRegistry.class);
if (hcr == null) {
StartupStep step4 = startupStepRecorder.beginStep(CamelContext.class, null, "Setup HealthCheckRegistry");
hcr = createHealthCheckRegistry();
if (hcr != null) {
// install health-check registry if it was discovered from classpath (camel-health)
hcr.setCamelContext(this);
getCamelContextExtension().addContextPlugin(HealthCheckRegistry.class, hcr);
}
startupStepRecorder.endStep(step4);
}
// setup dev-console registry as its needed this early phase for 3rd party to register custom consoles
DevConsoleRegistry dcr = getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class);
if (dcr == null) {
StartupStep step5 = startupStepRecorder.beginStep(CamelContext.class, null, "Setup DevConsoleRegistry");
dcr = createDevConsoleRegistry();
if (dcr != null) {
// install dev-console registry if it was discovered from classpath (camel-console)
dcr.setCamelContext(this);
getCamelContextExtension().addContextPlugin(DevConsoleRegistry.class, dcr);
}
startupStepRecorder.endStep(step5);
}
// Call all registered trackers with this context
// Note, this may use a partially constructed object
CamelContextTracker.notifyContextCreated(this);
// Setup type converter eager as its highly in use and should not be lazy initialized
if (eagerCreateTypeConverter()) {
StartupStep step5 = startupStepRecorder.beginStep(CamelContext.class, null, "Setting up TypeConverter");
camelContextExtension.getOrCreateTypeConverter();
startupStepRecorder.endStep(step5);
}
startupStepRecorder.endStep(step);
if (LOG.isDebugEnabled()) {
buildTaken = watch.taken();
LOG.debug("Apache Camel {} ({}) built in {}", getVersion(), camelContextExtension.getName(),
TimeUtils.printDuration(buildTaken, true));
}
}
/**
* Internal API to reset build time. Used by quarkus.
*/
@SuppressWarnings("unused")
protected void resetBuildTime() {
// needed by camel-quarkus
buildTaken = 0;
}
@Override
public void doInit() throws Exception {
final StopWatch watch = new StopWatch();
vetoed = null;
final StartupStepRecorder startupStepRecorder = camelContextExtension.getStartupStepRecorder();
StartupStep step = startupStepRecorder.beginStep(CamelContext.class, null, "Init CamelContext");
// init the route controller
final RouteController routeController = getRouteController();
if (startupSummaryLevel == StartupSummaryLevel.Verbose) {
// verbose startup should let route controller do the route startup logging
if (routeController.getLoggingLevel().ordinal() < LoggingLevel.INFO.ordinal()) {
routeController.setLoggingLevel(LoggingLevel.INFO);
}
}
// init the shutdown strategy
final ShutdownStrategy shutdownStrategy = getShutdownStrategy();
if (startupSummaryLevel == StartupSummaryLevel.Verbose) {
// verbose startup should let route controller do the route shutdown logging
if (shutdownStrategy != null && shutdownStrategy.getLoggingLevel().ordinal() < LoggingLevel.INFO.ordinal()) {
shutdownStrategy.setLoggingLevel(LoggingLevel.INFO);
}
}
// optimize - before starting routes lets check if event notifications are possible
camelContextExtension.setEventNotificationApplicable(EventHelper.eventsApplicable(this));
// ensure additional type converters is loaded (either if enabled or we should use package scanning from the base)
boolean load = loadTypeConverters || camelContextExtension.getBasePackageScan() != null;
final TypeConverter typeConverter = camelContextExtension.getTypeConverter();
if (load && typeConverter instanceof AnnotationScanTypeConverters annotationScanTypeConverters) {
StartupStep step2 = startupStepRecorder.beginStep(CamelContext.class, null, "Scan TypeConverters");
annotationScanTypeConverters.scanTypeConverters();
startupStepRecorder.endStep(step2);
}
// ensure additional health checks is loaded
if (loadHealthChecks) {
StartupStep step3 = startupStepRecorder.beginStep(CamelContext.class, null, "Scan HealthChecks");
HealthCheckRegistry hcr = getCamelContextExtension().getContextPlugin(HealthCheckRegistry.class);
if (hcr != null) {
hcr.loadHealthChecks();
}
startupStepRecorder.endStep(step3);
}
// ensure additional dev consoles is loaded
if (devConsole) {
StartupStep step4 = startupStepRecorder.beginStep(CamelContext.class, null, "Scan DevConsoles (phase 1)");
DevConsoleRegistry dcr = getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class);
if (dcr != null) {
dcr.loadDevConsoles();
}
startupStepRecorder.endStep(step4);
}
// custom properties may use property placeholders so resolve those
// early on
if (globalOptions != null && !globalOptions.isEmpty()) {
for (Map.Entry entry : globalOptions.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
if (value != null) {
String replaced = resolvePropertyPlaceholders(value);
if (!value.equals(replaced)) {
if (LOG.isDebugEnabled()) {
LOG.debug("Camel property with key {} replaced value from {} -> {}", key, value, replaced);
}
entry.setValue(replaced);
}
}
}
}
forceLazyInitialization();
// setup cli-connector if not already done
if (hasService(CliConnector.class) == null) {
CliConnectorFactory ccf = getCamelContextExtension().getContextPlugin(CliConnectorFactory.class);
if (ccf != null && ccf.isEnabled()) {
CliConnector connector = ccf.createConnector();
addService(connector, true);
// force start cli connector early as otherwise it will be deferred until context is started
// but, we want status available during startup phase
ServiceHelper.startService(connector);
}
}
// auto-detect camel-debug on classpath (if debugger has not been explicit added)
boolean debuggerDetected = false;
if (getDebugger() == null && hasService(BacklogDebugger.class) == null) {
// detect if camel-debug is on classpath that enables debugging
DebuggerFactory df = getCamelContextExtension().getBootstrapFactoryFinder()
.newInstance(Debugger.FACTORY, DebuggerFactory.class).orElse(null);
if (df != null) {
debuggerDetected = true;
LOG.info("Detected: {} JAR (Enabling Camel Debugging)", df);
setDebugging(true);
Debugger newDebugger = df.createDebugger(this);
if (newDebugger != null) {
setDebugger(newDebugger);
}
}
}
if (!debuggerDetected && (isDebugging() || isDebugStandby())) {
if (hasService(BacklogDebugger.class) == null) {
// debugging enabled but camel-debug was not auto-detected from classpath
// so install default debugger
BacklogDebugger backlog = DefaultBacklogDebugger.createDebugger(this);
addService(backlog, true, true);
}
}
addService(getManagementStrategy(), false);
// check startup conditions before we can continue
StartupConditionStrategy scs = getCamelContextExtension().getContextPlugin(StartupConditionStrategy.class);
scs.checkStartupConditions();
lifecycleStrategies.sort(OrderedComparator.get());
ServiceHelper.initService(lifecycleStrategies);
for (LifecycleStrategy strategy : lifecycleStrategies) {
try {
strategy.onContextInitializing(this);
} catch (VetoCamelContextStartException e) {
// okay we should not start Camel since it was vetoed
LOG.warn("Lifecycle strategy {} vetoed initializing CamelContext ({}) due to: {}", strategy,
camelContextExtension.getName(),
e.getMessage());
throw e;
} catch (Exception e) {
LOG.warn("Lifecycle strategy {} failed initializing CamelContext ({}) due to: {}", strategy,
camelContextExtension.getName(),
e.getMessage());
throw e;
}
}
// optimize - before starting routes lets check if event notifications are possible
camelContextExtension.setEventNotificationApplicable(EventHelper.eventsApplicable(this));
// start notifiers as services
for (EventNotifier notifier : getManagementStrategy().getEventNotifiers()) {
if (notifier instanceof Service service) {
for (LifecycleStrategy strategy : lifecycleStrategies) {
strategy.onServiceAdd(getCamelContextReference(), service, null);
}
}
ServiceHelper.initService(notifier);
}
// the event notifiers must be initialized before we can emit this event
EventHelper.notifyCamelContextInitializing(this);
// re-create endpoint registry as the cache size limit may be set after the constructor of this instance was called.
// and we needed to create endpoints up-front as it may be accessed before this context is started
endpoints = internalServiceManager.addService(this, createEndpointRegistry(endpoints));
// optimised to not include runtimeEndpointRegistry unless startServices
// is enabled or JMX statistics is in extended mode
if (runtimeEndpointRegistry == null && getManagementStrategy() != null
&& getManagementStrategy().getManagementAgent() != null) {
Boolean isEnabled = getManagementStrategy().getManagementAgent().getEndpointRuntimeStatisticsEnabled();
boolean isExtended = getManagementStrategy().getManagementAgent().getStatisticsLevel().isExtended();
// extended mode is either if we use Extended statistics level or
// the option is explicit enabled
boolean extended = isExtended || isEnabled != null && isEnabled;
if (extended) {
runtimeEndpointRegistry = new DefaultRuntimeEndpointRegistry();
}
}
if (runtimeEndpointRegistry != null) {
if (runtimeEndpointRegistry instanceof EventNotifier && getManagementStrategy() != null) {
getManagementStrategy().addEventNotifier((EventNotifier) runtimeEndpointRegistry);
}
addService(runtimeEndpointRegistry, true, true);
}
bindDataFormats();
// init components
ServiceHelper.initService(components.values());
// create route definitions from route templates if we have any sources
for (RouteTemplateParameterSource source : camelContextExtension.getRegistry()
.findByType(RouteTemplateParameterSource.class)) {
for (String routeId : source.routeIds()) {
// do a defensive copy of the parameters
Map map = new HashMap<>(source.parameters(routeId));
Object templateId = map.remove(RouteTemplateParameterSource.TEMPLATE_ID);
if (templateId == null) {
// use alternative style as well
templateId = map.remove("template-id");
}
final String id = templateId != null ? templateId.toString() : null;
if (id == null) {
throw new IllegalArgumentException(
"RouteTemplateParameterSource with routeId: " + routeId + " has no templateId defined");
}
addRouteFromTemplate(routeId, id, map);
}
}
// init the route definitions before the routes is started
StartupStep subStep = startupStepRecorder.beginStep(CamelContext.class, camelContextExtension.getName(), "Init Routes");
// the method is called start but at this point it will only initialize (as context is starting up)
startRouteDefinitions();
// this will init route definitions and populate as route services which we can then initialize now
internalRouteStartupManager.doInitRoutes(this, routeServices);
startupStepRecorder.endStep(subStep);
if (!lifecycleStrategies.isEmpty()) {
subStep = startupStepRecorder.beginStep(CamelContext.class, camelContextExtension.getName(),
"LifecycleStrategy onContextInitialized");
for (LifecycleStrategy strategy : lifecycleStrategies) {
try {
strategy.onContextInitialized(this);
} catch (VetoCamelContextStartException e) {
// okay we should not start Camel since it was vetoed
LOG.warn("Lifecycle strategy {} vetoed initializing CamelContext ({}) due to: {}", strategy,
camelContextExtension.getName(),
e.getMessage());
throw e;
} catch (Exception e) {
LOG.warn("Lifecycle strategy {} failed initializing CamelContext ({}) due to: {}", strategy,
camelContextExtension.getName(),
e.getMessage());
throw e;
}
}
startupStepRecorder.endStep(subStep);
}
EventHelper.notifyCamelContextInitialized(this);
startupStepRecorder.endStep(step);
if (LOG.isDebugEnabled()) {
initTaken = watch.taken();
LOG.debug("Apache Camel {} ({}) initialized in {}", getVersion(), camelContextExtension.getName(),
TimeUtils.printDuration(initTaken, true));
}
}
@Override
protected void doStart() throws Exception {
if (firstStartDone) {
// its not good practice resetting a camel context
LOG.warn("Starting CamelContext: {} after the context has been stopped is not recommended",
camelContextExtension.getName());
}
final StartupStepRecorder startupStepRecorder = camelContextExtension.getStartupStepRecorder();
StartupStep step
= startupStepRecorder.beginStep(CamelContext.class, camelContextExtension.getName(), "Start CamelContext");
try {
doStartContext();
} catch (Exception e) {
// fire event that we failed to start
EventHelper.notifyCamelContextStartupFailed(this, e);
// rethrow cause
throw e;
}
startupStepRecorder.endStep(step);
// if we should only record the startup process then stop it right after started
if (startupStepRecorder.getStartupRecorderDuration() < 0) {
startupStepRecorder.stop();
}
}
protected void doStartContext() throws Exception {
LOG.info("Apache Camel {} ({}) is starting", getVersion(), camelContextExtension.getName());
vetoed = null;
clock.add(ContextEvents.START, new ResetableClock());
stopWatch.restart();
// Start the route controller
startService(camelContextExtension.getRouteController());
doNotStartRoutesOnFirstStart = !firstStartDone && !isAutoStartup();
// if the context was configured with auto startup = false, and we
// are already started,
// then we may need to start the routes on the 2nd start call
if (firstStartDone && !isAutoStartup() && isStarted()) {
// invoke this logic to warm up the routes and if possible also
// start the routes
try {
internalRouteStartupManager.doStartOrResumeRoutes(this, routeServices, true, true, false, true);
} catch (Exception e) {
throw RuntimeCamelException.wrapRuntimeException(e);
}
}
// super will invoke doStart which will prepare internal services
// and start routes etc.
try {
firstStartDone = true;
doStartCamel();
} catch (Exception e) {
VetoCamelContextStartException veto = ObjectHelper.getException(VetoCamelContextStartException.class, e);
if (veto != null) {
// mark we veto against starting Camel
vetoed = veto;
return;
} else {
LOG.error("Error starting CamelContext ({}) due to exception thrown: {}", camelContextExtension.getName(),
e.getMessage(), e);
throw RuntimeCamelException.wrapRuntimeException(e);
}
}
// duplicate components in use?
logDuplicateComponents();
// log startup summary
logStartSummary();
// now Camel has been started/bootstrap is complete, then run cleanup to help free up memory etc
camelContextExtension.closeBootstraps();
if (camelContextExtension.getExchangeFactory().isPooled()) {
LOG.info(
"Pooled mode enabled. Camel pools and reuses objects to reduce JVM object allocations. The pool capacity is: {} elements.",
camelContextExtension.getExchangeFactory().getCapacity());
}
}
protected void logDuplicateComponents() {
// output how many instances of the same component class are in use, as multiple instances is potential a mistake
if (LOG.isInfoEnabled()) {
Map, Set> counters = new LinkedHashMap<>();
// use TreeSet to sort the names
Set cnames = new TreeSet<>(getComponentNames());
for (String sourceName : cnames) {
Class> source = getComponent(sourceName).getClass();
if (!counters.containsKey(source)) {
for (String targetName : cnames) {
Class> target = getComponent(targetName).getClass();
if (source == target) {
Set names = counters.computeIfAbsent(source, k -> new TreeSet<>());
names.add(targetName);
}
}
}
}
for (Map.Entry, Set> entry : counters.entrySet()) {
int count = entry.getValue().size();
if (count > 1) {
String fqn = entry.getKey().getName();
String names = String.join(", ", entry.getValue());
LOG.info("Using {} instances of same component class: {} with names: {}", count,
fqn, names);
}
}
}
}
protected void logStartSummary() {
// supervising route controller should do their own startup log summary
boolean supervised = getRouteController().isSupervising();
if (!supervised && startupSummaryLevel != StartupSummaryLevel.Oneline && startupSummaryLevel != StartupSummaryLevel.Off
&& LOG.isInfoEnabled()) {
int started = 0;
int total = 0;
int kamelets = 0;
int templates = 0;
int rests = 0;
int disabled = 0;
boolean registerKamelets = false;
boolean registerTemplates = true;
ManagementStrategy ms = getManagementStrategy();
if (ms != null && ms.getManagementAgent() != null) {
registerKamelets = ms.getManagementAgent().getRegisterRoutesCreateByKamelet();
registerTemplates = ms.getManagementAgent().getRegisterRoutesCreateByTemplate();
}
List lines = new ArrayList<>();
List configs = new ArrayList<>();
routeStartupOrder.sort(Comparator.comparingInt(RouteStartupOrder::getStartupOrder));
for (RouteStartupOrder order : routeStartupOrder) {
total++;
String id = order.getRoute().getRouteId();
String status = getRouteStatus(id).name();
if (order.getRoute().isCreatedByKamelet()) {
kamelets++;
} else if (order.getRoute().isCreatedByRouteTemplate()) {
templates++;
} else if (order.getRoute().isCreatedByRestDsl()) {
rests++;
}
boolean skip = (!registerKamelets && order.getRoute().isCreatedByKamelet())
|| (!registerTemplates && order.getRoute().isCreatedByRouteTemplate());
if (!skip && ServiceStatus.Started.name().equals(status)) {
started++;
}
// use basic endpoint uri to not log verbose details or potential sensitive data
String uri = order.getRoute().getEndpoint().getEndpointBaseUri();
uri = URISupport.sanitizeUri(uri);
String loc = order.getRoute().getSourceLocationShort();
if (startupSummaryLevel == StartupSummaryLevel.Verbose && loc != null) {
lines.add(String.format(" %s %s (%s) (source: %s)", status, id, uri, loc));
} else {
if (!skip) {
lines.add(String.format(" %s %s (%s)", status, id, uri));
}
}
String cid = order.getRoute().getConfigurationId();
if (cid != null) {
configs.add(String.format(" %s (%s)", id, cid));
}
}
for (Route route : routes) {
if (!route.isAutoStartup()) {
total++;
disabled++;
String id = route.getRouteId();
String status = getRouteStatus(id).name();
if (ServiceStatus.Stopped.name().equals(status)) {
status = "Disabled";
}
if (route.isCreatedByKamelet()) {
kamelets++;
} else if (route.isCreatedByRouteTemplate()) {
templates++;
} else if (route.isCreatedByRestDsl()) {
rests++;
}
boolean skip = (!registerKamelets && route.isCreatedByKamelet())
|| (!registerTemplates && route.isCreatedByRouteTemplate());
// use basic endpoint uri to not log verbose details or potential sensitive data
String uri = route.getEndpoint().getEndpointBaseUri();
uri = URISupport.sanitizeUri(uri);
String loc = route.getSourceLocationShort();
if (startupSummaryLevel == StartupSummaryLevel.Verbose && loc != null) {
lines.add(String.format(" %s %s (%s) (source: %s)", status, id, uri, loc));
} else {
if (!skip) {
lines.add(String.format(" %s %s (%s)", status, id, uri));
}
}
String cid = route.getConfigurationId();
if (cid != null) {
configs.add(String.format(" %s (%s)", id, cid));
}
}
}
int newTotal = total;
if (!registerKamelets) {
newTotal -= kamelets;
}
if (!registerTemplates) {
newTotal -= templates;
}
StringJoiner sj = new StringJoiner(" ");
sj.add("total:" + newTotal);
if (total != started) {
sj.add("started:" + started);
}
if (kamelets > 0) {
sj.add("kamelets:" + kamelets);
}
if (templates > 0) {
sj.add("templates:" + templates);
}
if (rests > 0) {
sj.add("rest-dsl:" + rests);
}
if (disabled > 0) {
sj.add("disabled:" + disabled);
}
LOG.info("Routes startup ({})", sj);
// if we are default/verbose then log each route line
if (startupSummaryLevel == StartupSummaryLevel.Default || startupSummaryLevel == StartupSummaryLevel.Verbose) {
for (String line : lines) {
LOG.info(line);
}
if (startupSummaryLevel == StartupSummaryLevel.Verbose && !configs.isEmpty()) {
LOG.info("Routes configuration:");
for (String line : configs) {
LOG.info(line);
}
}
}
}
if (startupSummaryLevel != StartupSummaryLevel.Off && LOG.isInfoEnabled()) {
long taken = stopWatch.taken();
long max = buildTaken + initTaken + taken;
String total = TimeUtils.printDuration(max, true);
String start = TimeUtils.printDuration(taken, true);
String init = TimeUtils.printDuration(initTaken, true);
String built = TimeUtils.printDuration(buildTaken, true);
String boot = null;
Clock bc = getClock().get(ContextEvents.BOOT);
if (bc != null) {
// calculate boot time as time before camel is starting
long delta = bc.elapsed() - max;
if (delta > 0) {
boot = TimeUtils.printDuration(delta, true);
}
}
String msg = String.format("Apache Camel %s (%s) started in %s (build:%s init:%s start:%s", getVersion(),
camelContextExtension.getName(), total, built, init, start);
if (boot != null) {
msg += " boot:" + boot;
}
msg += ")";
LOG.info(msg);
}
}
protected void doStartCamel() throws Exception {
if (!camelContextExtension.getContextPlugin(CamelBeanPostProcessor.class).isEnabled()) {
LOG.info("BeanPostProcessor is disabled. Dependency injection of Camel annotations in beans is not supported.");
}
if (LOG.isDebugEnabled()) {
LOG.debug(
"Using ClassResolver={}, PackageScanClassResolver={}, ApplicationContextClassLoader={}, RouteController={}",
getClassResolver(),
PluginHelper.getPackageScanClassResolver(camelContextExtension), getApplicationContextClassLoader(),
getRouteController());
}
if (isStreamCaching()) {
// stream caching is default enabled so lets report if it has been disabled
LOG.debug("StreamCaching is disabled on CamelContext: {}", camelContextExtension.getName());
}
if (isBacklogTracing()) {
// tracing is added in the DefaultChannel so we can enable it on the fly
LOG.debug("Backlog Tracing is enabled on CamelContext: {}", camelContextExtension.getName());
}
if (isTracing()) {
// tracing is added in the DefaultChannel so we can enable it on the fly
LOG.info("Tracing is enabled on CamelContext: {}", camelContextExtension.getName());
}
if (isUseMDCLogging()) {
// log if MDC has been enabled
String pattern = getMDCLoggingKeysPattern();
if (pattern != null) {
LOG.info("MDC logging (keys-pattern: {}) is enabled on CamelContext: {}", pattern,
camelContextExtension.getName());
} else {
LOG.info("MDC logging is enabled on CamelContext: {}", camelContextExtension.getName());
}
}
if (getDelayer() != null && getDelayer() > 0) {
LOG.info("Delayer is enabled with: {} ms. on CamelContext: {}", getDelayer(), camelContextExtension.getName());
}
// start management strategy before lifecycles are started
startService(getManagementStrategy());
// start lifecycle strategies
final StartupStepRecorder startupStepRecorder = camelContextExtension.getStartupStepRecorder();
if (!lifecycleStrategies.isEmpty()) {
StartupStep subStep
= startupStepRecorder.beginStep(CamelContext.class, camelContextExtension.getName(),
"LifecycleStrategy onContextStarting");
startServices(lifecycleStrategies);
for (LifecycleStrategy strategy : lifecycleStrategies) {
try {
strategy.onContextStarting(this);
} catch (VetoCamelContextStartException e) {
// okay we should not start Camel since it was vetoed
LOG.warn("Lifecycle strategy {} vetoed starting CamelContext ({}) due to: {}", strategy,
camelContextExtension.getName(),
e.getMessage());
throw e;
} catch (Exception e) {
LOG.warn("Lifecycle strategy {} failed starting CamelContext ({}) due to: {}", strategy,
camelContextExtension.getName(),
e.getMessage());
throw e;
}
}
startupStepRecorder.endStep(subStep);
}
// start log listeners
ServiceHelper.startService(getCamelContextExtension().getLogListeners());
// ensure components are started
for (Map.Entry entry : components.entrySet()) {
StartupStep step = startupStepRecorder.beginStep(Component.class, entry.getKey(), "Start Component");
try {
startService(entry.getValue());
} catch (Exception e) {
throw new FailedToStartComponentException(entry.getKey(), e.getMessage(), e);
} finally {
startupStepRecorder.endStep(step);
}
}
if (!startupListeners.isEmpty()) {
StartupStep subStep
= startupStepRecorder.beginStep(CamelContext.class, camelContextExtension.getName(),
"StartupListener onCamelContextStarting");
// sort the startup listeners so they are started in the right order
startupListeners.sort(OrderedComparator.get());
// now call the startup listeners where the routes has been warmed up
// (only the actual route consumer has not yet been started)
for (StartupListener startup : startupListeners) {
startup.onCamelContextStarting(getCamelContextReference(), isStarted());
}
startupStepRecorder.endStep(subStep);
}
// start notifiers as services
for (EventNotifier notifier : getManagementStrategy().getEventNotifiers()) {
if (notifier instanceof Service service) {
startService(service);
}
}
// must let some bootstrap service be started before we can notify the starting event
EventHelper.notifyCamelContextStarting(this);
if (isUseDataType()) {
// log if DataType has been enabled
LOG.debug("Message DataType is enabled on CamelContext: {}", camelContextExtension.getName());
}
// is there any stream caching enabled then log an info about this and
// its limit of spooling to disk, so people is aware of this
if (isStreamCachingInUse()) {
// stream caching is in use so enable the strategy
getStreamCachingStrategy().setEnabled(true);
} else {
// log if stream caching is not in use as this can help people to
// enable it if they use streams
LOG.debug("StreamCaching is not in use. If using streams then it's recommended to enable stream caching."
+ " See more details at https://camel.apache.org/stream-caching.html");
}
if (isAllowUseOriginalMessage()) {
LOG.debug("AllowUseOriginalMessage enabled because UseOriginalMessage is in use");
}
LOG.debug("Using HeadersMapFactory: {}", camelContextExtension.getHeadersMapFactory());
if (isCaseInsensitiveHeaders() && !camelContextExtension.getHeadersMapFactory().isCaseInsensitive()) {
LOG.info(
"HeadersMapFactory: {} is case-sensitive which can cause problems for protocols such as HTTP based, which rely on case-insensitive headers.",
camelContextExtension.getHeadersMapFactory());
} else if (!isCaseInsensitiveHeaders()) {
// notify user that the headers are sensitive which can be a problem
LOG.info(
"Case-insensitive headers is not in use. This can cause problems for protocols such as HTTP based, which rely on case-insensitive headers.");
}
// lets log at INFO level if we are not using the default reactive executor
final ReactiveExecutor reactiveExecutor = camelContextExtension.getReactiveExecutor();
if (!reactiveExecutor.getClass().getSimpleName().equals("DefaultReactiveExecutor")) {
LOG.info("Using ReactiveExecutor: {}", reactiveExecutor);
} else {
LOG.debug("Using ReactiveExecutor: {}", reactiveExecutor);
}
// lets log at INFO level if we are not using the default thread pool factory
if (!getExecutorServiceManager().getThreadPoolFactory().getClass().getSimpleName().equals("DefaultThreadPoolFactory")) {
LOG.info("Using ThreadPoolFactory: {}", getExecutorServiceManager().getThreadPoolFactory());
} else {
LOG.debug("Using ThreadPoolFactory: {}", getExecutorServiceManager().getThreadPoolFactory());
}
HealthCheckRegistry hcr = getCamelContextExtension().getContextPlugin(HealthCheckRegistry.class);
if (hcr != null && hcr.isEnabled()) {
LOG.debug("Using HealthCheck: {}", hcr.getId());
}
// start routes
if (doNotStartRoutesOnFirstStart) {
LOG.debug("Skip starting routes as CamelContext has been configured with autoStartup=false");
}
if (getDumpRoutes() != null && !"false".equals(getDumpRoutes())) {
doDumpRoutes();
}
if (!getRouteController().isSupervising()) {
// invoke this logic to warmup the routes and if possible also start the routes (using default route controller)
StartupStep subStep
= startupStepRecorder.beginStep(CamelContext.class, camelContextExtension.getName(), "Start Routes");
EventHelper.notifyCamelContextRoutesStarting(this);
internalRouteStartupManager.doStartOrResumeRoutes(this, routeServices, true, !doNotStartRoutesOnFirstStart, false,
true);
EventHelper.notifyCamelContextRoutesStarted(this);
startupStepRecorder.endStep(subStep);
}
// ensure extra dev consoles is loaded in case additional JARs has been dynamically added to the classpath
if (devConsole) {
StartupStep step = startupStepRecorder.beginStep(CamelContext.class, null, "Scan DevConsoles (phase 2)");
DevConsoleRegistry dcr = getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class);
if (dcr != null) {
dcr.loadDevConsoles(true);
}
startupStepRecorder.endStep(step);
}
final BeanIntrospection beanIntrospection = PluginHelper.getBeanIntrospection(this);
long cacheCounter = beanIntrospection != null ? beanIntrospection.getCachedClassesCounter() : 0;
if (cacheCounter > 0) {
LOG.debug("Clearing BeanIntrospection cache with {} objects using during starting Camel", cacheCounter);
beanIntrospection.clearCache();
}
long invokedCounter = beanIntrospection != null ? beanIntrospection.getInvokedCounter() : 0;
if (invokedCounter > 0) {
LOG.debug("BeanIntrospection invoked {} times during starting Camel", invokedCounter);
}
// starting will continue in the start method
}
@Override
protected void doStop() throws Exception {
stopWatch.restart();
final ShutdownStrategy shutdownStrategy = getShutdownStrategy();
if (startupSummaryLevel != StartupSummaryLevel.Oneline && startupSummaryLevel != StartupSummaryLevel.Off) {
if (shutdownStrategy != null && shutdownStrategy.getTimeUnit() != null) {
long timeout = shutdownStrategy.getTimeUnit().toMillis(shutdownStrategy.getTimeout());
// only use precise print duration if timeout is shorter than 10 seconds
String to = TimeUtils.printDuration(timeout, timeout < 10000);
LOG.info("Apache Camel {} ({}) is shutting down (timeout:{})", getVersion(), camelContextExtension.getName(),
to);
} else {
LOG.info("Apache Camel {} ({}) is shutting down", getVersion(), camelContextExtension.getName());
}
}
EventHelper.notifyCamelContextStopping(this);
EventHelper.notifyCamelContextRoutesStopping(this);
// Stop the route controller
camelContextExtension.stopAndShutdownRouteController();
// stop route inputs in the same order as they were started, so we stop
// the very first inputs at first
try {
// force shutting down routes as they may otherwise cause shutdown to hang
if (shutdownStrategy != null) {
shutdownStrategy.shutdownForced(this, camelContextExtension.getRouteStartupOrder());
}
} catch (Exception e) {
LOG.warn("Error occurred while shutting down routes. This exception will be ignored.", e);
}
// shutdown await manager to trigger interrupt of blocked threads to
// attempt to free these threads graceful
final AsyncProcessorAwaitManager asyncProcessorAwaitManager = PluginHelper.getAsyncProcessorAwaitManager(this);
InternalServiceManager.shutdownServices(this, asyncProcessorAwaitManager);
// we need also to include routes which failed to start to ensure all resources get stopped when stopping Camel
for (RouteService routeService : routeServices.values()) {
boolean found = routeStartupOrder.stream().anyMatch(o -> o.getRoute().getId().equals(routeService.getId()));
if (!found) {
LOG.debug("Route: {} which failed to startup will be stopped", routeService.getId());
routeStartupOrder.add(internalRouteStartupManager.doPrepareRouteToBeStarted(this, routeService));
}
}
routeStartupOrder.sort(Comparator.comparingInt(RouteStartupOrder::getStartupOrder).reversed());
List list = new ArrayList<>();
for (RouteStartupOrder startupOrder : routeStartupOrder) {
DefaultRouteStartupOrder order = (DefaultRouteStartupOrder) startupOrder;
RouteService routeService = order.getRouteService();
list.add(routeService);
}
InternalServiceManager.shutdownServices(this, list, false);
if (startupSummaryLevel != StartupSummaryLevel.Oneline
&& startupSummaryLevel != StartupSummaryLevel.Off) {
logRouteStopSummary(LoggingLevel.INFO);
}
// do not clear route services or startup listeners as we can start
// Camel again and get the route back as before
routeStartupOrder.clear();
EventHelper.notifyCamelContextRoutesStopped(this);
// but clear any suspend routes
suspendedRouteServices.clear();
// stop consumers from the services to close first, such as POJO
// consumer (eg @Consumer)
// which we need to stop after the routes, as a POJO consumer is
// essentially a route also
internalServiceManager.stopConsumers(this);
// the stop order is important
// shutdown default error handler thread pool
final ScheduledExecutorService errorHandlerExecutorService = PluginHelper.getErrorHandlerExecutorService(this);
if (errorHandlerExecutorService != null) {
// force shutting down the thread pool
getExecutorServiceManager().shutdownNow(errorHandlerExecutorService);
}
// shutdown debugger
ServiceHelper.stopAndShutdownService(getDebugger());
InternalServiceManager.shutdownServices(this, endpoints.values());
endpoints.clear();
InternalServiceManager.shutdownServices(this, components.values());
components.clear();
InternalServiceManager.shutdownServices(this, languages.values());
languages.clear();
// shutdown services as late as possible (except type converters as they may be needed during the remainder of the stopping)
internalServiceManager.shutdownServices(this);
// shutdown log listeners
ServiceHelper.stopAndShutdownServices(getCamelContextExtension().getLogListeners());
try {
for (LifecycleStrategy strategy : lifecycleStrategies) {
strategy.onContextStopped(this);
}
} catch (Exception e) {
LOG.warn("Error occurred while stopping lifecycle strategies. This exception will be ignored.", e);
}
// must notify that we are stopped before stopping the management strategy
EventHelper.notifyCamelContextStopped(this);
// stop the notifier service
if (getManagementStrategy() != null) {
for (EventNotifier notifier : getManagementStrategy().getEventNotifiers()) {
InternalServiceManager.shutdownServices(this, notifier);
}
}
// shutdown management and lifecycle after all other services
InternalServiceManager.shutdownServices(this, camelContextExtension.getManagementStrategy());
InternalServiceManager.shutdownServices(this, camelContextExtension.getManagementMBeanAssembler());
InternalServiceManager.shutdownServices(this, lifecycleStrategies);
// do not clear lifecycleStrategies as we can start Camel again and get
// the route back as before
// shutdown executor service, reactive executor last
InternalServiceManager.shutdownServices(this, camelContextExtension.getExecutorServiceManager());
InternalServiceManager.shutdownServices(this, camelContextExtension.getReactiveExecutor());
// shutdown type converter and registry as late as possible
camelContextExtension.stopTypeConverter();
camelContextExtension.stopTypeConverterRegistry();
camelContextExtension.stopRegistry();
// stop the lazy created so they can be re-created on restart
forceStopLazyInitialization();
if (startupSummaryLevel != StartupSummaryLevel.Off) {
if (LOG.isInfoEnabled()) {
String taken = TimeUtils.printDuration(stopWatch.taken(), true);
LOG.info("Apache Camel {} ({}) shutdown in {} (uptime:{})", getVersion(), camelContextExtension.getName(),
taken, CamelContextHelper.getUptime(this));
}
}
// ensure any recorder is stopped in case it was kept running
final StartupStepRecorder startupStepRecorder = camelContextExtension.getStartupStepRecorder();
startupStepRecorder.stop();
// and clear start date
clock.add(ContextEvents.START, null);
// Call all registered trackers with this context
// Note, this may use a partially constructed object
CamelContextTracker.notifyContextDestroyed(this);
firstStartDone = true;
}
@Override
protected void doFail(Exception e) {
super.doFail(e);
// reset flag in case of startup fail as we want to be able to allow to start again
firstStartDone = false;
}
protected void doDumpRoutes() {
// noop
}
protected void logRouteStopSummary(LoggingLevel loggingLevel) {
CamelLogger logger = new CamelLogger(LOG, loggingLevel);
if (logger.shouldLog()) {
int total = 0;
int stopped = 0;
int forced = 0;
int kamelets = 0;
int templates = 0;
int rests = 0;
boolean registerKamelets = false;
boolean registerTemplates = true;
ManagementStrategy ms = getManagementStrategy();
if (ms != null && ms.getManagementAgent() != null) {
registerKamelets = ms.getManagementAgent().getRegisterRoutesCreateByKamelet();
registerTemplates = ms.getManagementAgent().getRegisterRoutesCreateByTemplate();
}
List lines = new ArrayList<>();
final ShutdownStrategy shutdownStrategy = camelContextExtension.getShutdownStrategy();
if (shutdownStrategy != null && shutdownStrategy.isShutdownRoutesInReverseOrder()) {
routeStartupOrder.sort(Comparator.comparingInt(RouteStartupOrder::getStartupOrder).reversed());
} else {
routeStartupOrder.sort(Comparator.comparingInt(RouteStartupOrder::getStartupOrder));
}
for (RouteStartupOrder order : routeStartupOrder) {
total++;
String id = order.getRoute().getRouteId();
String status = getRouteStatus(id).name();
if (order.getRoute().isCreatedByKamelet()) {
kamelets++;
} else if (order.getRoute().isCreatedByRouteTemplate()) {
templates++;
} else if (order.getRoute().isCreatedByRestDsl()) {
rests++;
}
boolean skip = (!registerKamelets && order.getRoute().isCreatedByKamelet())
|| (!registerTemplates && order.getRoute().isCreatedByRouteTemplate());
if (!skip && ServiceStatus.Stopped.name().equals(status)) {
stopped++;
}
if (order.getRoute().getProperties().containsKey("forcedShutdown")) {
forced++;
status = "Forced stopped";
}
// use basic endpoint uri to not log verbose details or potential sensitive data
String uri = order.getRoute().getEndpoint().getEndpointBaseUri();
uri = URISupport.sanitizeUri(uri);
if (startupSummaryLevel == StartupSummaryLevel.Verbose || !skip) {
lines.add(String.format(" %s %s (%s)", status, id, uri));
}
}
int newTotal = total;
if (!registerKamelets) {
newTotal -= kamelets;
}
if (!registerTemplates) {
newTotal -= templates;
}
StringJoiner sj = new StringJoiner(" ");
sj.add("total:" + newTotal);
if (total != stopped) {
sj.add("stopped:" + stopped);
}
if (kamelets > 0) {
sj.add("kamelets:" + kamelets);
}
if (templates > 0) {
sj.add("templates:" + templates);
}
if (rests > 0) {
sj.add("rest-dsl:" + rests);
}
if (forced > 0) {
sj.add("forced:" + forced);
}
logger.log(String.format("Routes stopped (%s)", sj));
// if we are default/verbose then log each route line
if (startupSummaryLevel == StartupSummaryLevel.Default || startupSummaryLevel == StartupSummaryLevel.Verbose) {
for (String line : lines) {
logger.log(line);
}
}
}
}
protected void logRouteStartSummary(LoggingLevel loggingLevel) {
CamelLogger logger = new CamelLogger(LOG, loggingLevel);
if (logger.shouldLog()) {
int total = 0;
int started = 0;
int kamelets = 0;
int templates = 0;
int rests = 0;
boolean registerKamelets = false;
boolean registerTemplates = true;
ManagementStrategy ms = getManagementStrategy();
if (ms != null && ms.getManagementAgent() != null) {
registerKamelets = ms.getManagementAgent().getRegisterRoutesCreateByKamelet();
registerTemplates = ms.getManagementAgent().getRegisterRoutesCreateByTemplate();
}
List lines = new ArrayList<>();
final ShutdownStrategy shutdownStrategy = camelContextExtension.getShutdownStrategy();
if (shutdownStrategy != null && shutdownStrategy.isShutdownRoutesInReverseOrder()) {
routeStartupOrder.sort(Comparator.comparingInt(RouteStartupOrder::getStartupOrder).reversed());
} else {
routeStartupOrder.sort(Comparator.comparingInt(RouteStartupOrder::getStartupOrder));
}
for (RouteStartupOrder order : routeStartupOrder) {
total++;
String id = order.getRoute().getRouteId();
String status = getRouteStatus(id).name();
if (order.getRoute().isCreatedByKamelet()) {
kamelets++;
} else if (order.getRoute().isCreatedByRouteTemplate()) {
templates++;
} else if (order.getRoute().isCreatedByRestDsl()) {
rests++;
}
boolean skip = (!registerKamelets && order.getRoute().isCreatedByKamelet())
|| (!registerTemplates && order.getRoute().isCreatedByRouteTemplate());
if (!skip && ServiceStatus.Started.name().equals(status)) {
started++;
}
// use basic endpoint uri to not log verbose details or potential sensitive data
String uri = order.getRoute().getEndpoint().getEndpointBaseUri();
uri = URISupport.sanitizeUri(uri);
if (startupSummaryLevel == StartupSummaryLevel.Verbose || !skip) {
lines.add(String.format(" %s %s (%s)", status, id, uri));
}
}
int newTotal = total;
if (!registerKamelets) {
newTotal -= kamelets;
}
if (!registerTemplates) {
newTotal -= templates;
}
StringJoiner sj = new StringJoiner(" ");
sj.add("total:" + newTotal);
if (total != started) {
sj.add("started:" + started);
}
if (kamelets > 0) {
sj.add("kamelets:" + kamelets);
}
if (templates > 0) {
sj.add("templates:" + templates);
}
if (rests > 0) {
sj.add("rest-dsl:" + rests);
}
logger.log(String.format("Routes started (%s)", sj));
// if we are default/verbose then log each route line
if (startupSummaryLevel == StartupSummaryLevel.Default || startupSummaryLevel == StartupSummaryLevel.Verbose) {
for (String line : lines) {
logger.log(line);
}
}
}
}
public void startRouteDefinitions() throws Exception {
}
public void removeRouteDefinitionsFromTemplate() throws Exception {
}
protected boolean isStreamCachingInUse() throws Exception {
return isStreamCaching();
}
protected void bindDataFormats() throws Exception {
}
protected boolean routeSupportsSuspension(String routeId) {
RouteService routeService = routeServices.get(routeId);
if (routeService != null) {
return routeService.getRoute().supportsSuspension();
}
return false;
}
void startService(Service service) throws Exception {
// and register startup aware so they can be notified when
// camel context has been started
if (service instanceof StartupListener listener) {
addStartupListener(listener);
}
CamelContextAware.trySetCamelContext(service, getCamelContextReference());
ServiceHelper.startService(service);
}
private void startServices(Collection> services) throws Exception {
for (Object element : services) {
if (element instanceof Service service) {
startService(service);
}
}
}
private void stopServices(Object service) {
// allow us to do custom work before delegating to service helper
try {
ServiceHelper.stopService(service);
} catch (Exception e) {
// fire event
EventHelper.notifyServiceStopFailure(getCamelContextReference(), service, e);
// rethrow to signal error with stopping
throw e;
}
}
/**
* Starts the given route service
*/
public void startRouteService(RouteService routeService, boolean addingRoutes) throws Exception {
lock.lock();
try {
// we may already be starting routes so remember this, so we can unset
// accordingly in finally block
boolean alreadyStartingRoutes = isStartingRoutes();
if (!alreadyStartingRoutes) {
setStartingRoutes(true);
}
try {
// the route service could have been suspended, and if so then
// resume it instead
if (routeService.getStatus().isSuspended()) {
resumeRouteService(routeService);
} else {
// start the route service
routeServices.put(routeService.getId(), routeService);
if (shouldStartRoutes()) {
final StartupStepRecorder startupStepRecorder = camelContextExtension.getStartupStepRecorder();
StartupStep step
= startupStepRecorder.beginStep(Route.class, routeService.getId(), "Start Route Services");
// this method will log the routes being started
internalRouteStartupManager.safelyStartRouteServices(this, true, true, true, false, addingRoutes,
routeService);
// start route services if it was configured to auto startup
// and we are not adding routes
boolean isAutoStartup = routeService.isAutoStartup();
if (!addingRoutes || isAutoStartup) {
// start the route since auto start is enabled or we are
// starting a route (not adding new routes)
routeService.start();
}
startupStepRecorder.endStep(step);
}
}
} finally {
if (!alreadyStartingRoutes) {
setStartingRoutes(false);
}
}
} finally {
lock.unlock();
}
}
/**
* Resumes the given route service
*/
protected void resumeRouteService(RouteService routeService) throws Exception {
lock.lock();
try {
// the route service could have been stopped, and if so then start it
// instead
if (!routeService.getStatus().isSuspended()) {
startRouteService(routeService, false);
} else {
// resume the route service
if (shouldStartRoutes()) {
// this method will log the routes being started
internalRouteStartupManager.safelyStartRouteServices(this, true, false, true, true, false, routeService);
// must resume route service as well
routeService.resume();
}
}
} finally {
lock.unlock();
}
}
protected void stopRouteService(RouteService routeService, boolean removingRoutes, LoggingLevel loggingLevel)
throws Exception {
lock.lock();
try {
routeService.setRemovingRoutes(removingRoutes);
stopRouteService(routeService, loggingLevel);
} finally {
lock.unlock();
}
}
protected void logRouteState(Route route, String state, LoggingLevel loggingLevel) {
lock.lock();
try {
CamelLogger logger = new CamelLogger(LOG, loggingLevel);
if (logger.shouldLog()) {
if (route.getConsumer() != null) {
String id = route.getId();
String uri = route.getEndpoint().getEndpointBaseUri();
uri = URISupport.sanitizeUri(uri);
String line = String.format("%s %s (%s)", state, id, uri);
logger.log(line);
} else {
String id = route.getId();
String line = String.format("%s %s", state, id);
logger.log(line);
}
}
} finally {
lock.unlock();
}
}
protected void stopRouteService(RouteService routeService, LoggingLevel loggingLevel) {
lock.lock();
try {
routeService.stop();
logRouteState(routeService.getRoute(), "Stopped", loggingLevel);
} finally {
lock.unlock();
}
}
protected void shutdownRouteService(RouteService routeService) throws Exception {
lock.lock();
try {
shutdownRouteService(routeService, LoggingLevel.INFO);
} finally {
lock.unlock();
}
}
protected void shutdownRouteService(RouteService routeService, LoggingLevel loggingLevel) {
lock.lock();
try {
routeService.shutdown();
logRouteState(routeService.getRoute(), "Shutdown", loggingLevel);
} finally {
lock.unlock();
}
}
protected void suspendRouteService(RouteService routeService) {
lock.lock();
try {
routeService.setRemovingRoutes(false);
routeService.suspend();
logRouteState(routeService.getRoute(), "Suspended", LoggingLevel.INFO);
} finally {
lock.unlock();
}
}
/**
* Force some lazy initialization to occur upfront before we start any components and create routes
*/
protected void forceLazyInitialization() {
final StartupStepRecorder startupStepRecorder = camelContextExtension.getStartupStepRecorder();
StartupStep step = startupStepRecorder.beginStep(CamelContext.class, camelContextExtension.getName(),
"Start Mandatory Services");
initEagerMandatoryServices();
startupStepRecorder.endStep(step);
step = startupStepRecorder.beginStep(CamelContext.class, getName(), "Start Standard Services");
doStartStandardServices();
startupStepRecorder.endStep(step);
}
/**
* Initializes eager some mandatory services which needs to warmup and be ready as this helps optimize Camel at
* runtime.
*/
protected void initEagerMandatoryServices() {
camelContextExtension.initEagerMandatoryServices(isCaseInsensitiveHeaders(), this::createHeadersMapFactory);
}
protected void doStartStandardServices() {
getVersion();
getClassResolver();
camelContextExtension.getRegistry();
camelContextExtension.getBootstrapFactoryFinder();
getTypeConverterRegistry();
getInjector();
camelContextExtension.getDefaultFactoryFinder();
getPropertiesComponent();
getExecutorServiceManager();
camelContextExtension.getExchangeFactoryManager();
camelContextExtension.getExchangeFactory();
getShutdownStrategy();
getUuidGenerator();
// resolve simple language to initialize it
resolveLanguage("simple");
}
/**
* Force clear lazy initialization so they can be re-created on restart
*/
protected void forceStopLazyInitialization() {
camelContextExtension.resetInjector();
camelContextExtension.resetTypeConverterRegistry();
camelContextExtension.resetTypeConverter();
}
/**
* A pluggable strategy to allow an endpoint to be created without requiring a component to be its factory, such as
* for looking up the URI inside some {@link Registry}
*
* @param uri the uri for the endpoint to be created
* @return the newly created endpoint or null if it could not be resolved
*/
protected Endpoint createEndpoint(String uri) {
Object value = camelContextExtension.getRegistry().lookupByName(uri);
if (value instanceof Endpoint endpoint) {
return endpoint;
} else if (value instanceof Processor processor) {
return new ProcessorEndpoint(uri, getCamelContextReference(), processor);
} else if (value != null) {
return convertBeanToEndpoint(uri, value);
}
return null;
}
/**
* Strategy method for attempting to convert the bean from a {@link Registry} to an endpoint using some kind of
* transformation or wrapper
*
* @param uri the uri for the endpoint (and name in the registry)
* @param bean the bean to be converted to an endpoint, which will be not null
* @return a new endpoint
*/
protected Endpoint convertBeanToEndpoint(String uri, Object bean) {
throw new IllegalArgumentException("uri: " + uri + " bean: " + bean + " could not be converted to an Endpoint");
}
/**
* Should we start newly added routes?
*/
protected boolean shouldStartRoutes() {
return isStarted() && !isStarting();
}
@Override
public Map getGlobalOptions() {
return globalOptions;
}
@Override
public void setGlobalOptions(Map globalOptions) {
this.globalOptions = globalOptions;
}
protected FactoryFinder createBootstrapFactoryFinder(String path) {
return PluginHelper.getFactoryFinderResolver(camelContextExtension).resolveBootstrapFactoryFinder(getClassResolver(),
path);
}
protected FactoryFinder createFactoryFinder(String path) {
return PluginHelper.getFactoryFinderResolver(camelContextExtension).resolveFactoryFinder(getClassResolver(), path);
}
@Override
public ClassResolver getClassResolver() {
return camelContextExtension.getClassResolver();
}
@Override
public void setClassResolver(ClassResolver classResolver) {
camelContextExtension.setClassResolver(classResolver);
}
@Override
public Set getComponentNames() {
return Collections.unmodifiableSet(components.keySet());
}
@Override
public Set getLanguageNames() {
return Collections.unmodifiableSet(languages.keySet());
}
@Override
public ManagementStrategy getManagementStrategy() {
return camelContextExtension.getManagementStrategy();
}
@Override
public void setManagementStrategy(ManagementStrategy managementStrategy) {
camelContextExtension.setManagementStrategy(managementStrategy);
}
@Override
public void disableJMX() {
if (isNew()) {
disableJMX = true;
} else if (isInit() || isBuild()) {
disableJMX = true;
// we are still in initializing mode, so we can disable JMX, by
// setting up management again
camelContextExtension.setupManagement(null);
} else {
throw new IllegalStateException("Disabling JMX can only be done when CamelContext has not been started");
}
}
public boolean isJMXDisabled() {
String override = System.getProperty(JmxSystemPropertyKeys.DISABLED);
if (override != null) {
return Boolean.parseBoolean(override);
}
return disableJMX;
}
void enableDebugging(DebuggerFactory df) throws Exception {
setDebugging(true);
Debugger newDebugger = df.createDebugger(this);
if (newDebugger != null) {
setDebugger(newDebugger);
}
}
@Override
public InflightRepository getInflightRepository() {
return camelContextExtension.getInflightRepository();
}
@Override
public void setInflightRepository(InflightRepository repository) {
camelContextExtension.setInflightRepository(repository);
}
@Override
public void setAutoStartup(Boolean autoStartup) {
this.autoStartup = autoStartup;
}
@Override
public Boolean isAutoStartup() {
return autoStartup != null && autoStartup;
}
@Override
public Boolean isLoadTypeConverters() {
return loadTypeConverters != null && loadTypeConverters;
}
@Override
public void setLoadTypeConverters(Boolean loadTypeConverters) {
this.loadTypeConverters = loadTypeConverters;
}
@Override
public Boolean isLoadHealthChecks() {
return loadHealthChecks != null && loadHealthChecks;
}
@Override
public void setLoadHealthChecks(Boolean loadHealthChecks) {
this.loadHealthChecks = loadHealthChecks;
}
@Override
public Boolean isModeline() {
return modeline != null && modeline;
}
@Override
public void setModeline(Boolean modeline) {
this.modeline = modeline;
}
@Override
public Boolean isDevConsole() {
return devConsole != null && devConsole;
}
@Override
public void setDevConsole(Boolean loadDevConsoles) {
this.devConsole = loadDevConsoles;
}
@Override
public Boolean isTypeConverterStatisticsEnabled() {
return typeConverterStatisticsEnabled != null && typeConverterStatisticsEnabled;
}
@Override
public Boolean isSourceLocationEnabled() {
return sourceLocationEnabled;
}
@Override
public void setSourceLocationEnabled(Boolean sourceLocationEnabled) {
this.sourceLocationEnabled = sourceLocationEnabled;
}
@Override
public void setTypeConverterStatisticsEnabled(Boolean typeConverterStatisticsEnabled) {
this.typeConverterStatisticsEnabled = typeConverterStatisticsEnabled;
}
@Override
public String getDumpRoutes() {
return dumpRoutes;
}
@Override
public void setDumpRoutes(String dumpRoutes) {
this.dumpRoutes = dumpRoutes;
}
@Override
public Boolean isUseMDCLogging() {
return useMDCLogging != null && useMDCLogging;
}
@Override
public void setUseMDCLogging(Boolean useMDCLogging) {
this.useMDCLogging = useMDCLogging;
}
@Override
public String getMDCLoggingKeysPattern() {
return mdcLoggingKeysPattern;
}
@Override
public void setMDCLoggingKeysPattern(String pattern) {
this.mdcLoggingKeysPattern = pattern;
}
@Override
public Boolean isUseDataType() {
return useDataType;
}
@Override
public void setUseDataType(Boolean useDataType) {
this.useDataType = useDataType;
}
@Override
public Boolean isUseBreadcrumb() {
return useBreadcrumb != null && useBreadcrumb;
}
@Override
public void setUseBreadcrumb(Boolean useBreadcrumb) {
this.useBreadcrumb = useBreadcrumb;
}
@Override
public ClassLoader getApplicationContextClassLoader() {
return applicationContextClassLoader;
}
@Override
public void setApplicationContextClassLoader(ClassLoader classLoader) {
applicationContextClassLoader = classLoader;
}
private DataFormat doResolveDataFormat(String name) {
StartupStep step = null;
final StartupStepRecorder startupStepRecorder = camelContextExtension.getStartupStepRecorder();
// only record startup step during startup (not started)
if (!isStarted() && startupStepRecorder.isEnabled()) {
step = startupStepRecorder.beginStep(DataFormat.class, name, "Resolve DataFormat");
}
final DataFormat df = Optional
.ofNullable(ResolverHelper.lookupDataFormatInRegistryWithFallback(getCamelContextReference(), name))
.orElseGet(() -> PluginHelper.getDataFormatResolver(camelContextExtension).createDataFormat(name,
getCamelContextReference()));
if (df != null) {
// inject CamelContext if aware
CamelContextAware.trySetCamelContext(df, getCamelContextReference());
for (LifecycleStrategy strategy : lifecycleStrategies) {
strategy.onDataFormatCreated(name, df);
}
}
if (step != null) {
startupStepRecorder.endStep(step);
}
return df;
}
@Override
public DataFormat resolveDataFormat(String name) {
return dataformats.computeIfAbsent(name, s -> doResolveDataFormat(name));
}
@Override
public DataFormat createDataFormat(String name) {
StartupStep step = null;
// only record startup step during startup (not started)
final StartupStepRecorder startupStepRecorder = camelContextExtension.getStartupStepRecorder();
if (!isStarted() && startupStepRecorder.isEnabled()) {
step = startupStepRecorder.beginStep(DataFormat.class, name, "Create DataFormat");
}
DataFormat answer
= PluginHelper.getDataFormatResolver(camelContextExtension).createDataFormat(name, getCamelContextReference());
// inject CamelContext if aware
CamelContextAware.trySetCamelContext(answer, getCamelContextReference());
for (LifecycleStrategy strategy : lifecycleStrategies) {
strategy.onDataFormatCreated(name, answer);
}
if (step != null) {
startupStepRecorder.endStep(step);
}
return answer;
}
@Override
public Set getDataFormatNames() {
return Collections.unmodifiableSet(dataformats.keySet());
}
@Override
public ShutdownStrategy getShutdownStrategy() {
return camelContextExtension.getShutdownStrategy();
}
@Override
public void setShutdownStrategy(ShutdownStrategy shutdownStrategy) {
camelContextExtension.setShutdownStrategy(shutdownStrategy);
}
@Override
public ShutdownRoute getShutdownRoute() {
return shutdownRoute;
}
@Override
public void setShutdownRoute(ShutdownRoute shutdownRoute) {
this.shutdownRoute = shutdownRoute;
}
@Override
public ShutdownRunningTask getShutdownRunningTask() {
return shutdownRunningTask;
}
@Override
public void setShutdownRunningTask(ShutdownRunningTask shutdownRunningTask) {
this.shutdownRunningTask = shutdownRunningTask;
}
@Override
public void setAllowUseOriginalMessage(Boolean allowUseOriginalMessage) {
this.allowUseOriginalMessage = allowUseOriginalMessage;
}
@Override
public Boolean isAllowUseOriginalMessage() {
return allowUseOriginalMessage != null && allowUseOriginalMessage;
}
@Override
public Boolean isCaseInsensitiveHeaders() {
return caseInsensitiveHeaders != null && caseInsensitiveHeaders;
}
@Override
public void setCaseInsensitiveHeaders(Boolean caseInsensitiveHeaders) {
this.caseInsensitiveHeaders = caseInsensitiveHeaders;
}
@Override
public Boolean isAutowiredEnabled() {
return autowiredEnabled != null && autowiredEnabled;
}
@Override
public void setAutowiredEnabled(Boolean autowiredEnabled) {
this.autowiredEnabled = autowiredEnabled;
}
@Override
public ExecutorServiceManager getExecutorServiceManager() {
return camelContextExtension.getExecutorServiceManager();
}
@Override
public void setExecutorServiceManager(ExecutorServiceManager executorServiceManager) {
camelContextExtension.setExecutorServiceManager(executorServiceManager);
}
@Override
public MessageHistoryFactory getMessageHistoryFactory() {
return camelContextExtension.getMessageHistoryFactory();
}
@Override
public void setMessageHistoryFactory(MessageHistoryFactory messageHistoryFactory) {
camelContextExtension.setMessageHistoryFactory(messageHistoryFactory);
// enable message history if we set a custom factory
setMessageHistory(true);
}
@Override
public Debugger getDebugger() {
return debugger;
// do not lazy create debugger as the DefaultDebugger is mostly only useable for testing
// and if debugging is enabled then Camel will use BacklogDebugger that can be remotely controlled via JMX management
}
@Override
public void setDebugger(Debugger debugger) {
if (isStartingOrStarted()) {
throw new IllegalStateException("Cannot set debugger on a started CamelContext");
}
this.debugger = internalServiceManager.addService(this, debugger, true, false, true);
}
@Override
public Tracer getTracer() {
return camelContextExtension.getTracer();
}
@Override
public void setTracer(Tracer tracer) {
// if tracing is in standby mode, then we can use it after camel is started
if (!isTracingStandby() && isStartingOrStarted()) {
throw new IllegalStateException("Cannot set tracer on a started CamelContext");
}
camelContextExtension.setTracer(tracer);
}
@Override
public void setTracingStandby(boolean tracingStandby) {
this.traceStandby = tracingStandby;
}
@Override
public boolean isTracingStandby() {
return traceStandby != null && traceStandby;
}
@Override
public void setTracingTemplates(boolean tracingTemplates) {
this.traceTemplates = tracingTemplates;
}
@Override
public boolean isTracingTemplates() {
return traceTemplates != null && traceTemplates;
}
@Override
public void setBacklogTracingTemplates(boolean backlogTracingTemplates) {
this.backlogTraceTemplates = backlogTracingTemplates;
}
@Override
public boolean isBacklogTracingTemplates() {
return backlogTraceTemplates != null && backlogTraceTemplates;
}
@Override
public void setBacklogTracingStandby(boolean backlogTracingStandby) {
this.backlogTraceStandby = backlogTracingStandby;
}
@Override
public boolean isBacklogTracingStandby() {
return backlogTraceStandby != null && backlogTraceStandby;
}
@Override
public UuidGenerator getUuidGenerator() {
return camelContextExtension.getUuidGenerator();
}
@Override
public void setUuidGenerator(UuidGenerator uuidGenerator) {
camelContextExtension.setUuidGenerator(uuidGenerator);
}
@Override
public StreamCachingStrategy getStreamCachingStrategy() {
return camelContextExtension.getStreamCachingStrategy();
}
@Override
public void setStreamCachingStrategy(StreamCachingStrategy streamCachingStrategy) {
camelContextExtension.setStreamCachingStrategy(streamCachingStrategy);
}
@Override
public RestRegistry getRestRegistry() {
return camelContextExtension.getRestRegistry();
}
@Override
public void setRestRegistry(RestRegistry restRegistry) {
camelContextExtension.setRestRegistry(restRegistry);
}
protected RestRegistry createRestRegistry() {
RestRegistryFactory factory = camelContextExtension.getRestRegistryFactory();
return factory.createRegistry();
}
@Override
public String getGlobalOption(String key) {
String value = getGlobalOptions().get(key);
if (ObjectHelper.isNotEmpty(value)) {
try {
value = resolvePropertyPlaceholders(value);
} catch (Exception e) {
throw new RuntimeCamelException("Error getting global option: " + key, e);
}
}
return value;
}
@Override
public Transformer resolveTransformer(String name) {
return getTransformerRegistry().resolveTransformer(new TransformerKey(name));
}
@Override
public Transformer resolveTransformer(DataType from, DataType to) {
return getTransformerRegistry().resolveTransformer(new TransformerKey(from, to));
}
@Override
public TransformerRegistry getTransformerRegistry() {
return camelContextExtension.getTransformerRegistry();
}
@Override
public Validator resolveValidator(DataType type) {
return getValidatorRegistry().resolveValidator(new ValidatorKey(type));
}
@Override
public ValidatorRegistry getValidatorRegistry() {
return camelContextExtension.getValidatorRegistry();
}
@Override
public SSLContextParameters getSSLContextParameters() {
return this.sslContextParameters;
}
@Override
public void setSSLContextParameters(SSLContextParameters sslContextParameters) {
this.sslContextParameters = sslContextParameters;
}
@Override
public StartupSummaryLevel getStartupSummaryLevel() {
return startupSummaryLevel;
}
@Override
public void setStartupSummaryLevel(StartupSummaryLevel startupSummaryLevel) {
this.startupSummaryLevel = startupSummaryLevel;
}
protected Map getRouteServices() {
return routeServices;
}
@Override
public String toString() {
return "CamelContext(" + camelContextExtension.getName() + ")";
}
protected void failOnStartup(Exception e) {
if (e instanceof VetoCamelContextStartException vetoException) {
if (vetoException.isRethrowException()) {
fail(e);
} else {
// swallow exception and change state of this camel context to stopped
status = FAILED;
}
} else {
fail(e);
}
}
protected abstract ExchangeFactory createExchangeFactory();
protected abstract ExchangeFactoryManager createExchangeFactoryManager();
protected abstract ProcessorExchangeFactory createProcessorExchangeFactory();
protected abstract HealthCheckRegistry createHealthCheckRegistry();
protected abstract DevConsoleRegistry createDevConsoleRegistry();
protected abstract ReactiveExecutor createReactiveExecutor();
protected abstract StreamCachingStrategy createStreamCachingStrategy();
protected abstract TypeConverter createTypeConverter();
protected abstract TypeConverterRegistry createTypeConverterRegistry();
protected abstract Injector createInjector();
protected abstract PropertiesComponent createPropertiesComponent();
protected abstract CamelBeanPostProcessor createBeanPostProcessor();
protected abstract CamelDependencyInjectionAnnotationFactory createDependencyInjectionAnnotationFactory();
protected abstract ComponentResolver createComponentResolver();
protected abstract ComponentNameResolver createComponentNameResolver();
protected abstract Registry createRegistry();
protected abstract UuidGenerator createUuidGenerator();
protected abstract ModelJAXBContextFactory createModelJAXBContextFactory();
protected abstract NodeIdFactory createNodeIdFactory();
protected abstract ModelineFactory createModelineFactory();
protected abstract PeriodTaskResolver createPeriodTaskResolver();
protected abstract PeriodTaskScheduler createPeriodTaskScheduler();
protected abstract FactoryFinderResolver createFactoryFinderResolver();
protected abstract ClassResolver createClassResolver();
protected abstract ProcessorFactory createProcessorFactory();
protected abstract InternalProcessorFactory createInternalProcessorFactory();
protected abstract InterceptEndpointFactory createInterceptEndpointFactory();
protected abstract RouteFactory createRouteFactory();
protected abstract DataFormatResolver createDataFormatResolver();
protected abstract HealthCheckResolver createHealthCheckResolver();
protected abstract DevConsoleResolver createDevConsoleResolver();
protected abstract MessageHistoryFactory createMessageHistoryFactory();
protected abstract InflightRepository createInflightRepository();
protected abstract AsyncProcessorAwaitManager createAsyncProcessorAwaitManager();
protected abstract RouteController createRouteController();
protected abstract ShutdownStrategy createShutdownStrategy();
protected abstract PackageScanClassResolver createPackageScanClassResolver();
protected abstract PackageScanResourceResolver createPackageScanResourceResolver();
protected abstract ExecutorServiceManager createExecutorServiceManager();
protected abstract UnitOfWorkFactory createUnitOfWorkFactory();
protected abstract CamelContextNameStrategy createCamelContextNameStrategy();
protected abstract ManagementNameStrategy createManagementNameStrategy();
protected abstract HeadersMapFactory createHeadersMapFactory();
protected abstract BeanProxyFactory createBeanProxyFactory();
protected abstract AnnotationBasedProcessorFactory createAnnotationBasedProcessorFactory();
protected abstract DeferServiceFactory createDeferServiceFactory();
protected abstract BeanProcessorFactory createBeanProcessorFactory();
protected abstract BeanIntrospection createBeanIntrospection();
protected abstract RoutesLoader createRoutesLoader();
protected abstract ResourceLoader createResourceLoader();
protected abstract ModelToXMLDumper createModelToXMLDumper();
protected abstract ModelToYAMLDumper createModelToYAMLDumper();
protected abstract RestBindingJaxbDataFormatFactory createRestBindingJaxbDataFormatFactory();
protected abstract RuntimeCamelCatalog createRuntimeCamelCatalog();
protected abstract DumpRoutesStrategy createDumpRoutesStrategy();
protected abstract Tracer createTracer();
protected abstract LanguageResolver createLanguageResolver();
protected abstract ConfigurerResolver createConfigurerResolver();
protected abstract UriFactoryResolver createUriFactoryResolver();
protected abstract RestRegistryFactory createRestRegistryFactory();
protected abstract EndpointRegistry createEndpointRegistry(
Map endpoints);
protected abstract TransformerRegistry createTransformerRegistry();
protected abstract ValidatorRegistry createValidatorRegistry();
protected abstract VariableRepositoryFactory createVariableRepositoryFactory();
protected abstract EndpointServiceRegistry createEndpointServiceRegistry();
protected abstract StartupConditionStrategy createStartupConditionStrategy();
protected RestConfiguration createRestConfiguration() {
// lookup a global which may have been on a container such spring-boot / CDI / etc.
RestConfiguration conf
= CamelContextHelper.lookup(this, RestConfiguration.DEFAULT_REST_CONFIGURATION_ID, RestConfiguration.class);
if (conf == null) {
conf = CamelContextHelper.findSingleByType(this, RestConfiguration.class);
}
if (conf == null) {
conf = new RestConfiguration();
}
return conf;
}
public abstract Processor createErrorHandler(Route route, Processor processor) throws Exception;
@Deprecated
public abstract void disposeModel();
public abstract String getTestExcludeRoutes();
@Override
public ExtendedCamelContext getCamelContextExtension() {
return camelContextExtension;
}
@Override
public String getName() {
return camelContextExtension.getName();
}
@Override
public String getDescription() {
return camelContextExtension.getDescription();
}
public void addRoute(Route route) {
routesLock.lock();
try {
routes.add(route);
} finally {
routesLock.unlock();
}
}
public void removeRoute(Route route) {
routesLock.lock();
try {
routes.remove(route);
} finally {
routesLock.unlock();
}
}
protected Lock getLock() {
return lock;
}
byte getStatusPhase() {
return status;
}
class LifecycleHelper implements AutoCloseable {
final Map originalContextMap;
final ClassLoader tccl;
LifecycleHelper() {
// Using the ApplicationClassLoader as the default for TCCL
tccl = Thread.currentThread().getContextClassLoader();
if (applicationContextClassLoader != null) {
Thread.currentThread().setContextClassLoader(applicationContextClassLoader);
}
if (isUseMDCLogging()) {
originalContextMap = MDC.getCopyOfContextMap();
MDC.put(MDC_CAMEL_CONTEXT_ID, camelContextExtension.getName());
} else {
originalContextMap = null;
}
}
@Override
public void close() {
if (isUseMDCLogging()) {
if (originalContextMap != null) {
MDC.setContextMap(originalContextMap);
} else {
MDC.clear();
}
}
Thread.currentThread().setContextClassLoader(tccl);
}
}
@Override
public Registry getRegistry() {
return camelContextExtension.getRegistry();
}
Set getEndpointStrategies() {
return endpointStrategies;
}
List getRouteStartupOrder() {
return routeStartupOrder;
}
InternalServiceManager getInternalServiceManager() {
return internalServiceManager;
}
/*
* This method exists for testing purposes only: we need to make sure we don't leak bootstraps.
* This allows us to check for leaks without compromising the visibility/access on the DefaultCamelContextExtension.
* Check the test AddRoutesAtRuntimeTest for details.
*/
@SuppressWarnings("unused")
private List getBootstraps() {
return camelContextExtension.getBootstraps();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy