CAMEL-8545: camel-swagger-java to run outside servlet - work in progress
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/646c9bcb Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/646c9bcb Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/646c9bcb Branch: refs/heads/master Commit: 646c9bcb2067070b9b88116dd3139af8ce3eaf00 Parents: b88093c Author: Claus Ibsen <davscl...@apache.org> Authored: Tue Sep 22 16:48:17 2015 +0200 Committer: Claus Ibsen <davscl...@apache.org> Committed: Wed Sep 23 07:51:03 2015 +0200 ---------------------------------------------------------------------- .../camel/spi/RestApiResponseAdapter.java | 3 +- .../spi/RestApiResponseAdapterFactory.java | 34 +++++++++++ .../netty4/http/NettyHttpComponent.java | 14 ++++- .../http/NettyRestApiResponseAdapter.java | 48 +++++++++++++++ .../camel/swagger/RestSwaggerProcessor.java | 62 +++++++++++++++++++- .../camel/swagger/RestSwaggerSupport.java | 11 ++-- .../swagger/SwaggerRestApiProcessorFactory.java | 3 +- .../servlet/ServletRestApiResponseAdapter.java | 5 +- 8 files changed, 165 insertions(+), 15 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/646c9bcb/camel-core/src/main/java/org/apache/camel/spi/RestApiResponseAdapter.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/spi/RestApiResponseAdapter.java b/camel-core/src/main/java/org/apache/camel/spi/RestApiResponseAdapter.java index 3575d8d..01b1e4f 100644 --- a/camel-core/src/main/java/org/apache/camel/spi/RestApiResponseAdapter.java +++ b/camel-core/src/main/java/org/apache/camel/spi/RestApiResponseAdapter.java @@ -17,7 +17,6 @@ package org.apache.camel.spi; import java.io.IOException; -import java.io.OutputStream; /** * An adapter to allow Camel rest-api to use Camel components to render the api response. @@ -26,7 +25,7 @@ public interface RestApiResponseAdapter { void addHeader(String name, String value); - OutputStream getOutputStream() throws IOException; + void writeBytes(byte[] bytes) throws IOException; void noContent(); http://git-wip-us.apache.org/repos/asf/camel/blob/646c9bcb/camel-core/src/main/java/org/apache/camel/spi/RestApiResponseAdapterFactory.java ---------------------------------------------------------------------- diff --git a/camel-core/src/main/java/org/apache/camel/spi/RestApiResponseAdapterFactory.java b/camel-core/src/main/java/org/apache/camel/spi/RestApiResponseAdapterFactory.java new file mode 100644 index 0000000..71bffd8 --- /dev/null +++ b/camel-core/src/main/java/org/apache/camel/spi/RestApiResponseAdapterFactory.java @@ -0,0 +1,34 @@ +/** + * 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.spi; + +import org.apache.camel.Exchange; + +/** + * Factory to create {@link RestApiResponseAdapter} which allows Camel components + * to provide a response adapter to be used by the rest-dsl api support. + */ +public interface RestApiResponseAdapterFactory { + + /** + * Creates a new {@link RestApiResponseAdapter} + * + * @param exchange the exchange + * @return the adapter + */ + RestApiResponseAdapter newAdapter(Exchange exchange); +} http://git-wip-us.apache.org/repos/asf/camel/blob/646c9bcb/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpComponent.java ---------------------------------------------------------------------- diff --git a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpComponent.java b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpComponent.java index 0a4502c..d036cff 100644 --- a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpComponent.java +++ b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyHttpComponent.java @@ -24,6 +24,7 @@ import java.util.Map; import org.apache.camel.CamelContext; import org.apache.camel.Consumer; import org.apache.camel.Endpoint; +import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.component.netty4.NettyComponent; import org.apache.camel.component.netty4.NettyConfiguration; @@ -31,6 +32,8 @@ import org.apache.camel.component.netty4.NettyServerBootstrapConfiguration; import org.apache.camel.component.netty4.http.handlers.HttpServerMultiplexChannelHandler; import org.apache.camel.spi.HeaderFilterStrategy; import org.apache.camel.spi.HeaderFilterStrategyAware; +import org.apache.camel.spi.RestApiResponseAdapter; +import org.apache.camel.spi.RestApiResponseAdapterFactory; import org.apache.camel.spi.RestConfiguration; import org.apache.camel.spi.RestConsumerFactory; import org.apache.camel.util.FileUtil; @@ -46,7 +49,7 @@ import org.slf4j.LoggerFactory; /** * Netty HTTP based component. */ -public class NettyHttpComponent extends NettyComponent implements HeaderFilterStrategyAware, RestConsumerFactory { +public class NettyHttpComponent extends NettyComponent implements HeaderFilterStrategyAware, RestConsumerFactory, RestApiResponseAdapterFactory { private static final Logger LOG = LoggerFactory.getLogger(NettyHttpComponent.class); @@ -297,6 +300,15 @@ public class NettyHttpComponent extends NettyComponent implements HeaderFilterSt } @Override + public RestApiResponseAdapter newAdapter(Exchange exchange) { + NettyHttpMessage http = exchange.getIn(NettyHttpMessage.class); + if (http != null) { + return new NettyRestApiResponseAdapter(http.getHttpResponse()); + } + return null; + } + + @Override protected void doStop() throws Exception { super.doStop(); http://git-wip-us.apache.org/repos/asf/camel/blob/646c9bcb/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyRestApiResponseAdapter.java ---------------------------------------------------------------------- diff --git a/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyRestApiResponseAdapter.java b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyRestApiResponseAdapter.java new file mode 100644 index 0000000..263f1e3 --- /dev/null +++ b/components/camel-netty4-http/src/main/java/org/apache/camel/component/netty4/http/NettyRestApiResponseAdapter.java @@ -0,0 +1,48 @@ +/** + * 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.component.netty4.http; + +import java.io.IOException; + +import io.netty.handler.codec.http.FullHttpResponse; +import io.netty.handler.codec.http.HttpResponseStatus; +import org.apache.camel.spi.RestApiResponseAdapter; + +public class NettyRestApiResponseAdapter implements RestApiResponseAdapter { + + private final FullHttpResponse httpResponse; + + public NettyRestApiResponseAdapter(FullHttpResponse httpResponse) { + this.httpResponse = httpResponse; + } + + @Override + public void addHeader(String name, String value) { + httpResponse.headers().set(name, value); + } + + @Override + public void writeBytes(byte[] bytes) throws IOException { + httpResponse.content().writeBytes(bytes); + } + + @Override + public void noContent() { + httpResponse.setStatus(HttpResponseStatus.NO_CONTENT); + + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/646c9bcb/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerProcessor.java ---------------------------------------------------------------------- diff --git a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerProcessor.java b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerProcessor.java index d8b34db..4b3b9cd 100644 --- a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerProcessor.java +++ b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerProcessor.java @@ -17,11 +17,16 @@ package org.apache.camel.swagger; import java.util.Map; +import java.util.Set; import io.swagger.jaxrs.config.BeanConfig; +import org.apache.camel.CamelContext; +import org.apache.camel.Component; import org.apache.camel.Exchange; +import org.apache.camel.NoSuchBeanException; import org.apache.camel.Processor; import org.apache.camel.spi.RestApiResponseAdapter; +import org.apache.camel.spi.RestApiResponseAdapterFactory; import org.apache.camel.support.ServiceSupport; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,11 +36,13 @@ public class RestSwaggerProcessor extends ServiceSupport implements Processor { private static final Logger LOG = LoggerFactory.getLogger(RestSwaggerProcessor.class); private final BeanConfig swaggerConfig; private final RestSwaggerSupport support; + private final String componentName; public RestSwaggerProcessor(Map<String, Object> parameters) { support = new RestSwaggerSupport(); swaggerConfig = new BeanConfig(); support.initSwagger(swaggerConfig, parameters); + componentName = (String) parameters.get("componentName"); } @Override @@ -44,9 +51,8 @@ public class RestSwaggerProcessor extends ServiceSupport implements Processor { String contextId; String route = exchange.getIn().getHeader(Exchange.HTTP_PATH, String.class); - RestApiResponseAdapter adapter = null; - try { + RestApiResponseAdapter adapter = lookupAdapter(exchange); // render list of camel contexts as root if (route == null || route.equals("") || route.equals("/")) { @@ -69,6 +75,58 @@ public class RestSwaggerProcessor extends ServiceSupport implements Processor { } } + protected RestApiResponseAdapter lookupAdapter(Exchange exchange) { + CamelContext camelContext = exchange.getContext(); + + RestApiResponseAdapterFactory factory = null; + + if (componentName != null) { + Object comp = camelContext.getRegistry().lookupByName(componentName); + if (comp != null && comp instanceof RestApiResponseAdapterFactory) { + factory = (RestApiResponseAdapterFactory) comp; + } else { + comp = camelContext.getComponent(componentName); + if (comp != null && comp instanceof RestApiResponseAdapterFactory) { + factory = (RestApiResponseAdapterFactory) comp; + } + } + + if (factory == null) { + if (comp != null) { + throw new IllegalArgumentException("Component " + componentName + " is not a RestApiResponseAdapterFactory"); + } else { + throw new NoSuchBeanException(componentName, RestApiResponseAdapterFactory.class.getName()); + } + } + } + + // try all components + if (factory == null) { + for (String name : camelContext.getComponentNames()) { + Component comp = camelContext.getComponent(name); + if (comp != null && comp instanceof RestApiResponseAdapterFactory) { + factory = (RestApiResponseAdapterFactory) comp; + break; + } + } + } + + // lookup in registry + if (factory == null) { + Set<RestApiResponseAdapterFactory> factories = camelContext.getRegistry().findByType(RestApiResponseAdapterFactory.class); + if (factories != null && factories.size() == 1) { + factory = factories.iterator().next(); + } + } + + if (factory != null) { + return factory.newAdapter(exchange); + } else { + throw new IllegalStateException("Cannot find RestApiResponseAdapterFactory in Registry or as a Component to use"); + } + + } + @Override protected void doStart() throws Exception { // noop http://git-wip-us.apache.org/repos/asf/camel/blob/646c9bcb/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerSupport.java ---------------------------------------------------------------------- diff --git a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerSupport.java b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerSupport.java index ebff12f..e558ee3 100644 --- a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerSupport.java +++ b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/RestSwaggerSupport.java @@ -182,7 +182,8 @@ public class RestSwaggerSupport { ObjectMapper mapper = new ObjectMapper(); mapper.enable(SerializationFeature.INDENT_OUTPUT); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - mapper.writeValue(response.getOutputStream(), swagger); + byte[] bytes = mapper.writeValueAsBytes(swagger); + response.writeBytes(bytes); } else { response.noContent(); } @@ -201,15 +202,15 @@ public class RestSwaggerSupport { } List<String> contexts = findCamelContexts(); - response.getOutputStream().write("[\n".getBytes()); + response.writeBytes("[\n".getBytes()); for (int i = 0; i < contexts.size(); i++) { String name = contexts.get(i); - response.getOutputStream().write(("{\"name\": \"" + name + "\"}").getBytes()); + response.writeBytes(("{\"name\": \"" + name + "\"}").getBytes()); if (i < contexts.size() - 1) { - response.getOutputStream().write(",\n".getBytes()); + response.writeBytes(",\n".getBytes()); } } - response.getOutputStream().write("\n]".getBytes()); + response.writeBytes("\n]".getBytes()); } } http://git-wip-us.apache.org/repos/asf/camel/blob/646c9bcb/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/SwaggerRestApiProcessorFactory.java ---------------------------------------------------------------------- diff --git a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/SwaggerRestApiProcessorFactory.java b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/SwaggerRestApiProcessorFactory.java index 436ae45..19cd1a7 100644 --- a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/SwaggerRestApiProcessorFactory.java +++ b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/SwaggerRestApiProcessorFactory.java @@ -26,7 +26,6 @@ public class SwaggerRestApiProcessorFactory implements RestApiProcessorFactory { @Override public Processor createApiProcessor(CamelContext camelContext, String contextPath, Map<String, Object> parameters) throws Exception { - RestSwaggerProcessor processor = new RestSwaggerProcessor(parameters); - return null; + return new RestSwaggerProcessor(parameters); } } http://git-wip-us.apache.org/repos/asf/camel/blob/646c9bcb/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/servlet/ServletRestApiResponseAdapter.java ---------------------------------------------------------------------- diff --git a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/servlet/ServletRestApiResponseAdapter.java b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/servlet/ServletRestApiResponseAdapter.java index 499b07d..bae3aec 100644 --- a/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/servlet/ServletRestApiResponseAdapter.java +++ b/components/camel-swagger-java/src/main/java/org/apache/camel/swagger/servlet/ServletRestApiResponseAdapter.java @@ -17,7 +17,6 @@ package org.apache.camel.swagger.servlet; import java.io.IOException; -import java.io.OutputStream; import javax.servlet.http.HttpServletResponse; import org.apache.camel.spi.RestApiResponseAdapter; @@ -36,8 +35,8 @@ public class ServletRestApiResponseAdapter implements RestApiResponseAdapter { } @Override - public OutputStream getOutputStream() throws IOException { - return response.getOutputStream(); + public void writeBytes(byte[] bytes) throws IOException { + response.getOutputStream().write(bytes); } @Override