CAMEL-9737 - Create camel component for ServiceNow
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/aa7ca432 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/aa7ca432 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/aa7ca432 Branch: refs/heads/master Commit: aa7ca432d6b2f838edd5b9e4811c83a971051ed4 Parents: 1f9dc80 Author: lburgazzoli <lburgazz...@gmail.com> Authored: Tue Mar 22 10:21:59 2016 +0100 Committer: Claus Ibsen <davscl...@apache.org> Committed: Tue Mar 22 16:36:41 2016 +0100 ---------------------------------------------------------------------- apache-camel/pom.xml | 4 + .../src/main/descriptors/common-bin.xml | 1 + components/camel-servicenow/pom.xml | 162 +++++++++++ .../servicenow/ServiceNowComponent.java | 52 ++++ .../servicenow/ServiceNowConfiguration.java | 258 +++++++++++++++++ .../servicenow/ServiceNowConstants.java | 52 ++++ .../servicenow/ServiceNowConsumer.java | 26 ++ .../servicenow/ServiceNowEndpoint.java | 100 +++++++ .../servicenow/ServiceNowException.java | 59 ++++ .../servicenow/ServiceNowExceptionMapper.java | 59 ++++ .../servicenow/ServiceNowProducer.java | 103 +++++++ .../servicenow/ServiceNowProducerProcessor.java | 139 +++++++++ .../auth/AuthenticationRequestFilter.java | 61 ++++ .../component/servicenow/auth/OAuthToken.java | 109 +++++++ .../servicenow/model/ServiceNowAggregate.java | 50 ++++ .../model/ServiceNowAggregateProcessor.java | 68 +++++ .../servicenow/model/ServiceNowImportSet.java | 48 ++++ .../model/ServiceNowImportSetProcessor.java | 79 +++++ .../servicenow/model/ServiceNowTable.java | 108 +++++++ .../model/ServiceNowTableProcessor.java | 169 +++++++++++ .../org/apache/camel/component/servicenow | 1 + .../servicenow/ServiceNowTableTest.java | 286 +++++++++++++++++++ .../component/servicenow/ServiceNowTest.java | 112 ++++++++ .../servicenow/ServiceNowTestSupport.java | 61 ++++ .../component/servicenow/model/Incident.java | 96 +++++++ .../src/test/resources/log4j.properties | 19 ++ components/pom.xml | 1 + parent/pom.xml | 5 + .../features/src/main/resources/features.xml | 12 + .../camel/itest/karaf/CamelServicenowTest.java | 40 +++ 30 files changed, 2340 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/aa7ca432/apache-camel/pom.xml ---------------------------------------------------------------------- diff --git a/apache-camel/pom.xml b/apache-camel/pom.xml index 4553726..766cbc6 100644 --- a/apache-camel/pom.xml +++ b/apache-camel/pom.xml @@ -716,6 +716,10 @@ </dependency> <dependency> <groupId>org.apache.camel</groupId> + <artifactId>camel-servicenow</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> <artifactId>camel-servlet</artifactId> </dependency> <dependency> http://git-wip-us.apache.org/repos/asf/camel/blob/aa7ca432/apache-camel/src/main/descriptors/common-bin.xml ---------------------------------------------------------------------- diff --git a/apache-camel/src/main/descriptors/common-bin.xml b/apache-camel/src/main/descriptors/common-bin.xml index c797dff..1439828 100644 --- a/apache-camel/src/main/descriptors/common-bin.xml +++ b/apache-camel/src/main/descriptors/common-bin.xml @@ -190,6 +190,7 @@ <include>org.apache.camel:camel-schematron</include> <include>org.apache.camel:camel-scr</include> <include>org.apache.camel:camel-script</include> + <include>org.apache.camel:camel-servicenow</include> <include>org.apache.camel:camel-servlet</include> <include>org.apache.camel:camel-servletlistener</include> <include>org.apache.camel:camel-shiro</include> http://git-wip-us.apache.org/repos/asf/camel/blob/aa7ca432/components/camel-servicenow/pom.xml ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/pom.xml b/components/camel-servicenow/pom.xml new file mode 100644 index 0000000..8ea683e --- /dev/null +++ b/components/camel-servicenow/pom.xml @@ -0,0 +1,162 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.camel</groupId> + <artifactId>components</artifactId> + <version>2.18-SNAPSHOT</version> + </parent> + + <artifactId>camel-servicenow</artifactId> + <packaging>bundle</packaging> + <name>Camel :: ServiceNow</name> + <description>Camel ServiceNow support</description> + + <properties> + <camel.osgi.export.pkg> + org.apache.camel.component.servicenow.* + </camel.osgi.export.pkg> + <camel.osgi.export.service> + org.apache.camel.spi.ComponentResolver;component=servicenow + </camel.osgi.export.service> + </properties> + + + <dependencies> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-core</artifactId> + </dependency> + + <!-- CXF --> + <dependency> + <groupId>org.apache.cxf</groupId> + <artifactId>cxf-core</artifactId> + <version>${cxf-version}</version> + </dependency> + <dependency> + <groupId>org.apache.cxf</groupId> + <artifactId>cxf-rt-frontend-jaxrs</artifactId> + <version>${cxf-version}</version> + </dependency> + <dependency> + <groupId>org.apache.cxf</groupId> + <artifactId>cxf-rt-rs-security-oauth2</artifactId> + <version>${cxf-version}</version> + </dependency> + <dependency> + <groupId>org.apache.cxf</groupId> + <artifactId>cxf-rt-rs-extension-providers</artifactId> + <version>${cxf-version}</version> + </dependency> + <dependency> + <groupId>org.apache.cxf</groupId> + <artifactId>cxf-rt-rs-client</artifactId> + <version>${cxf-version}</version> + </dependency> + + <!-- Jackson --> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-core</artifactId> + <version>${jackson2-version}</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + <version>${jackson2-version}</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <version>${jackson2-version}</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.jaxrs</groupId> + <artifactId>jackson-jaxrs-json-provider</artifactId> + <version>${jackson2-version}</version> + </dependency> + + <!-- testing --> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-test</artifactId> + <scope>test</scope> + </dependency> + + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-all</artifactId> + <version>${mockito-version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>java-hamcrest</artifactId> + <version>${hamcrest-version}</version> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <skipTests>true</skipTests> + </configuration> + </plugin> + </plugins> + </build> + + <profiles> + <profile> + <id>servicenow-tests</id> + <activation> + <property> + <name>env.SERVICENOW_INSTANCE</name> + </property> + </activation> + <build> + <plugins> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <skipTests>false</skipTests> + </configuration> + </plugin> + </plugins> + </build> + </profile> + </profiles> + +</project> http://git-wip-us.apache.org/repos/asf/camel/blob/aa7ca432/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java new file mode 100644 index 0000000..30135c9 --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowComponent.java @@ -0,0 +1,52 @@ +/** + * 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.servicenow; + +import java.util.Map; + +import org.apache.camel.CamelContext; +import org.apache.camel.Endpoint; +import org.apache.camel.impl.UriEndpointComponent; +import org.apache.camel.util.EndpointHelper; +import org.apache.camel.util.IntrospectionSupport; + +/** + * Represents the component that manages {@link ServiceNowEndpoint}. + */ +public class ServiceNowComponent extends UriEndpointComponent { + + public ServiceNowComponent() { + super(ServiceNowEndpoint.class); + } + + @Override + protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception { + final CamelContext context = getCamelContext(); + final ServiceNowConfiguration configuration = new ServiceNowConfiguration(); + + Map<String, Object> models = IntrospectionSupport.extractProperties(parameters, "model."); + for (Map.Entry<String, Object> entry : models.entrySet()) { + configuration.addModel( + entry.getKey(), + EndpointHelper.resolveParameter(context, (String)entry.getValue(), Class.class)); + } + + setProperties(configuration, parameters); + + return new ServiceNowEndpoint(uri, this, configuration, remaining); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/aa7ca432/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java new file mode 100644 index 0000000..755e49f --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConfiguration.java @@ -0,0 +1,258 @@ +/** + * 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.servicenow; + +import java.util.HashMap; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.camel.spi.UriParam; +import org.apache.camel.spi.UriParams; +import org.apache.camel.util.ObjectHelper; + + +@UriParams +public class ServiceNowConfiguration { + + private static final ObjectMapper MAPPER = new ObjectMapper() + .configure( + DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, + false) + .setSerializationInclusion( + JsonInclude.Include.NON_NULL + ); + + @UriParam + private String userName; + @UriParam + private String password; + @UriParam + private String oauthClientId; + @UriParam + private String oauthClientSecret; + @UriParam(label = "advanced") + private String oauthTokenUrl; + @UriParam(label = "advanced") + private String apiUrl; + @UriParam + private String table; + @UriParam(defaultValue = "false") + private Boolean excludeReferenceLink = false; + @UriParam(defaultValue = "false") + private Boolean suppressAutoSysField = false; + @UriParam(defaultValue = "false") + private String displayValue = "false"; + @UriParam(defaultValue = "false") + private Boolean inputDisplayValue = false; + @UriParam(prefix = "model.", multiValue = true, javaType = "java.lang.String") + private Map<String, Class<?>> models; + @UriParam(label = "advanced") + private ObjectMapper mapper = MAPPER; + + + public String getUserName() { + return userName; + } + + public String getApiUrl() { + return apiUrl; + } + + /** + * The ServiceNow REST API url + */ + public void setApiUrl(String apiUrl) { + this.apiUrl = apiUrl; + } + + public boolean hasApiUrl() { + return apiUrl != null; + } + + /** + * ServiceNow user account name, MUST be provided + */ + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassword() { + return password; + } + + /** + * ServiceNow account password, MUST be provided + */ + public void setPassword(String password) { + this.password = password; + } + + public String getOauthClientId() { + return oauthClientId; + } + + /** + * OAuth2 ClientID + */ + public void setOauthClientId(String oauthClientId) { + this.oauthClientId = oauthClientId; + } + + public String getOauthClientSecret() { + return oauthClientSecret; + } + + /** + * OAuth2 ClientSecret + */ + public void setOauthClientSecret(String oauthClientSecret) { + this.oauthClientSecret = oauthClientSecret; + } + + public String getOauthTokenUrl() { + return oauthTokenUrl; + } + + public boolean hasOautTokenUrl() { + return oauthTokenUrl != null; + } + + /** + * OAuth token Url + */ + public void setOauthTokenUrl(String oauthTokenUrl) { + this.oauthTokenUrl = oauthTokenUrl; + } + + public boolean hasBasicAuthentication() { + return ObjectHelper.isNotEmpty(userName) + && ObjectHelper.isNotEmpty(password); + } + + public boolean hasOAuthAuthentication() { + return ObjectHelper.isNotEmpty(userName) + && ObjectHelper.isNotEmpty(password) + && ObjectHelper.isNotEmpty(oauthClientId) + && ObjectHelper.isNotEmpty(oauthClientSecret); + } + + public String getTable() { + return table; + } + + /** + * The default table, can be overridden by header CamelServiceNowTable + */ + public void setTable(String table) { + this.table = table; + } + + public Boolean getExcludeReferenceLink() { + return excludeReferenceLink; + } + + /** + * True to exclude Table API links for reference fields (default: false) + */ + public void setExcludeReferenceLink(Boolean excludeReferenceLink) { + this.excludeReferenceLink = excludeReferenceLink; + } + + public Boolean getSuppressAutoSysField() { + return suppressAutoSysField; + } + + /** + * True to suppress auto generation of system fields (default: false) + */ + public void setSuppressAutoSysField(Boolean suppressAutoSysField) { + this.suppressAutoSysField = suppressAutoSysField; + } + + public String getDisplayValue() { + return displayValue; + } + + /** + * Return the display value (true), actual value (false), or both (all) for + * reference fields (default: false) + */ + public void setDisplayValue(String displayValue) { + this.displayValue = displayValue; + } + + public Boolean getInputDisplayValue() { + return inputDisplayValue; + } + + /** + * True to set raw value of input fields (default: false) + */ + public void setInputDisplayValue(Boolean inputDisplayValue) { + this.inputDisplayValue = inputDisplayValue; + } + + public Map<String, Class<?>> getModels() { + return models; + } + + /** + * Defines the default model to use for a table + */ + public void setModels(Map<String, Class<?>> models) { + this.models = models; + } + + public void addModel(String name, Class<?> type) { + if (this.models == null) { + this.models = new HashMap<>(); + } + + this.models.put(name, type); + } + + public Class<?> getModel(String name) { + return getModel(name, null); + } + + public Class<?> getModel(String name, Class<?> defaultType) { + Class<?> model = defaultType; + + if (this.models != null && this.models.containsKey(name)) { + model = this.models.get(name); + } + + return model; + } + + /** + * Sets Jackson's ObjectMapper to use for request/reply + */ + public void setMapper(ObjectMapper mapper) { + this.mapper = mapper; + } + + public ObjectMapper getMapper() { + return mapper; + } + + public boolean hasMapper() { + return mapper != null; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/aa7ca432/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java new file mode 100644 index 0000000..3dfb20e --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConstants.java @@ -0,0 +1,52 @@ +/** + * 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.servicenow; + +public interface ServiceNowConstants { + String RESOURCE = "CamelServiceNowResource"; + String TABLE = "CamelServiceNowTable"; + String ACTION = "CamelServiceNowAction"; + String MODEL = "CamelServiceNowModel"; + + String RESOURCE_TABLE = "table"; + String RESOURCE_AGGREGATE = "aggregate"; + String RESOURCE_IMPORT = "aggregate"; + + String ACTION_RETRIEVE = "retrieve"; + String ACTION_CREATE = "create"; + String ACTION_MODIFY = "modify"; + String ACTION_DELETE = "delete"; + String ACTION_UPDATE = "update"; + + String SYSPARM_ID = "CamelServiceNowSysId"; + String SYSPARM_QUERY = "CamelServiceNowQuery"; + String SYSPARM_DISPLAY_VALUE = "CamelServiceNowDisplayValue"; + String SYSPARM_INPUT_DISPLAY_VALUE = "CamelServiceNowInputDisplayValue"; + String SYSPARM_EXCLUDE_REFERENCE_LINK = "CamelServiceNowExcludeReferenceLink"; + String SYSPARM_FIELDS = "CamelServiceNowFields"; + String SYSPARM_MIN_FIELDS = "CamelServiceNowMinFields"; + String SYSPARM_MAX_FIELDS = "CamelServiceNowMaxFields"; + String SYSPARM_SUM_FIELDS = "CamelServiceNowSumFields"; + String SYSPARM_LIMIT = "CamelServiceNowLimit"; + String SYSPARM_VIEW = "CamelServiceNowView"; + String SYSPARM_SUPPRESS_AUTO_SYS_FIELD = "CamelServiceNowSuppressAutoSysField"; + String SYSPARM_AVG_FIELDS = "CamelServiceNowAvgFields"; + String SYSPARM_COUNT = "CamelServiceNowCount"; + String SYSPARM_GROUP_BY = "CamelServiceGroupBy"; + String SYSPARM_ORDER_BY = "CamelServiceOrderBy"; + String SYSPARM_HAVING = "CamelServiceHaving"; +} http://git-wip-us.apache.org/repos/asf/camel/blob/aa7ca432/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConsumer.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConsumer.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConsumer.java new file mode 100644 index 0000000..b841ba3 --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowConsumer.java @@ -0,0 +1,26 @@ +/** + * 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.servicenow; + +import org.apache.camel.Processor; +import org.apache.camel.impl.DefaultConsumer; + +public class ServiceNowConsumer extends DefaultConsumer { + public ServiceNowConsumer(ServiceNowEndpoint endpoint, Processor processor) { + super(endpoint, processor); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/aa7ca432/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java new file mode 100644 index 0000000..d7f4375 --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowEndpoint.java @@ -0,0 +1,100 @@ +/** + * 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.servicenow; + +import java.util.Arrays; + +import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; +import org.apache.camel.Consumer; +import org.apache.camel.Processor; +import org.apache.camel.Producer; +import org.apache.camel.component.servicenow.auth.AuthenticationRequestFilter; +import org.apache.camel.component.servicenow.auth.OAuthToken; +import org.apache.camel.impl.DefaultEndpoint; +import org.apache.camel.spi.Metadata; +import org.apache.camel.spi.UriEndpoint; +import org.apache.camel.spi.UriPath; +import org.apache.cxf.jaxrs.client.JAXRSClientFactory; + +/** + * Represents a ServiceNow endpoint. + */ +@UriEndpoint(scheme = "servicenow", title = "ServiceNow", syntax = "servicenow:instanceName", consumerClass = ServiceNowConsumer.class, label = "ServiceNow") +public class ServiceNowEndpoint extends DefaultEndpoint { + + @UriPath(description = "The ServiceNow instance name ") + @Metadata(required = "true") + private final String instanceName; + + private final ServiceNowConfiguration configuration; + private final String apiUrl; + private final String oauthUrl; + private final OAuthToken token; + + public ServiceNowEndpoint(String uri, ServiceNowComponent component, ServiceNowConfiguration configuration, String instanceName) throws Exception { + super(uri, component); + + this.configuration = configuration; + this.instanceName = component.getCamelContext().resolvePropertyPlaceholders(instanceName); + + this.apiUrl = configuration.hasApiUrl() + ? configuration.getApiUrl() + : String.format("https://%s.service-now.com/api/now", instanceName); + this.oauthUrl = configuration.hasOautTokenUrl() + ? configuration.getOauthTokenUrl() + : String.format("https://%s.service-now.com/oauth_token.do", instanceName); + + this.token = configuration.hasOAuthAuthentication() + ? new OAuthToken(this.oauthUrl, this.configuration) + : null; + } + + @Override + public Producer createProducer() throws Exception { + return new ServiceNowProducer(this); + } + + @Override + public Consumer createConsumer(Processor processor) throws Exception { + throw new UnsupportedOperationException("Consumer interface is not supported"); + } + + @Override + public boolean isSingleton() { + return false; + } + + public ServiceNowConfiguration getConfiguration() { + return configuration; + } + + public String getInstanceName() { + return instanceName; + } + + public <T> T createClient(Class<T> type) throws Exception { + return JAXRSClientFactory.create( + apiUrl, + type, + Arrays.asList( + new AuthenticationRequestFilter(configuration, token), + new JacksonJsonProvider(configuration.getMapper()), + new ServiceNowExceptionMapper(configuration.getMapper()) + ) + ); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/aa7ca432/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowException.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowException.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowException.java new file mode 100644 index 0000000..cb1ce8b --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowException.java @@ -0,0 +1,59 @@ +/** + * 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.servicenow; + +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.apache.camel.CamelException; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class ServiceNowException extends CamelException { + private final String status; + private final String detail; + + public ServiceNowException( + @JsonProperty("status") String status, + @JsonProperty("error") Map<String, String> error) { + super(error.get("message")); + this.status = status; + this.detail = error.get("detail"); + } + + public ServiceNowException(Throwable cause) { + super(cause); + + this.status = null; + this.detail = null; + } + + public String getStatus() { + return status; + } + + public String getDetail() { + return detail; + } + + @Override + public String toString() { + return getMessage() != null + ? "" + this.status + ": " + getMessage() + : super.toString(); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/aa7ca432/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionMapper.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionMapper.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionMapper.java new file mode 100644 index 0000000..5b80c69 --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowExceptionMapper.java @@ -0,0 +1,59 @@ +/** + * 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.servicenow; + +import java.io.IOException; +import java.io.InputStream; +import javax.annotation.Priority; +import javax.ws.rs.Priorities; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.Provider; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.cxf.jaxrs.client.ResponseExceptionMapper; + +@Provider +@Priority(Priorities.USER) +public class ServiceNowExceptionMapper implements ResponseExceptionMapper<ServiceNowException> { + private final ObjectMapper mapper; + + public ServiceNowExceptionMapper(ObjectMapper mapper) { + this.mapper = mapper; + } + + @Override + public ServiceNowException fromResponse(Response r) { + int code = r.getStatus(); + + try { + // Only ServiceNow known error status codes are mapped + // See http://wiki.servicenow.com/index.php?title=REST_API#REST_Response_HTTP_Status_Codes + if (code == Response.Status.NOT_FOUND.getStatusCode() + || code == Response.Status.BAD_REQUEST.getStatusCode() + || code == Response.Status.UNAUTHORIZED.getStatusCode() + || code == Response.Status.FORBIDDEN.getStatusCode() + || code == Response.Status.METHOD_NOT_ALLOWED.getStatusCode()) { + + return mapper.readValue((InputStream)r.getEntity(), ServiceNowException.class); + } + } catch (IOException e) { + return new ServiceNowException(e); + } + + return null; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/aa7ca432/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducer.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducer.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducer.java new file mode 100644 index 0000000..cd7d4a7 --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducer.java @@ -0,0 +1,103 @@ +/** + * 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.servicenow; + +import java.lang.ref.WeakReference; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.component.servicenow.model.ServiceNowAggregateProcessor; +import org.apache.camel.component.servicenow.model.ServiceNowImportSetProcessor; +import org.apache.camel.component.servicenow.model.ServiceNowTableProcessor; +import org.apache.camel.impl.DefaultProducer; +import org.apache.camel.util.ObjectHelper; + +/** + * The ServiceNow producer. + */ +public class ServiceNowProducer extends DefaultProducer { + + private final ServiceNowEndpoint endpoint; + private final ServiceNowConfiguration configuration; + private final WeakThreadLocal tableCache; + private final WeakThreadLocal aggregateCache; + private final WeakThreadLocal importSetCache; + + public ServiceNowProducer(ServiceNowEndpoint endpoint) { + super(endpoint); + + this.endpoint = endpoint; + this.configuration = endpoint.getConfiguration(); + this.tableCache = new WeakThreadLocal(ServiceNowTableProcessor.SUPPLIER); + this.aggregateCache = new WeakThreadLocal(ServiceNowAggregateProcessor.SUPPLIER); + this.importSetCache = new WeakThreadLocal(ServiceNowImportSetProcessor.SUPPLIER); + } + + @Override + public void process(Exchange exchange) throws Exception { + final String resource = exchange.getIn().getHeader(ServiceNowConstants.RESOURCE, String.class); + + if (ObjectHelper.equal(ServiceNowConstants.RESOURCE_TABLE, resource, true)) { + tableCache.get().process(exchange); + } else if (ObjectHelper.equal(ServiceNowConstants.RESOURCE_AGGREGATE, resource, true)) { + aggregateCache.get().process(exchange); + } else if (ObjectHelper.equal(ServiceNowConstants.RESOURCE_IMPORT, resource, true)) { + importSetCache.get().process(exchange); + } else { + throw new IllegalArgumentException("Unknown resource type: " + resource); + } + } + + // ************************************************************************* + // Thread-Local processor instances as CXF client proxies are not thread + // safe. To be refactored once moved to Java 8 as ServiceNowProcessorSupplier + // can be replaced by: + // + // java.util.function.Function<ServiceNowEndpoint, Processor> + // + // so an instance of a specific processor can be obtained by a constructor + // ref, i.e: + // + // ServiceNowImportSetProcessor::new + // + // ************************************************************************* + + private final class WeakThreadLocal { + private final ThreadLocal<WeakReference<Processor>> cache; + private final ServiceNowProducerProcessor.Supplier supplier; + + public WeakThreadLocal(ServiceNowProducerProcessor.Supplier supplier) { + this.cache = new ThreadLocal<>(); + this.supplier = supplier; + } + + public Processor get() throws Exception { + Processor processor = null; + WeakReference<Processor> ref = cache.get(); + if (ref != null) { + processor = ref.get(); + } + + if (processor == null) { + processor = supplier.get(endpoint); + cache.set(new WeakReference<>(processor)); + } + + return processor; + } + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/aa7ca432/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducerProcessor.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducerProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducerProcessor.java new file mode 100644 index 0000000..83b61ce --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/ServiceNowProducerProcessor.java @@ -0,0 +1,139 @@ +/** + * 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.servicenow; + +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.Processor; +import org.apache.camel.util.ObjectHelper; + +public abstract class ServiceNowProducerProcessor<T> implements Processor { + + protected final ServiceNowEndpoint endpoint; + protected final ServiceNowConfiguration config; + protected final T client; + protected final ObjectMapper mapper; + + // Cache for JavaTypes + private final JavaTypeCache javaTypeCache; + + protected ServiceNowProducerProcessor(ServiceNowEndpoint endpoint, Class<T> type) throws Exception { + this.javaTypeCache = new JavaTypeCache(); + this.endpoint = endpoint; + this.config = endpoint.getConfiguration(); + this.client = endpoint.createClient(type); + this.mapper = ObjectHelper.notNull(config.getMapper(), "mapper"); + } + + @Override + public void process(Exchange exchange) throws Exception { + final Message in = exchange.getIn(); + final String tableName = in.getHeader(ServiceNowConstants.TABLE, config.getTable(), String.class); + final Class<?> model = in.getHeader(ServiceNowConstants.MODEL, config.getModel(tableName, Map.class), Class.class); + final String action = in.getHeader(ServiceNowConstants.ACTION, String.class); + final String sysId = in.getHeader(ServiceNowConstants.SYSPARM_ID, String.class); + + doProcess( + exchange, + ObjectHelper.notNull(model, "model"), + ObjectHelper.notNull(action, "action"), + ObjectHelper.notNull(tableName, "tableName"), + sysId); + } + + protected abstract void doProcess( + Exchange exchange, + Class<?> model, + String action, + String tableName, + String sysId) throws Exception; + + + protected ServiceNowProducerProcessor<T> validateBody(Message message, Class<?> model) { + return validateBody(message.getBody(), model); + } + + protected ServiceNowProducerProcessor<T> validateBody(Object body, Class<?> model) { + ObjectHelper.notNull(body, "body"); + + if (!body.getClass().isAssignableFrom(model)) { + throw new IllegalArgumentException( + "Body is not compatible with model (body=" + body.getClass() + ", model=" + model); + } + + return this; + } + + protected ServiceNowProducerProcessor<T> setBody(Message message, Class<?> model, JsonNode answer) throws Exception { + message.setBody(unwrap(answer, model)); + + return this; + } + + protected Object unwrap(JsonNode answer, Class<?> model) throws Exception { + Object result = null; + + if (answer != null) { + JsonNode node = answer.get("result"); + if (node != null) { + if (node.isArray()) { + if (model.isInstance(Map.class)) { + // If the model is a Map, there's no need to use any + // specific JavaType to instruct Jackson about the + // expected element type + result = mapper.treeToValue(node, List.class); + } else { + result = mapper.readValue(node.traverse(), javaTypeCache.get(model)); + } + } else { + result = mapper.treeToValue(node, model); + } + } + } + + return result; + } + + // ************************************************************************* + // Use ClassValue to lazy create and cache JavaType + // ************************************************************************* + + private class JavaTypeCache extends ClassValue<JavaType> { + @Override + protected JavaType computeValue(Class<?> type) { + return mapper.getTypeFactory().constructCollectionType(List.class, type); + } + } + + // ************************************************************************* + // To be replaced with: + // + // java.util.function.Function<ServiceNowEndpoint, Processor> + // + // Once Camel will be Java 8 ready + // ************************************************************************* + + public interface Supplier { + Processor get(ServiceNowEndpoint endpoint) throws Exception; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/aa7ca432/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/auth/AuthenticationRequestFilter.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/auth/AuthenticationRequestFilter.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/auth/AuthenticationRequestFilter.java new file mode 100644 index 0000000..d6e3b05 --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/auth/AuthenticationRequestFilter.java @@ -0,0 +1,61 @@ +/** + * 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.servicenow.auth; + +import java.io.IOException; +import javax.annotation.Priority; +import javax.ws.rs.Priorities; +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientRequestFilter; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.ext.Provider; +import javax.xml.bind.DatatypeConverter; + +import org.apache.camel.component.servicenow.ServiceNowConfiguration; + + +@Provider +@Priority(Priorities.AUTHENTICATION) +public class AuthenticationRequestFilter implements ClientRequestFilter { + private final ServiceNowConfiguration configuration; + private final OAuthToken token; + private final String authString; + + public AuthenticationRequestFilter(ServiceNowConfiguration configuration, OAuthToken token) throws IOException { + this.configuration = configuration; + this.token = token; + this.authString = buildBasicAuthString(configuration); + } + + @Override + public void filter(ClientRequestContext requestContext) throws IOException { + if (token != null) { + requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, token.getAuthString()); + } else if (authString != null) { + requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, authString); + } + } + + private static String buildBasicAuthString(final ServiceNowConfiguration configuration) throws IOException { + if (!configuration.hasBasicAuthentication()) { + return null; + } + + String userAndPassword = configuration.getUserName() + ":" + configuration.getPassword(); + return "Basic " + DatatypeConverter.printBase64Binary(userAndPassword.getBytes("UTF-8")); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/aa7ca432/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/auth/OAuthToken.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/auth/OAuthToken.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/auth/OAuthToken.java new file mode 100644 index 0000000..11c3842 --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/auth/OAuthToken.java @@ -0,0 +1,109 @@ +/** + * 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.servicenow.auth; + +import java.util.concurrent.TimeUnit; + +import org.apache.camel.component.servicenow.ServiceNowConfiguration; +import org.apache.cxf.jaxrs.client.WebClient; +import org.apache.cxf.rs.security.oauth2.client.Consumer; +import org.apache.cxf.rs.security.oauth2.client.OAuthClientUtils; +import org.apache.cxf.rs.security.oauth2.common.ClientAccessToken; +import org.apache.cxf.rs.security.oauth2.grants.owner.ResourceOwnerGrant; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class OAuthToken { + private static final Logger LOGGER = LoggerFactory.getLogger(OAuthToken.class); + + private final String url; + private final ServiceNowConfiguration configuration; + private ClientAccessToken token; + private String authString; + private long expireAt; + + public OAuthToken(String url, ServiceNowConfiguration configuration) { + this.url = url; + this.configuration = configuration; + this.token = null; + this.authString = null; + this.expireAt = 0; + } + + private synchronized void getOrRefreshAccessToken() { + if (token == null) { + LOGGER.debug("Generate OAuth token"); + + token = OAuthClientUtils.getAccessToken( + WebClient.create(url), + new Consumer( + configuration.getOauthClientId(), + configuration.getOauthClientSecret()), + new ResourceOwnerGrant( + configuration.getUserName(), + configuration.getPassword()), + true + ); + + LOGGER.debug("OAuth token expires in {}s", token.getExpiresIn()); + + // Set expiration time related info in milliseconds + token.setIssuedAt(System.currentTimeMillis()); + token.setExpiresIn(TimeUnit.MILLISECONDS.convert(token.getExpiresIn(), TimeUnit.SECONDS)); + + authString = token.toString(); + + if (token.getExpiresIn() > 0) { + expireAt = token.getIssuedAt() + token.getExpiresIn(); + } + } else if (expireAt > 0 && System.currentTimeMillis() >= expireAt) { + LOGGER.debug("OAuth token is expired, refresh it"); + + token = OAuthClientUtils.refreshAccessToken( + WebClient.create(url), + new Consumer( + configuration.getOauthClientId(), + configuration.getOauthClientSecret()), + token, + null, + false + ); + + LOGGER.debug("Refreshed OAuth token expires in {}s", token.getExpiresIn()); + + // Set expiration time related info in milliseconds + token.setIssuedAt(System.currentTimeMillis()); + token.setExpiresIn(TimeUnit.MILLISECONDS.convert(token.getExpiresIn(), TimeUnit.SECONDS)); + + authString = token.toString(); + + if (token.getExpiresIn() > 0) { + expireAt = token.getIssuedAt() + token.getExpiresIn(); + } + } + } + + public ClientAccessToken getClientAccess() { + getOrRefreshAccessToken(); + return token; + } + + public String getAuthString() { + getOrRefreshAccessToken(); + return authString; + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/aa7ca432/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowAggregate.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowAggregate.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowAggregate.java new file mode 100644 index 0000000..b723387 --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowAggregate.java @@ -0,0 +1,50 @@ +/** + * 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.servicenow.model; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; + +import com.fasterxml.jackson.databind.JsonNode; +import org.apache.camel.component.servicenow.ServiceNowException; + +@Path("/stats") +@Produces("application/json") +@Consumes("application/json") +public interface ServiceNowAggregate { + + @GET + @Path("{tableName}") + JsonNode retrieveStats( + @PathParam("tableName") String tableName, + @QueryParam("sysparm_query") String query, + @QueryParam("sysparm_avg_fields") String avgFields, + @QueryParam("sysparm_count") String count, + @QueryParam("sysparm_min_fields") String minFields, + @QueryParam("sysparm_max_fields") String maxFields, + @QueryParam("sysparm_sum_fields") String sumFields, + @QueryParam("sysparm_group_by") String groupBy, + @QueryParam("sysparm_order_by") String orderBy, + @QueryParam("sysparm_having") String having, + @QueryParam("sysparm_display_value") String displayValue + ) throws ServiceNowException; +} http://git-wip-us.apache.org/repos/asf/camel/blob/aa7ca432/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowAggregateProcessor.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowAggregateProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowAggregateProcessor.java new file mode 100644 index 0000000..964b772 --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowAggregateProcessor.java @@ -0,0 +1,68 @@ +/** + * 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.servicenow.model; + +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.Processor; +import org.apache.camel.component.servicenow.ServiceNowConstants; +import org.apache.camel.component.servicenow.ServiceNowEndpoint; +import org.apache.camel.component.servicenow.ServiceNowProducerProcessor; +import org.apache.camel.util.ObjectHelper; + +public class ServiceNowAggregateProcessor extends ServiceNowProducerProcessor<ServiceNowAggregate> { + + public static final ServiceNowProducerProcessor.Supplier SUPPLIER = new ServiceNowProducerProcessor.Supplier() { + @Override + public Processor get(ServiceNowEndpoint endpoint) throws Exception { + return new ServiceNowAggregateProcessor(endpoint); + } + }; + + public ServiceNowAggregateProcessor(ServiceNowEndpoint endpoint) throws Exception { + super(endpoint, ServiceNowAggregate.class); + } + + @Override + protected void doProcess(Exchange exchange, Class<?> model, String action, String tableName, String sysId) throws Exception { + if (ObjectHelper.equal(ServiceNowConstants.ACTION_RETRIEVE, action, true)) { + retrieveStats(exchange.getIn(), model, tableName); + } else { + throw new IllegalArgumentException("Unknown action " + action); + } + } + + private void retrieveStats(Message in, Class<?> model, String tableName) throws Exception { + setBody( + in, + model, + client.retrieveStats( + tableName, + in.getHeader(ServiceNowConstants.SYSPARM_QUERY, String.class), + in.getHeader(ServiceNowConstants.SYSPARM_AVG_FIELDS, String.class), + in.getHeader(ServiceNowConstants.SYSPARM_COUNT, String.class), + in.getHeader(ServiceNowConstants.SYSPARM_MIN_FIELDS, String.class), + in.getHeader(ServiceNowConstants.SYSPARM_MAX_FIELDS, String.class), + in.getHeader(ServiceNowConstants.SYSPARM_SUM_FIELDS, String.class), + in.getHeader(ServiceNowConstants.SYSPARM_GROUP_BY, String.class), + in.getHeader(ServiceNowConstants.SYSPARM_ORDER_BY, String.class), + in.getHeader(ServiceNowConstants.SYSPARM_HAVING, String.class), + in.getHeader(ServiceNowConstants.SYSPARM_DISPLAY_VALUE, config.getDisplayValue(), String.class) + ) + ); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/aa7ca432/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowImportSet.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowImportSet.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowImportSet.java new file mode 100644 index 0000000..865187e --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowImportSet.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.servicenow.model; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; + +import com.fasterxml.jackson.databind.JsonNode; +import org.apache.camel.component.servicenow.ServiceNowException; + +@Path("/import") +@Produces("application/json") +@Consumes("application/json") +public interface ServiceNowImportSet { + + @GET + @Path("{tableName}/{sysId}") + JsonNode retrieveRecordById( + @PathParam("tableName") String tableName, + @PathParam("sysId") String id + ) throws ServiceNowException; + + @POST + @Path("{tableName}") + JsonNode createRecord( + @PathParam("tableName") String tableName, + String body + ) throws ServiceNowException; +} http://git-wip-us.apache.org/repos/asf/camel/blob/aa7ca432/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowImportSetProcessor.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowImportSetProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowImportSetProcessor.java new file mode 100644 index 0000000..e76e9c1 --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowImportSetProcessor.java @@ -0,0 +1,79 @@ +/** + * 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.servicenow.model; + +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.Processor; +import org.apache.camel.component.servicenow.ServiceNowConstants; +import org.apache.camel.component.servicenow.ServiceNowEndpoint; +import org.apache.camel.component.servicenow.ServiceNowProducerProcessor; +import org.apache.camel.util.ObjectHelper; + +public class ServiceNowImportSetProcessor extends ServiceNowProducerProcessor<ServiceNowImportSet> { + + public static final ServiceNowProducerProcessor.Supplier SUPPLIER = new ServiceNowProducerProcessor.Supplier() { + @Override + public Processor get(ServiceNowEndpoint endpoint) throws Exception { + return new ServiceNowImportSetProcessor(endpoint); + } + }; + + public ServiceNowImportSetProcessor(ServiceNowEndpoint endpoint) throws Exception { + super(endpoint, ServiceNowImportSet.class); + } + + @Override + protected void doProcess(Exchange exchange, Class<?> model, String action, String tableName, String sysId) throws Exception { + if (ObjectHelper.equal(ServiceNowConstants.ACTION_RETRIEVE, action, true)) { + retrieveRecord(exchange.getIn(), model, tableName, sysId); + } else if (ObjectHelper.equal(ServiceNowConstants.ACTION_CREATE, action, true)) { + createRecord(exchange.getIn(), model, tableName); + } else { + throw new IllegalArgumentException("Unknown action " + action); + } + } + + /* + * GET https://instance.service-now.com/api/now/import/{tableName}/{sys_id} + */ + private void retrieveRecord(Message in, Class<?> model, String tableName, String sysId) throws Exception { + setBody( + in, + model, + client.retrieveRecordById( + tableName, + ObjectHelper.notNull(sysId, "sysId")) + ); + } + + + /* + * POST https://instance.service-now.com/api/now/import/{tableName} + */ + private void createRecord(Message in, Class<?> model, String tableName) throws Exception { + validateBody(in, model); + setBody( + in, + model, + client.createRecord( + tableName, + mapper.writeValueAsString(in.getBody()) + ) + ); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/aa7ca432/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowTable.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowTable.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowTable.java new file mode 100644 index 0000000..366d8ee --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowTable.java @@ -0,0 +1,108 @@ +/** + * 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.servicenow.model; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; + +import com.fasterxml.jackson.databind.JsonNode; +import org.apache.camel.component.servicenow.ServiceNowException; +import org.apache.cxf.jaxrs.ext.PATCH; + +@Path("/table") +@Produces("application/json") +@Consumes("application/json") +public interface ServiceNowTable { + + @GET + @Path("{tableName}") + JsonNode retrieveRecord( + @PathParam("tableName") String tableName, + @QueryParam("sysparm_query") String query, + @QueryParam("sysparm_display_value") String displayValue, + @QueryParam("sysparm_exclude_reference_link") Boolean excludeReferenceLink, + @QueryParam("sysparm_fields") String fields, + @QueryParam("sysparm_limit") Integer limit, + @QueryParam("sysparm_view") String view + ) throws ServiceNowException; + + @GET + @Path("{tableName}/{sysId}") + JsonNode retrieveRecordById( + @PathParam("tableName") String tableName, + @PathParam("sysId") String id, + @QueryParam("sysparm_display_value") String displayValue, + @QueryParam("sysparm_exclude_reference_link") Boolean excludeReferenceLink, + @QueryParam("sysparm_fields") String fields, + @QueryParam("sysparm_view") String view + ) throws ServiceNowException; + + @POST + @Path("{tableName}") + JsonNode createRecord( + @PathParam("tableName") String tableName, + @QueryParam("sysparm_display_value") String displayValue, + @QueryParam("sysparm_exclude_reference_link") Boolean excludeReferenceLink, + @QueryParam("sysparm_fields") String fields, + @QueryParam("sysparm_input_display_value") Boolean inputDisplayValue, + @QueryParam("sysparm_suppress_auto_sys_field") Boolean suppressAutoSysField, + @QueryParam("sysparm_view") String view, + String body + ) throws ServiceNowException; + + @PUT + @Path("{tableName}/{sysId}") + JsonNode modifyRecord( + @PathParam("tableName") String tableName, + @PathParam("sysId") String id, + @QueryParam("sysparm_display_value") String displayValue, + @QueryParam("sysparm_exclude_reference_link") Boolean excludeReferenceLink, + @QueryParam("sysparm_fields") String fields, + @QueryParam("sysparm_input_display_value") Boolean inputDisplayValue, + @QueryParam("sysparm_suppress_auto_sys_field") Boolean suppressAutoSysField, + @QueryParam("sysparm_view") String view, + String body + ) throws ServiceNowException; + + @DELETE + @Path("{tableName}/{sysId}") + JsonNode deleteRecord( + @PathParam("tableName") String tableName, + @PathParam("sysId") String id + ) throws ServiceNowException; + + @PATCH + @Path("{tableName}/{sysId}") + JsonNode updateRecord( + @PathParam("tableName") String tableName, + @PathParam("sysId") String id, + @QueryParam("sysparm_display_value") String displayValue, + @QueryParam("sysparm_exclude_reference_link") Boolean excludeReferenceLink, + @QueryParam("sysparm_fields") String fields, + @QueryParam("sysparm_input_display_value") Boolean inputDisplayValue, + @QueryParam("sysparm_suppress_auto_sys_field") Boolean suppressAutoSysField, + @QueryParam("sysparm_view") String view, + String body + ) throws ServiceNowException; +} http://git-wip-us.apache.org/repos/asf/camel/blob/aa7ca432/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowTableProcessor.java ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowTableProcessor.java b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowTableProcessor.java new file mode 100644 index 0000000..7b6504d --- /dev/null +++ b/components/camel-servicenow/src/main/java/org/apache/camel/component/servicenow/model/ServiceNowTableProcessor.java @@ -0,0 +1,169 @@ +/** + * 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.servicenow.model; + +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.Processor; +import org.apache.camel.component.servicenow.ServiceNowConstants; +import org.apache.camel.component.servicenow.ServiceNowEndpoint; +import org.apache.camel.component.servicenow.ServiceNowProducerProcessor; +import org.apache.camel.util.ObjectHelper; + +public class ServiceNowTableProcessor extends ServiceNowProducerProcessor<ServiceNowTable> { + + public static final ServiceNowProducerProcessor.Supplier SUPPLIER = new ServiceNowProducerProcessor.Supplier() { + @Override + public Processor get(ServiceNowEndpoint endpoint) throws Exception { + return new ServiceNowTableProcessor(endpoint); + } + }; + + public ServiceNowTableProcessor(ServiceNowEndpoint endpoint) throws Exception { + super(endpoint, ServiceNowTable.class); + } + + @Override + protected void doProcess(Exchange exchange, Class<?> model, String action, String tableName, String sysId) throws Exception { + if (ObjectHelper.equal(ServiceNowConstants.ACTION_RETRIEVE, action, true)) { + retrieveRecord(exchange.getIn(), model, tableName, sysId); + } else if (ObjectHelper.equal(ServiceNowConstants.ACTION_CREATE, action, true)) { + createRecord(exchange.getIn(), model, tableName); + } else if (ObjectHelper.equal(ServiceNowConstants.ACTION_MODIFY, action, true)) { + modifyRecord(exchange.getIn(), model, tableName, sysId); + } else if (ObjectHelper.equal(ServiceNowConstants.ACTION_DELETE, action, true)) { + deleteRecord(exchange.getIn(), model, tableName, sysId); + } else if (ObjectHelper.equal(ServiceNowConstants.ACTION_UPDATE, action, true)) { + updateRecord(exchange.getIn(), model, tableName, sysId); + } else { + throw new IllegalArgumentException("Unknown action " + action); + } + } + + /* + * GET https://instance.service-now.com/api/now/table/{tableName} + * GET https://instance.service-now.com/api/now/table/{tableName}/{sys_id} + */ + private void retrieveRecord(Message in, Class<?> model, String tableName, String sysId) throws Exception { + if (sysId == null) { + setBody( + in, + model, + client.retrieveRecord( + tableName, + in.getHeader(ServiceNowConstants.SYSPARM_QUERY, String.class), + in.getHeader(ServiceNowConstants.SYSPARM_DISPLAY_VALUE, config.getDisplayValue(), String.class), + in.getHeader(ServiceNowConstants.SYSPARM_EXCLUDE_REFERENCE_LINK, config.getExcludeReferenceLink(), Boolean.class), + in.getHeader(ServiceNowConstants.SYSPARM_FIELDS, String.class), + in.getHeader(ServiceNowConstants.SYSPARM_LIMIT, Integer.class), + in.getHeader(ServiceNowConstants.SYSPARM_VIEW, String.class) + ) + ); + } else { + setBody( + in, + model, + client.retrieveRecordById( + tableName, + ObjectHelper.notNull(sysId, "sysId"), + in.getHeader(ServiceNowConstants.SYSPARM_DISPLAY_VALUE, config.getDisplayValue(), String.class), + in.getHeader(ServiceNowConstants.SYSPARM_EXCLUDE_REFERENCE_LINK, config.getExcludeReferenceLink(), Boolean.class), + in.getHeader(ServiceNowConstants.SYSPARM_FIELDS, String.class), + in.getHeader(ServiceNowConstants.SYSPARM_VIEW, String.class) + ) + ); + } + } + + /* + * POST https://instance.service-now.com/api/now/table/{tableName} + */ + private void createRecord(Message in, Class<?> model, String tableName) throws Exception { + validateBody(in, model); + setBody( + in, + model, + client.createRecord( + tableName, + in.getHeader(ServiceNowConstants.SYSPARM_DISPLAY_VALUE, config.getDisplayValue(), String.class), + in.getHeader(ServiceNowConstants.SYSPARM_EXCLUDE_REFERENCE_LINK, config.getExcludeReferenceLink(), Boolean.class), + in.getHeader(ServiceNowConstants.SYSPARM_FIELDS, String.class), + in.getHeader(ServiceNowConstants.SYSPARM_INPUT_DISPLAY_VALUE, config.getInputDisplayValue(), Boolean.class), + in.getHeader(ServiceNowConstants.SYSPARM_SUPPRESS_AUTO_SYS_FIELD, config.getSuppressAutoSysField(), Boolean.class), + in.getHeader(ServiceNowConstants.SYSPARM_VIEW, String.class), + mapper.writeValueAsString(in.getBody()) + ) + ); + } + + /* + * PUT https://instance.service-now.com/api/now/table/{tableName}/{sys_id} + */ + private void modifyRecord(Message in, Class<?> model, String tableName, String sysId) throws Exception { + validateBody(in, model); + setBody( + in, + model, + client.modifyRecord( + tableName, + ObjectHelper.notNull(sysId, "sysId"), + in.getHeader(ServiceNowConstants.SYSPARM_DISPLAY_VALUE, config.getDisplayValue(), String.class), + in.getHeader(ServiceNowConstants.SYSPARM_EXCLUDE_REFERENCE_LINK, config.getExcludeReferenceLink(), Boolean.class), + in.getHeader(ServiceNowConstants.SYSPARM_FIELDS, String.class), + in.getHeader(ServiceNowConstants.SYSPARM_INPUT_DISPLAY_VALUE, config.getInputDisplayValue(), Boolean.class), + in.getHeader(ServiceNowConstants.SYSPARM_SUPPRESS_AUTO_SYS_FIELD, config.getSuppressAutoSysField(), Boolean.class), + in.getHeader(ServiceNowConstants.SYSPARM_VIEW, String.class), + mapper.writeValueAsString(in.getBody()) + ) + ); + } + + /* + * DELETE https://instance.service-now.com/api/now/table/{tableName}/{sys_id} + */ + private void deleteRecord(Message in, Class<?> model, String tableName, String sysId) throws Exception { + setBody( + in, + model, + client.deleteRecord( + tableName, + ObjectHelper.notNull(sysId, "sysId")) + ); + } + + /* + * PATCH instance://dev21005.service-now.com/api/now/table/{tableName}/{sys_id} + */ + private void updateRecord(Message in, Class<?> model, String tableName, String sysId) throws Exception { + validateBody(in, model); + setBody( + in, + model, + client.updateRecord( + tableName, + ObjectHelper.notNull(sysId, "sysId"), + in.getHeader(ServiceNowConstants.SYSPARM_DISPLAY_VALUE, config.getDisplayValue(), String.class), + in.getHeader(ServiceNowConstants.SYSPARM_EXCLUDE_REFERENCE_LINK, config.getExcludeReferenceLink(), Boolean.class), + in.getHeader(ServiceNowConstants.SYSPARM_FIELDS, String.class), + in.getHeader(ServiceNowConstants.SYSPARM_INPUT_DISPLAY_VALUE, config.getInputDisplayValue(), Boolean.class), + in.getHeader(ServiceNowConstants.SYSPARM_SUPPRESS_AUTO_SYS_FIELD, config.getSuppressAutoSysField(), Boolean.class), + in.getHeader(ServiceNowConstants.SYSPARM_VIEW, String.class), + mapper.writeValueAsString(in.getBody()) + ) + ); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/aa7ca432/components/camel-servicenow/src/main/resources/META-INF/services/org/apache/camel/component/servicenow ---------------------------------------------------------------------- diff --git a/components/camel-servicenow/src/main/resources/META-INF/services/org/apache/camel/component/servicenow b/components/camel-servicenow/src/main/resources/META-INF/services/org/apache/camel/component/servicenow new file mode 100644 index 0000000..be9acb6 --- /dev/null +++ b/components/camel-servicenow/src/main/resources/META-INF/services/org/apache/camel/component/servicenow @@ -0,0 +1 @@ +class=org.apache.camel.component.servicenow.ServiceNowComponent