Repository: camel Updated Branches: refs/heads/master 365ac51a0 -> 23c460f31
CAMEL-11073: camel-rest - Spring boot option named c-o-r-s Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/23c460f3 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/23c460f3 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/23c460f3 Branch: refs/heads/master Commit: 23c460f3144c2f280d8e87a5b95d503e0661c934 Parents: 365ac51 Author: lburgazzoli <[email protected]> Authored: Tue Mar 28 18:34:55 2017 +0200 Committer: lburgazzoli <[email protected]> Committed: Tue Mar 28 18:34:55 2017 +0200 ---------------------------------------------------------------------- .../spring/boot/CamelRestAutoConfiguration.java | 60 --- .../boot/CamelRestConfigurationProperties.java | 233 ------------ .../main/resources/META-INF/spring.factories | 1 - .../apache/camel/spring/boot/CamelRestTest.java | 167 --------- .../camel-core-starter/pom.xml | 5 + ...onfigurationDefinitionAutoConfiguration.java | 65 ++++ .../RestConfigurationDefinitionProperties.java | 374 +++++++++++++++++++ .../main/resources/META-INF/spring.factories | 4 +- .../model/rest/springboot/CamelRestTest.java | 167 +++++++++ .../src/test/resources/application.properties | 0 .../src/test/resources/logback.xml | 40 ++ .../SpringBootAutoConfigurationMojo.java | 234 +++++++++--- 12 files changed, 844 insertions(+), 506 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/23c460f3/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelRestAutoConfiguration.java ---------------------------------------------------------------------- diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelRestAutoConfiguration.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelRestAutoConfiguration.java deleted file mode 100644 index ef58774..0000000 --- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelRestAutoConfiguration.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.camel.spring.boot; - -import org.apache.camel.CamelContext; -import org.apache.camel.model.rest.RestConstants; -import org.apache.camel.spi.RestConfiguration; -import org.apache.camel.util.IntrospectionSupport; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -@ConditionalOnProperty(name = "camel.rest.enabled", matchIfMissing = true) -@ConditionalOnBean(CamelAutoConfiguration.class) -@AutoConfigureAfter(CamelAutoConfiguration.class) -@EnableConfigurationProperties(CamelRestConfigurationProperties.class) -public class CamelRestAutoConfiguration { - @Autowired - private CamelContext camelContext; - @Autowired - private CamelRestConfigurationProperties config; - - @Bean(name = RestConstants.DEFAULT_REST_CONFIGURATION_ID) - @ConditionalOnClass(CamelContext.class) - @ConditionalOnMissingBean - public RestConfiguration restConfiguration() throws Exception { - final RestConfiguration configuration = new RestConfiguration(); - - // Copy properties - IntrospectionSupport.setProperties( - camelContext, - camelContext.getTypeConverter(), - configuration, - IntrospectionSupport.getNonNullProperties(config) - ); - - return configuration; - } -} http://git-wip-us.apache.org/repos/asf/camel/blob/23c460f3/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelRestConfigurationProperties.java ---------------------------------------------------------------------- diff --git a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelRestConfigurationProperties.java b/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelRestConfigurationProperties.java deleted file mode 100644 index cf1c855..0000000 --- a/components/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/CamelRestConfigurationProperties.java +++ /dev/null @@ -1,233 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.camel.spring.boot; - -import java.util.Map; - -import org.apache.camel.spi.RestConfiguration; -import org.springframework.boot.context.properties.ConfigurationProperties; - -@ConfigurationProperties(prefix = "camel.rest") -public class CamelRestConfigurationProperties { - // Delegate it so we do not have the CamelRestConfigurationProperties - // registered available also as RestConfiguration - private final RestConfiguration delegate; - - public CamelRestConfigurationProperties() { - this.delegate = new RestConfiguration(); - } - - public String getComponent() { - return delegate.getComponent(); - } - - public void setComponent(String componentName) { - delegate.setComponent(componentName); - } - - public String getApiComponent() { - return delegate.getApiComponent(); - } - - public void setApiComponent(String apiComponent) { - delegate.setApiComponent(apiComponent); - } - - public String getProducerComponent() { - return delegate.getProducerComponent(); - } - - public void setProducerComponent(String componentName) { - delegate.setProducerComponent(componentName); - } - - public String getProducerApiDoc() { - return delegate.getProducerApiDoc(); - } - - public void setProducerApiDoc(String producerApiDoc) { - delegate.setProducerApiDoc(producerApiDoc); - } - - public String getHost() { - return delegate.getHost(); - } - - public void setHost(String host) { - delegate.setHost(host); - } - - public String getScheme() { - return delegate.getScheme(); - } - - public void setScheme(String scheme) { - delegate.setScheme(scheme); - } - - public int getPort() { - return delegate.getPort(); - } - - public void setPort(int port) { - delegate.setPort(port); - } - - public String getContextPath() { - return delegate.getContextPath(); - } - - public void setContextPath(String contextPath) { - delegate.setContextPath(contextPath); - } - - public String getApiContextPath() { - return delegate.getApiContextPath(); - } - - public void setApiContextPath(String contextPath) { - delegate.setApiContextPath(contextPath); - } - - public String getApiContextRouteId() { - return delegate.getApiContextRouteId(); - } - - public void setApiContextRouteId(String apiContextRouteId) { - delegate.setApiContextRouteId(apiContextRouteId); - } - - public String getApiContextIdPattern() { - return delegate.getApiContextIdPattern(); - } - - public void setApiContextIdPattern(String apiContextIdPattern) { - delegate.setApiContextIdPattern(apiContextIdPattern); - } - - public boolean isApiContextListing() { - return delegate.isApiContextListing(); - } - - public void setApiContextListing(boolean apiContextListing) { - delegate.setApiContextListing(apiContextListing); - } - - public RestConfiguration.RestHostNameResolver getRestHostNameResolver() { - return delegate.getRestHostNameResolver(); - } - - public void setRestHostNameResolver(RestConfiguration.RestHostNameResolver restHostNameResolver) { - delegate.setRestHostNameResolver(restHostNameResolver); - } - - public void setRestHostNameResolver(String restHostNameResolver) { - delegate.setRestHostNameResolver(restHostNameResolver); - } - - public RestConfiguration.RestBindingMode getBindingMode() { - return delegate.getBindingMode(); - } - - public void setBindingMode(RestConfiguration.RestBindingMode bindingMode) { - delegate.setBindingMode(bindingMode); - } - - public void setBindingMode(String bindingMode) { - delegate.setBindingMode(bindingMode); - } - - public boolean isSkipBindingOnErrorCode() { - return delegate.isSkipBindingOnErrorCode(); - } - - public void setSkipBindingOnErrorCode(boolean skipBindingOnErrorCode) { - delegate.setSkipBindingOnErrorCode(skipBindingOnErrorCode); - } - - public boolean isEnableCORS() { - return delegate.isEnableCORS(); - } - - public void setEnableCORS(boolean enableCORS) { - delegate.setEnableCORS(enableCORS); - } - - public String getJsonDataFormat() { - return delegate.getJsonDataFormat(); - } - - public void setJsonDataFormat(String name) { - delegate.setJsonDataFormat(name); - } - - public String getXmlDataFormat() { - return delegate.getXmlDataFormat(); - } - - public void setXmlDataFormat(String name) { - delegate.setXmlDataFormat(name); - } - - public Map<String, Object> getComponentProperties() { - return delegate.getComponentProperties(); - } - - public void setComponentProperties(Map<String, Object> componentProperties) { - delegate.setComponentProperties(componentProperties); - } - - public Map<String, Object> getEndpointProperties() { - return delegate.getEndpointProperties(); - } - - public void setEndpointProperties(Map<String, Object> endpointProperties) { - delegate.setEndpointProperties(endpointProperties); - } - - public Map<String, Object> getConsumerProperties() { - return delegate.getConsumerProperties(); - } - - public void setConsumerProperties(Map<String, Object> consumerProperties) { - delegate.setConsumerProperties(consumerProperties); - } - - public Map<String, Object> getDataFormatProperties() { - return delegate.getDataFormatProperties(); - } - - public void setDataFormatProperties(Map<String, Object> dataFormatProperties) { - delegate.setDataFormatProperties(dataFormatProperties); - } - - public Map<String, Object> getApiProperties() { - return delegate.getApiProperties(); - } - - public void setApiProperties(Map<String, Object> apiProperties) { - delegate.setApiProperties(apiProperties); - } - - public Map<String, String> getCorsHeaders() { - return delegate.getCorsHeaders(); - } - - public void setCorsHeaders(Map<String, String> corsHeaders) { - delegate.setCorsHeaders(corsHeaders); - } -} http://git-wip-us.apache.org/repos/asf/camel/blob/23c460f3/components/camel-spring-boot/src/main/resources/META-INF/spring.factories ---------------------------------------------------------------------- diff --git a/components/camel-spring-boot/src/main/resources/META-INF/spring.factories b/components/camel-spring-boot/src/main/resources/META-INF/spring.factories index 10f5de7..ef14820 100644 --- a/components/camel-spring-boot/src/main/resources/META-INF/spring.factories +++ b/components/camel-spring-boot/src/main/resources/META-INF/spring.factories @@ -17,7 +17,6 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.apache.camel.spring.boot.CamelAutoConfiguration,\ -org.apache.camel.spring.boot.CamelRestAutoConfiguration,\ org.apache.camel.spring.boot.cloud.CamelCloudAutoConfiguration,\ org.apache.camel.spring.boot.cloud.CamelCloudServiceCallConfigurationAutoConfiguration,\ org.apache.camel.spring.boot.cloud.CamelCloudServiceDiscoveryAutoConfiguration,\ http://git-wip-us.apache.org/repos/asf/camel/blob/23c460f3/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/CamelRestTest.java ---------------------------------------------------------------------- diff --git a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/CamelRestTest.java b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/CamelRestTest.java deleted file mode 100644 index ab7fe56..0000000 --- a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/CamelRestTest.java +++ /dev/null @@ -1,167 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.camel.spring.boot; - -import java.util.Map; - -import org.apache.camel.CamelContext; -import org.apache.camel.Consumer; -import org.apache.camel.Processor; -import org.apache.camel.ProducerTemplate; -import org.apache.camel.builder.RouteBuilder; -import org.apache.camel.component.seda.SedaEndpoint; -import org.apache.camel.impl.ActiveMQUuidGenerator; -import org.apache.camel.spi.RestApiConsumerFactory; -import org.apache.camel.spi.RestConfiguration; -import org.apache.camel.spi.RestConsumerFactory; -import org.apache.camel.util.CamelContextHelper; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.junit4.SpringRunner; - - -@DirtiesContext -@RunWith(SpringRunner.class) -@EnableAutoConfiguration -@SpringBootTest( - classes = { - CamelRestTest.class, - CamelRestTest.TestConfiguration.class - }, - properties = { - "debug=false", - "camel.springboot.xml-rests=false", - "camel.springboot.xml-routes=false", - "camel.rest.enabled=true", - "camel.rest.component=dummy-rest", - "camel.rest.host=localhost" - } -) -public class CamelRestTest { - @Autowired - private CamelContext context; - - @Test - public void test() throws Exception { - ProducerTemplate template = context.createProducerTemplate(); - String result = template.requestBody("seda:get-say-hello", "test", String.class); - - Assert.assertEquals("Hello World", result); - } - - // *********************************** - // Configuration - // *********************************** - - @Configuration - public static class TestConfiguration { - @Bean(name = "dummy-rest") - public RestConsumerFactory dummyRestConsumerFactory() { - return new TestConsumerFactory(); - } - - @Bean - public RouteBuilder routeBuilder() { - return new RouteBuilder() { - @Override - public void configure() throws Exception { - rest("/say/hello") - .get().to("direct:hello"); - from("direct:hello") - .transform().constant("Hello World"); - } - }; - } - } - - // *********************************** - // Rest Helpers - // *********************************** - - private static final class TestConsumerFactory implements RestConsumerFactory, RestApiConsumerFactory { - private Object dummy; - - public Object getDummy() { - return dummy; - } - - public void setDummy(Object dummy) { - this.dummy = dummy; - } - - @Override - public Consumer createConsumer( - CamelContext camelContext, - Processor processor, - String verb, - String basePath, - String uriTemplate, - String consumes, - String produces, - RestConfiguration configuration, - Map<String, Object> parameters) throws Exception { - - // just use a seda endpoint for testing purpose - String id; - if (uriTemplate != null) { - id = ActiveMQUuidGenerator.generateSanitizedId(basePath + uriTemplate); - } else { - id = ActiveMQUuidGenerator.generateSanitizedId(basePath); - } - // remove leading dash as we add that ourselves - if (id.startsWith("-")) { - id = id.substring(1); - } - - if (configuration.getConsumerProperties() != null) { - String ref = (String) configuration.getConsumerProperties().get("dummy"); - if (ref != null) { - dummy = CamelContextHelper.mandatoryLookup(camelContext, ref.substring(1)); - } - } - - SedaEndpoint seda = camelContext.getEndpoint("seda:" + verb + "-" + id, SedaEndpoint.class); - return seda.createConsumer(processor); - } - - @Override - public Consumer createApiConsumer( - CamelContext camelContext, - Processor processor, - String contextPath, - RestConfiguration configuration, - Map<String, Object> parameters) throws Exception { - - // just use a seda endpoint for testing purpose - String id = ActiveMQUuidGenerator.generateSanitizedId(contextPath); - // remove leading dash as we add that ourselves - if (id.startsWith("-")) { - id = id.substring(1); - } - - SedaEndpoint seda = camelContext.getEndpoint("seda:api:" + "-" + id, SedaEndpoint.class); - return seda.createConsumer(processor); - } - } -} http://git-wip-us.apache.org/repos/asf/camel/blob/23c460f3/platforms/spring-boot/components-starter/camel-core-starter/pom.xml ---------------------------------------------------------------------- diff --git a/platforms/spring-boot/components-starter/camel-core-starter/pom.xml b/platforms/spring-boot/components-starter/camel-core-starter/pom.xml index d441b3f..49159da 100644 --- a/platforms/spring-boot/components-starter/camel-core-starter/pom.xml +++ b/platforms/spring-boot/components-starter/camel-core-starter/pom.xml @@ -37,6 +37,11 @@ <artifactId>camel-core</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-spring-boot-starter</artifactId> + <scope>test</scope> + </dependency> <!--START OF GENERATED CODE--> <dependency> <groupId>com.github.ben-manes.caffeine</groupId> http://git-wip-us.apache.org/repos/asf/camel/blob/23c460f3/platforms/spring-boot/components-starter/camel-core-starter/src/main/java/org/apache/camel/model/rest/springboot/RestConfigurationDefinitionAutoConfiguration.java ---------------------------------------------------------------------- diff --git a/platforms/spring-boot/components-starter/camel-core-starter/src/main/java/org/apache/camel/model/rest/springboot/RestConfigurationDefinitionAutoConfiguration.java b/platforms/spring-boot/components-starter/camel-core-starter/src/main/java/org/apache/camel/model/rest/springboot/RestConfigurationDefinitionAutoConfiguration.java new file mode 100644 index 0000000..3ea9cbe --- /dev/null +++ b/platforms/spring-boot/components-starter/camel-core-starter/src/main/java/org/apache/camel/model/rest/springboot/RestConfigurationDefinitionAutoConfiguration.java @@ -0,0 +1,65 @@ +/** + * 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.model.rest.springboot; + +import java.util.HashMap; +import java.util.Map; +import org.apache.camel.CamelContext; +import org.apache.camel.model.rest.RestConstants; +import org.apache.camel.spi.RestConfiguration; +import org.apache.camel.util.IntrospectionSupport; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Lazy; + +/** + * Generated by camel-package-maven-plugin - do not edit this file! + */ +@Configuration +@ConditionalOnBean(type = "org.apache.camel.spring.boot.CamelAutoConfiguration") +@ConditionalOnProperty(name = "camel.rest.enabled", matchIfMissing = true) +@AutoConfigureAfter(name = "org.apache.camel.spring.boot.CamelAutoConfiguration") +@EnableConfigurationProperties(RestConfigurationDefinitionProperties.class) +public class RestConfigurationDefinitionAutoConfiguration { + + @Autowired + private CamelContext camelContext; + @Autowired + private RestConfigurationDefinitionProperties config; + + @Lazy + @Bean(name = RestConstants.DEFAULT_REST_CONFIGURATION_ID) + @ConditionalOnClass(CamelContext.class) + @ConditionalOnMissingBean + public RestConfiguration configureRestConfigurationDefinition() + throws Exception { + Map<String, Object> properties = new HashMap<>(); + IntrospectionSupport.getProperties(config, properties, null, false); + RestConfiguration definition = new RestConfiguration(); + IntrospectionSupport.setProperties(camelContext, + camelContext.getTypeConverter(), definition, properties); + definition.setEnableCORS(config.getEnableCors()); + return definition; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/23c460f3/platforms/spring-boot/components-starter/camel-core-starter/src/main/java/org/apache/camel/model/rest/springboot/RestConfigurationDefinitionProperties.java ---------------------------------------------------------------------- diff --git a/platforms/spring-boot/components-starter/camel-core-starter/src/main/java/org/apache/camel/model/rest/springboot/RestConfigurationDefinitionProperties.java b/platforms/spring-boot/components-starter/camel-core-starter/src/main/java/org/apache/camel/model/rest/springboot/RestConfigurationDefinitionProperties.java new file mode 100644 index 0000000..ec134c2 --- /dev/null +++ b/platforms/spring-boot/components-starter/camel-core-starter/src/main/java/org/apache/camel/model/rest/springboot/RestConfigurationDefinitionProperties.java @@ -0,0 +1,374 @@ +/** + * 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.model.rest.springboot; + +import java.util.List; +import org.apache.camel.model.rest.RestBindingMode; +import org.apache.camel.model.rest.RestHostNameResolver; +import org.apache.camel.model.rest.RestPropertyDefinition; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * To configure rest + * + * Generated by camel-package-maven-plugin - do not edit this file! + */ +@ConfigurationProperties(prefix = "camel.rest") +public class RestConfigurationDefinitionProperties { + + /** + * The Camel Rest component to use for the REST transport (consumer) such as + * restlet spark-rest. If no component has been explicit configured then + * Camel will lookup if there is a Camel component that integrates with the + * Rest DSL or if a org.apache.camel.spi.RestConsumerFactory is registered + * in the registry. If either one is found then that is being used. + */ + private String component; + /** + * The name of the Camel component to use as the REST API (such as swagger) + */ + private String apiComponent = "swagger"; + /** + * Sets the name of the Camel component to use as the REST producer + */ + private String producerComponent; + /** + * The scheme to use for exposing the REST service. Usually http or https is + * supported. The default value is http + */ + private String scheme; + /** + * The hostname to use for exposing the REST service. + */ + private String host; + /** + * The port number to use for exposing the REST service. Notice if you use + * servlet component then the port number configured here does not apply as + * the port number in use is the actual port number the servlet component is + * using. eg if using Apache Tomcat its the tomcat http port if using Apache + * Karaf its the HTTP service in Karaf that uses port 8181 by default etc. + * Though in those situations setting the port number here allows tooling + * and JMX to know the port number so its recommended to set the port number + * to the number that the servlet engine uses. + */ + private String port; + /** + * Sets the location of the api document (swagger api) the REST producer + * will use to validate the REST uri and query parameters are valid + * accordingly to the api document. This requires adding camel-swagger-java + * to the classpath and any miss configuration will let Camel fail on + * startup and report the error(s). The location of the api document is + * loaded from classpath by default but you can use file: or http: to refer + * to resources to load from file or http url. + */ + private String producerApiDoc; + /** + * Sets a leading context-path the REST services will be using. This can be + * used when using components such as camel-servlet where the deployed web + * application is deployed using a context-path. Or for components such as + * camel-jetty or camel-netty4-http that includes a HTTP server. + */ + private String contextPath; + /** + * Sets a leading API context-path the REST API services will be using. This + * can be used when using components such as camel-servlet where the + * deployed web application is deployed using a context-path. + */ + private String apiContextPath; + /** + * Sets the route id to use for the route that services the REST API. The + * route will by default use an auto assigned route id. + */ + private String apiContextRouteId; + /** + * Sets an CamelContext id pattern to only allow Rest APIs from rest + * services within CamelContext's which name matches the pattern. The + * pattern name refers to the CamelContext name to match on the current + * CamelContext only. For any other value the pattern uses the rules from + * link org.apache.camel.util.EndpointHelpermatchPattern(String String) + */ + private String apiContextIdPattern; + /** + * Sets whether listing of all available CamelContext's with REST services + * in the JVM is enabled. If enabled it allows to discover these contexts if + * false then only the current CamelContext is in use. + */ + private Boolean apiContextListing = false; + /** + * If no hostname has been explicit configured then this resolver is used to + * compute the hostname the REST service will be using. + */ + private RestHostNameResolver hostNameResolver; + /** + * Sets the binding mode to use. The default value is off + */ + private RestBindingMode bindingMode; + /** + * Whether to skip binding on output if there is a custom HTTP error code + * header. This allows to build custom error messages that do not bind to + * json / xml etc as success messages otherwise will do. + */ + private Boolean skipBindingOnErrorCode = false; + /** + * Whether to enable CORS headers in the HTTP response. The default value is + * false. + */ + private Boolean enableCors = false; + /** + * Name of specific json data format to use. By default json-jackson will be + * used. Important: This option is only for setting a custom name of the + * data format not to refer to an existing data format instance. + */ + private String jsonDataFormat; + /** + * Name of specific XML data format to use. By default jaxb will be used. + * Important: This option is only for setting a custom name of the data + * format not to refer to an existing data format instance. + */ + private String xmlDataFormat; + /** + * Allows to configure as many additional properties for the rest component + * in use. + */ + private List<RestPropertyDefinition> componentProperty; + /** + * Allows to configure as many additional properties for the rest endpoint + * in use. + */ + private List<RestPropertyDefinition> endpointProperty; + /** + * Allows to configure as many additional properties for the rest consumer + * in use. + */ + private List<RestPropertyDefinition> consumerProperty; + /** + * Allows to configure as many additional properties for the data formats in + * use. For example set property prettyPrint to true to have json outputted + * in pretty mode. The properties can be prefixed to denote the option is + * only for either JSON or XML and for either the IN or the OUT. The + * prefixes are: json.in. json.out. xml.in. xml.out. For example a key with + * value xml.out.mustBeJAXBElement is only for the XML data format for the + * outgoing. A key without a prefix is a common key for all situations. + */ + private List<RestPropertyDefinition> dataFormatProperty; + /** + * Allows to configure as many additional properties for the api + * documentation (swagger). For example set property api.title to my cool + * stuff + */ + private List<RestPropertyDefinition> apiProperty; + /** + * Allows to configure custom CORS headers. + */ + private List<RestPropertyDefinition> corsHeaders; + + public String getComponent() { + return component; + } + + public void setComponent(String component) { + this.component = component; + } + + public String getApiComponent() { + return apiComponent; + } + + public void setApiComponent(String apiComponent) { + this.apiComponent = apiComponent; + } + + public String getProducerComponent() { + return producerComponent; + } + + public void setProducerComponent(String producerComponent) { + this.producerComponent = producerComponent; + } + + public String getScheme() { + return scheme; + } + + public void setScheme(String scheme) { + this.scheme = scheme; + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public String getPort() { + return port; + } + + public void setPort(String port) { + this.port = port; + } + + public String getProducerApiDoc() { + return producerApiDoc; + } + + public void setProducerApiDoc(String producerApiDoc) { + this.producerApiDoc = producerApiDoc; + } + + public String getContextPath() { + return contextPath; + } + + public void setContextPath(String contextPath) { + this.contextPath = contextPath; + } + + public String getApiContextPath() { + return apiContextPath; + } + + public void setApiContextPath(String apiContextPath) { + this.apiContextPath = apiContextPath; + } + + public String getApiContextRouteId() { + return apiContextRouteId; + } + + public void setApiContextRouteId(String apiContextRouteId) { + this.apiContextRouteId = apiContextRouteId; + } + + public String getApiContextIdPattern() { + return apiContextIdPattern; + } + + public void setApiContextIdPattern(String apiContextIdPattern) { + this.apiContextIdPattern = apiContextIdPattern; + } + + public Boolean getApiContextListing() { + return apiContextListing; + } + + public void setApiContextListing(Boolean apiContextListing) { + this.apiContextListing = apiContextListing; + } + + public RestHostNameResolver getHostNameResolver() { + return hostNameResolver; + } + + public void setHostNameResolver(RestHostNameResolver hostNameResolver) { + this.hostNameResolver = hostNameResolver; + } + + public RestBindingMode getBindingMode() { + return bindingMode; + } + + public void setBindingMode(RestBindingMode bindingMode) { + this.bindingMode = bindingMode; + } + + public Boolean getSkipBindingOnErrorCode() { + return skipBindingOnErrorCode; + } + + public void setSkipBindingOnErrorCode(Boolean skipBindingOnErrorCode) { + this.skipBindingOnErrorCode = skipBindingOnErrorCode; + } + + public Boolean getEnableCors() { + return enableCors; + } + + public void setEnableCors(Boolean enableCors) { + this.enableCors = enableCors; + } + + public String getJsonDataFormat() { + return jsonDataFormat; + } + + public void setJsonDataFormat(String jsonDataFormat) { + this.jsonDataFormat = jsonDataFormat; + } + + public String getXmlDataFormat() { + return xmlDataFormat; + } + + public void setXmlDataFormat(String xmlDataFormat) { + this.xmlDataFormat = xmlDataFormat; + } + + public List<RestPropertyDefinition> getComponentProperty() { + return componentProperty; + } + + public void setComponentProperty( + List<RestPropertyDefinition> componentProperty) { + this.componentProperty = componentProperty; + } + + public List<RestPropertyDefinition> getEndpointProperty() { + return endpointProperty; + } + + public void setEndpointProperty( + List<RestPropertyDefinition> endpointProperty) { + this.endpointProperty = endpointProperty; + } + + public List<RestPropertyDefinition> getConsumerProperty() { + return consumerProperty; + } + + public void setConsumerProperty( + List<RestPropertyDefinition> consumerProperty) { + this.consumerProperty = consumerProperty; + } + + public List<RestPropertyDefinition> getDataFormatProperty() { + return dataFormatProperty; + } + + public void setDataFormatProperty( + List<RestPropertyDefinition> dataFormatProperty) { + this.dataFormatProperty = dataFormatProperty; + } + + public List<RestPropertyDefinition> getApiProperty() { + return apiProperty; + } + + public void setApiProperty(List<RestPropertyDefinition> apiProperty) { + this.apiProperty = apiProperty; + } + + public List<RestPropertyDefinition> getCorsHeaders() { + return corsHeaders; + } + + public void setCorsHeaders(List<RestPropertyDefinition> corsHeaders) { + this.corsHeaders = corsHeaders; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/23c460f3/platforms/spring-boot/components-starter/camel-core-starter/src/main/resources/META-INF/spring.factories ---------------------------------------------------------------------- diff --git a/platforms/spring-boot/components-starter/camel-core-starter/src/main/resources/META-INF/spring.factories b/platforms/spring-boot/components-starter/camel-core-starter/src/main/resources/META-INF/spring.factories index a42ae0c..44a3c18 100644 --- a/platforms/spring-boot/components-starter/camel-core-starter/src/main/resources/META-INF/spring.factories +++ b/platforms/spring-boot/components-starter/camel-core-starter/src/main/resources/META-INF/spring.factories @@ -54,4 +54,6 @@ org.apache.camel.component.dataset.springboot.DataSetComponentAutoConfiguration, org.apache.camel.component.binding.springboot.BindingNameComponentAutoConfiguration,\ org.apache.camel.component.bean.springboot.BeanComponentAutoConfiguration,\ org.apache.camel.component.dataformat.springboot.DataFormatComponentAutoConfiguration,\ -org.apache.camel.component.rest.springboot.RestApiComponentAutoConfiguration +org.apache.camel.component.rest.springboot.RestApiComponentAutoConfiguration,\ +org.apache.camel.model.rest.springboot.RestConfigurationDefinitionAutoConfiguration + http://git-wip-us.apache.org/repos/asf/camel/blob/23c460f3/platforms/spring-boot/components-starter/camel-core-starter/src/test/java/org/apache/camel/model/rest/springboot/CamelRestTest.java ---------------------------------------------------------------------- diff --git a/platforms/spring-boot/components-starter/camel-core-starter/src/test/java/org/apache/camel/model/rest/springboot/CamelRestTest.java b/platforms/spring-boot/components-starter/camel-core-starter/src/test/java/org/apache/camel/model/rest/springboot/CamelRestTest.java new file mode 100644 index 0000000..cae2ae4 --- /dev/null +++ b/platforms/spring-boot/components-starter/camel-core-starter/src/test/java/org/apache/camel/model/rest/springboot/CamelRestTest.java @@ -0,0 +1,167 @@ +/** + * 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.model.rest.springboot; + +import java.util.Map; + +import org.apache.camel.CamelContext; +import org.apache.camel.Consumer; +import org.apache.camel.Processor; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.seda.SedaEndpoint; +import org.apache.camel.impl.ActiveMQUuidGenerator; +import org.apache.camel.spi.RestApiConsumerFactory; +import org.apache.camel.spi.RestConfiguration; +import org.apache.camel.spi.RestConsumerFactory; +import org.apache.camel.util.CamelContextHelper; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringRunner; + + +@DirtiesContext +@RunWith(SpringRunner.class) +@EnableAutoConfiguration +@SpringBootTest( + classes = { + CamelRestTest.class, + CamelRestTest.TestConfiguration.class + }, + properties = { + "debug=false", + "camel.springboot.xml-rests=false", + "camel.springboot.xml-routes=false", + "camel.rest.enabled=true", + "camel.rest.component=dummy-rest", + "camel.rest.host=localhost" + } +) +public class CamelRestTest { + @Autowired + private CamelContext context; + + @Test + public void test() throws Exception { + ProducerTemplate template = context.createProducerTemplate(); + String result = template.requestBody("seda:get-say-hello", "test", String.class); + + Assert.assertEquals("Hello World", result); + } + + // *********************************** + // Configuration + // *********************************** + + @Configuration + public static class TestConfiguration { + @Bean(name = "dummy-rest") + public RestConsumerFactory dummyRestConsumerFactory() { + return new TestConsumerFactory(); + } + + @Bean + public RouteBuilder routeBuilder() { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + rest("/say/hello") + .get().to("direct:hello"); + from("direct:hello") + .transform().constant("Hello World"); + } + }; + } + } + + // *********************************** + // Rest Helpers + // *********************************** + + private static final class TestConsumerFactory implements RestConsumerFactory, RestApiConsumerFactory { + private Object dummy; + + public Object getDummy() { + return dummy; + } + + public void setDummy(Object dummy) { + this.dummy = dummy; + } + + @Override + public Consumer createConsumer( + CamelContext camelContext, + Processor processor, + String verb, + String basePath, + String uriTemplate, + String consumes, + String produces, + RestConfiguration configuration, + Map<String, Object> parameters) throws Exception { + + // just use a seda endpoint for testing purpose + String id; + if (uriTemplate != null) { + id = ActiveMQUuidGenerator.generateSanitizedId(basePath + uriTemplate); + } else { + id = ActiveMQUuidGenerator.generateSanitizedId(basePath); + } + // remove leading dash as we add that ourselves + if (id.startsWith("-")) { + id = id.substring(1); + } + + if (configuration.getConsumerProperties() != null) { + String ref = (String) configuration.getConsumerProperties().get("dummy"); + if (ref != null) { + dummy = CamelContextHelper.mandatoryLookup(camelContext, ref.substring(1)); + } + } + + SedaEndpoint seda = camelContext.getEndpoint("seda:" + verb + "-" + id, SedaEndpoint.class); + return seda.createConsumer(processor); + } + + @Override + public Consumer createApiConsumer( + CamelContext camelContext, + Processor processor, + String contextPath, + RestConfiguration configuration, + Map<String, Object> parameters) throws Exception { + + // just use a seda endpoint for testing purpose + String id = ActiveMQUuidGenerator.generateSanitizedId(contextPath); + // remove leading dash as we add that ourselves + if (id.startsWith("-")) { + id = id.substring(1); + } + + SedaEndpoint seda = camelContext.getEndpoint("seda:api:" + "-" + id, SedaEndpoint.class); + return seda.createConsumer(processor); + } + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/23c460f3/platforms/spring-boot/components-starter/camel-core-starter/src/test/resources/application.properties ---------------------------------------------------------------------- diff --git a/platforms/spring-boot/components-starter/camel-core-starter/src/test/resources/application.properties b/platforms/spring-boot/components-starter/camel-core-starter/src/test/resources/application.properties new file mode 100644 index 0000000..e69de29 http://git-wip-us.apache.org/repos/asf/camel/blob/23c460f3/platforms/spring-boot/components-starter/camel-core-starter/src/test/resources/logback.xml ---------------------------------------------------------------------- diff --git a/platforms/spring-boot/components-starter/camel-core-starter/src/test/resources/logback.xml b/platforms/spring-boot/components-starter/camel-core-starter/src/test/resources/logback.xml new file mode 100644 index 0000000..185b32e --- /dev/null +++ b/platforms/spring-boot/components-starter/camel-core-starter/src/test/resources/logback.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<configuration> + + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <!-- encoders are assigned the type + ch.qos.logback.classic.encoder.PatternLayoutEncoder by default --> + <encoder> + <pattern>%d{HH:mm:ss.SSS} [%-15.15thread] %-5level %-30.30logger - %msg%n</pattern> + </encoder> + </appender> + + <appender name="FILE" class="ch.qos.logback.core.FileAppender"> + <encoder> + <pattern>%d{HH:mm:ss.SSS} [%-15.15thread] %-5level %-30.30logger - %msg%n</pattern> + </encoder> + <file>target/camel-core-starter-test.log</file> + </appender> + + <root level="INFO"> + <!--<appender-ref ref="STDOUT"/>--> + <appender-ref ref="FILE"/> + </root> + +</configuration> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/camel/blob/23c460f3/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/SpringBootAutoConfigurationMojo.java ---------------------------------------------------------------------- diff --git a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/SpringBootAutoConfigurationMojo.java b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/SpringBootAutoConfigurationMojo.java index 4af0892..d7eac27 100644 --- a/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/SpringBootAutoConfigurationMojo.java +++ b/tooling/maven/camel-package-maven-plugin/src/main/java/org/apache/camel/maven/packaging/SpringBootAutoConfigurationMojo.java @@ -71,12 +71,14 @@ import org.jboss.forge.roaster.model.source.MethodSource; import org.jboss.forge.roaster.model.source.PropertySource; import org.jboss.forge.roaster.model.util.Formatter; import org.jboss.forge.roaster.model.util.Strings; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionMessage; import org.springframework.boot.autoconfigure.condition.ConditionOutcome; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.SpringBootCondition; import org.springframework.boot.bind.RelaxedPropertyResolver; import org.springframework.boot.context.properties.DeprecatedConfigurationProperty; @@ -207,7 +209,7 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo { String pkg = model.getJavaType().substring(0, pos) + ".springboot"; // Generate properties, auto-configuration happens in camel-hystrix-starter - createOtherModelConfigurationSource(pkg, model, "camel.hystrix"); + createOtherModelConfigurationSource(pkg, model, "camel.hystrix", true); } // Consul @@ -219,7 +221,7 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo { String pkg = model.getJavaType().substring(0, pos) + ".springboot"; // Generate properties, auto-configuration happens in camel-consul-starter - createOtherModelConfigurationSource(pkg, model, "camel.cloud.consul.service-discovery"); + createOtherModelConfigurationSource(pkg, model, "camel.cloud.consul.service-discovery", true); } // DNS @@ -231,7 +233,7 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo { String pkg = model.getJavaType().substring(0, pos) + ".springboot"; // Generate properties, auto-configuration happens in camel-dns-starter - createOtherModelConfigurationSource(pkg, model, "camel.cloud.dns.service-discovery"); + createOtherModelConfigurationSource(pkg, model, "camel.cloud.dns.service-discovery", true); } // Etcd @@ -243,7 +245,7 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo { String pkg = model.getJavaType().substring(0, pos) + ".springboot"; // Generate properties, auto-configuration happens in camel-etcd-starter - createOtherModelConfigurationSource(pkg, model, "camel.cloud.etcd.service-discovery"); + createOtherModelConfigurationSource(pkg, model, "camel.cloud.etcd.service-discovery", true); } // Kubernetes @@ -255,14 +257,27 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo { String pkg = model.getJavaType().substring(0, pos) + ".springboot"; // Generate properties, auto-configuration happens in camel-kubernetes-starter - createOtherModelConfigurationSource(pkg, model, "camel.cloud.kubernetes.service-discovery"); + createOtherModelConfigurationSource(pkg, model, "camel.cloud.kubernetes.service-discovery", true); + } + + // Rest + json = loadModelJson(files, "restConfiguration"); + if (json != null) { + OtherModel model = generateOtherModel(json); + + int pos = model.getJavaType().lastIndexOf("."); + String pkg = model.getJavaType().substring(0, pos) + ".springboot"; + + // Generate properties, auto-configuration happens in camel-kubernetes-starter + createRestConfigurationSource(pkg, model, "camel.rest"); + createRestModuleAutoConfigurationSource(pkg, model); } } - private void createOtherModelConfigurationSource(String packageName, OtherModel model, String propertiesPrefix) throws MojoFailureException { + private void createOtherModelConfigurationSource(String packageName, OtherModel model, String propertiesPrefix, boolean generatedNestedConfig) throws MojoFailureException { final int pos = model.getJavaType().lastIndexOf("."); - final String commonName = model.getJavaType().substring(pos + 1) + "Common"; - final String configName = model.getJavaType().substring(pos + 1) + "Properties"; + final String commonName = model.getJavaType().substring(pos + 1) + (generatedNestedConfig ? "Common" : "Properties"); + final String configName = model.getJavaType().substring(pos + 1) + (generatedNestedConfig ? "Properties" : null); // Common base class JavaClassSource commonClass = Roaster.create(JavaClassSource.class); @@ -310,51 +325,182 @@ public class SpringBootAutoConfigurationMojo extends AbstractMojo { } } + sortImports(commonClass); + writeSourceIfChanged(commonClass, packageName.replaceAll("\\.", "\\/") + "/" + commonName + ".java"); + // Config class - JavaClassSource configClass = Roaster.create(JavaClassSource.class); - configClass.setPackage(packageName); - configClass.setName(configName); - configClass.extendSuperType(commonClass); - configClass.addAnnotation("org.springframework.boot.context.properties.ConfigurationProperties").setStringValue("prefix", propertiesPrefix); - configClass.addImport(Map.class); - configClass.addImport(HashMap.class); - configClass.removeImport(commonClass); - - configClass.addField() - .setName("enabled") - .setType(boolean.class) + if (generatedNestedConfig) { + JavaClassSource configClass = Roaster.create(JavaClassSource.class); + configClass.setPackage(packageName); + configClass.setName(configName); + configClass.extendSuperType(commonClass); + configClass.addAnnotation("org.springframework.boot.context.properties.ConfigurationProperties").setStringValue("prefix", propertiesPrefix); + configClass.addImport(Map.class); + configClass.addImport(HashMap.class); + configClass.removeImport(commonClass); + + configClass.addField() + .setName("enabled") + .setType(boolean.class) + .setPrivate() + .setLiteralInitializer("true") + .getJavaDoc().setFullText("Enable the component"); + configClass.addField("Map<String, " + commonName + "> configurations = new HashMap<>()") + .setPrivate() + .getJavaDoc().setFullText("Define additional configuration definitions"); + + MethodSource<JavaClassSource> method; + + method = configClass.addMethod(); + method.setName("getConfigurations"); + method.setReturnType("Map<String, " + commonName + ">"); + method.setPublic(); + method.setBody("return configurations;"); + + method = configClass.addMethod(); + method.setName("isEnabled"); + method.setReturnType(boolean.class); + method.setPublic(); + method.setBody("return enabled;"); + + method = configClass.addMethod(); + method.setName("setEnabled"); + method.addParameter(boolean.class, "enabled"); + method.setPublic(); + method.setBody("this.enabled = enabled;"); + + + sortImports(configClass); + writeSourceIfChanged(configClass, packageName.replaceAll("\\.", "\\/") + "/" + configName + ".java"); + } + } + + private void createRestConfigurationSource(String packageName, OtherModel model, String propertiesPrefix) throws MojoFailureException { + final int pos = model.getJavaType().lastIndexOf("."); + final String className = model.getJavaType().substring(pos + 1) + "Properties"; + + // Common base class + JavaClassSource javaClass = Roaster.create(JavaClassSource.class); + javaClass.setPackage(packageName); + javaClass.setName(className); + javaClass.addAnnotation("org.springframework.boot.context.properties.ConfigurationProperties").setStringValue("prefix", propertiesPrefix); + + String doc = "Generated by camel-package-maven-plugin - do not edit this file!"; + if (!Strings.isBlank(model.getDescription())) { + doc = model.getDescription() + "\n\n" + doc; + } + javaClass.getJavaDoc().setFullText(doc); + + for (OtherOptionModel option : model.getOptions()) { + String type = option.getJavaType(); + String name = option.getName(); + + if ("id".equalsIgnoreCase(name) || "parent".equalsIgnoreCase(name) || "camelContext".equalsIgnoreCase(name)) { + // Skip them as they should not be set via spring boot + continue; + } + + if ("java.util.List<org.apache.camel.model.PropertyDefinition>".equalsIgnoreCase(type)) { + type = "java.util.Map<java.lang.String, java.lang.String>"; + } + + if ("enableCORS".equalsIgnoreCase(name)) { + name = "enableCors"; + } + + // generate inner class for non-primitive options + PropertySource<JavaClassSource> prop = javaClass.addProperty(type, name); + if (!Strings.isBlank(option.getDescription())) { + prop.getField().getJavaDoc().setFullText(option.getDescription()); + } + if (!Strings.isBlank(option.getDefaultValue())) { + if ("java.lang.String".equals(type)) { + prop.getField().setStringInitializer(option.getDefaultValue()); + } else if ("long".equals(type) || "java.lang.Long".equals(type)) { + // the value should be a Long number + String value = option.getDefaultValue() + "L"; + prop.getField().setLiteralInitializer(value); + } else if ("integer".equals(option.getType()) || "boolean".equals(option.getType())) { + prop.getField().setLiteralInitializer(option.getDefaultValue()); + } else if (!Strings.isBlank(option.getEnums())) { + String enumShortName = type.substring(type.lastIndexOf(".") + 1); + prop.getField().setLiteralInitializer(enumShortName + "." + option.getDefaultValue()); + javaClass.addImport(model.getJavaType()); + } + } + } + + sortImports(javaClass); + writeSourceIfChanged(javaClass, packageName.replaceAll("\\.", "\\/") + "/" + className + ".java"); + } + + private void createRestModuleAutoConfigurationSource(String packageName, OtherModel model) throws MojoFailureException { + final JavaClassSource javaClass = Roaster.create(JavaClassSource.class); + final int pos = model.getJavaType().lastIndexOf("."); + final String name = model.getJavaType().substring(pos + 1) + "AutoConfiguration"; + final String configType = model.getJavaType().substring(pos + 1) + "Properties"; + + javaClass.setPackage(packageName); + javaClass.setName(name); + + String doc = "Generated by camel-package-maven-plugin - do not edit this file!"; + javaClass.getJavaDoc().setFullText(doc); + + javaClass.addAnnotation(Configuration.class); + javaClass.addAnnotation(ConditionalOnBean.class).setStringValue("type", "org.apache.camel.spring.boot.CamelAutoConfiguration"); + javaClass.addAnnotation(ConditionalOnProperty.class).setStringValue("name", "camel.rest.enabled").setLiteralValue("matchIfMissing", "true"); + javaClass.addAnnotation(AutoConfigureAfter.class).setStringValue("name", "org.apache.camel.spring.boot.CamelAutoConfiguration"); + javaClass.addAnnotation(EnableConfigurationProperties.class).setLiteralValue("value", configType + ".class"); + + javaClass.addImport("java.util.Map"); + javaClass.addImport("java.util.HashMap"); + javaClass.addImport("org.apache.camel.util.IntrospectionSupport"); + javaClass.addImport("org.apache.camel.CamelContext"); + javaClass.addImport("org.apache.camel.model.rest.RestConstants"); + javaClass.addImport("org.apache.camel.spi.RestConfiguration"); + + javaClass.addField() + .setName("camelContext") + .setType("org.apache.camel.CamelContext") .setPrivate() - .setLiteralInitializer("true") - .getJavaDoc().setFullText("Enable the component"); - configClass.addField("Map<String, " + commonName + "> configurations = new HashMap<>()") + .addAnnotation(Autowired.class); + javaClass.addField() + .setName("config") + .setType(configType) .setPrivate() - .getJavaDoc().setFullText("Define additional configuration definitions"); + .addAnnotation(Autowired.class); MethodSource<JavaClassSource> method; - method = configClass.addMethod(); - method.setName("getConfigurations"); - method.setReturnType("Map<String, " + commonName + ">"); - method.setPublic(); - method.setBody("return configurations;"); - - method = configClass.addMethod(); - method.setName("isEnabled"); - method.setReturnType(boolean.class); + // Configuration + method = javaClass.addMethod(); + method.setName("configure" + model.getShortJavaType()); method.setPublic(); - method.setBody("return enabled;"); - - method = configClass.addMethod(); - method.setName("setEnabled"); - method.addParameter(boolean.class, "enabled"); - method.setPublic(); - method.setBody("this.enabled = enabled;"); + method.addThrows(Exception.class); + method.setReturnType("org.apache.camel.spi.RestConfiguration"); + method.addAnnotation(Lazy.class); + method.addAnnotation(Bean.class).setLiteralValue("name", "RestConstants.DEFAULT_REST_CONFIGURATION_ID"); + method.addAnnotation(ConditionalOnClass.class).setLiteralValue("value", "CamelContext.class"); + method.addAnnotation(ConditionalOnMissingBean.class); + method.setBody("" + + "Map<String, Object> properties = new HashMap<>();\n" + + "IntrospectionSupport.getProperties(config, properties, null, false);\n" + + "\n" + + "RestConfiguration definition = new RestConfiguration();\n" + + "IntrospectionSupport.setProperties(camelContext, camelContext.getTypeConverter(), definition, properties);\n" + + "\n" + + "// Workaround for spring-boot properties name as It would appear\n" + + "// as enable-c-o-r-s if left uppercase in Configuration\n" + + "definition.setEnableCORS(config.getEnableCors());\n" + + "\n" + + "return definition;" + ); - sortImports(commonClass); - sortImports(configClass); + sortImports(javaClass); - writeSourceIfChanged(commonClass, packageName.replaceAll("\\.", "\\/") + "/" + commonName + ".java"); - writeSourceIfChanged(configClass, packageName.replaceAll("\\.", "\\/") + "/" + configName + ".java"); + String fileName = packageName.replaceAll("\\.", "\\/") + "/" + name + ".java"; + writeSourceIfChanged(javaClass, fileName); + writeComponentSpringFactorySource(packageName, name); } private void executeComponent() throws MojoExecutionException, MojoFailureException {
