You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by GitBox <gi...@apache.org> on 2022/05/27 15:20:19 UTC

[GitHub] [camel] orpiske commented on a diff in pull request #7683: ✨ camel-whatsapp component

orpiske commented on code in PR #7683:
URL: https://github.com/apache/camel/pull/7683#discussion_r883696299


##########
components/camel-whatsapp/src/main/java/org/apache/camel/component/whatsapp/service/WhatsAppServiceRestAPIAdapter.java:
##########
@@ -0,0 +1,285 @@
+package org.apache.camel.component.whatsapp.service;
+
+import static org.asynchttpclient.util.HttpUtils.extractContentTypeCharsetAttribute;
+import static org.asynchttpclient.util.MiscUtils.withDefault;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.Exchange;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.whatsapp.WhatsAppService;
+import org.apache.camel.component.whatsapp.model.BaseMessage;
+import org.apache.camel.component.whatsapp.model.ContactMessageRequest;
+import org.apache.camel.component.whatsapp.model.InteractiveMessageRequest;
+import org.apache.camel.component.whatsapp.model.LocationMessageRequest;
+import org.apache.camel.component.whatsapp.model.MediaMessageRequest;
+import org.apache.camel.component.whatsapp.model.MessageResponse;
+import org.apache.camel.component.whatsapp.model.TextMessageRequest;
+import org.apache.camel.component.whatsapp.model.UploadMediaRequest;
+import org.apache.camel.support.GZIPHelper;
+import org.apache.camel.util.IOHelper;
+
+import org.asynchttpclient.AsyncHandler;
+import org.asynchttpclient.AsyncHttpClient;
+import org.asynchttpclient.HttpResponseBodyPart;
+import org.asynchttpclient.HttpResponseStatus;
+import org.asynchttpclient.RequestBuilder;
+import org.asynchttpclient.request.body.multipart.ByteArrayPart;
+import org.asynchttpclient.request.body.multipart.FilePart;
+import org.asynchttpclient.request.body.multipart.MultipartUtils;
+import org.asynchttpclient.request.body.multipart.StringPart;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import io.netty.handler.codec.http.HttpHeaders;
+
+public class WhatsAppServiceRestAPIAdapter implements WhatsAppService {
+	private static final Logger LOG = LoggerFactory.getLogger(WhatsAppServiceRestAPIAdapter.class);
+
+	private final Map<Class<?>, WhatsAppServiceRestAPIAdapter.OutgoingMessageHandler<?>> handlers;
+	private final AsyncHttpClient asyncHttpClient;
+	private final ObjectMapper mapper;
+	private final String baseUri;
+	private final String authorizationToken;
+
+	public WhatsAppServiceRestAPIAdapter(AsyncHttpClient client, String baseUri, String apiVersion, String phoneNumberId, String authorizationToken) {
+		this.asyncHttpClient = client;
+		this.baseUri = baseUri + "/" + apiVersion + "/" + phoneNumberId;
+		this.mapper = new ObjectMapper().registerModule(new JavaTimeModule());
+		this.mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		this.authorizationToken = authorizationToken;
+
+		int bufferSize = 4 * 1024;
+
+		final Map<Class<?>, WhatsAppServiceRestAPIAdapter.OutgoingMessageHandler<?>> m = new HashMap<>();
+		m.put(TextMessageRequest.class, new OutgoingPlainMessageHandler(client, bufferSize, mapper, this.baseUri + "/messages"));

Review Comment:
   Maybe use a constant for the `/messages` endpoint? 



##########
components/camel-whatsapp/src/test/java/org/apache/camel/component/whatsapp/WhatsAppApiConfig.java:
##########
@@ -0,0 +1,72 @@
+/*
+ *
+ * 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.whatsapp;
+
+public class WhatsAppApiConfig {
+
+	private final String authorizationToken;
+	private final int port;
+	private final String baseUri;
+	private final String phoneNumberId;
+	private final String apiVersion;
+	private final String recipientPhoneNumber;
+
+	public WhatsAppApiConfig(String baseUri, int port, String authorizationToken, String phoneNumberId, String apiVersion, String recipientPhoneNumber) {
+		this.baseUri = baseUri;
+		this.port = port;
+		this.authorizationToken = authorizationToken;
+		this.phoneNumberId = phoneNumberId;
+		this.apiVersion = apiVersion;
+		this.recipientPhoneNumber = recipientPhoneNumber;
+	}
+
+	public static WhatsAppApiConfig fromEnv() {
+		final String authorizationToken = System.getenv("WHATSAPP_AUTHORIZATION_TOKEN");
+		final String phoneNumberId = System.getenv("WHATSAPP_PHONE_NUMBER_ID");
+		final String recipientPhoneNumber = System.getenv("WHATSAPP_RECIPIENT_PHONE_NUMBER");
+		return new WhatsAppApiConfig(WhatsAppComponent.API_DEFAULT_URL, 443, authorizationToken, phoneNumberId, WhatsAppComponent.API_DEFAULT_VERSION, recipientPhoneNumber);

Review Comment:
   If possible, try not to use a fixed port as it breaks the tests on some CIs if the port is used (and, also, 443 is a privileged port that would require root access). Take a look at the `AvailablePortFinder` class for this.



##########
components/camel-whatsapp/src/main/java/org/apache/camel/component/whatsapp/WhatsAppProducer.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.component.whatsapp;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.Exchange;
+import org.apache.camel.component.whatsapp.model.BaseMessage;
+import org.apache.camel.component.whatsapp.model.TextMessageRequest;
+import org.apache.camel.support.DefaultAsyncProducer;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class WhatsAppProducer extends DefaultAsyncProducer {
+	private static final Logger LOG = LoggerFactory.getLogger(WhatsAppProducer.class);
+
+	private WhatsAppEndpoint endpoint;
+
+	public WhatsAppProducer(WhatsAppEndpoint endpoint) {
+		super(endpoint);
+		this.endpoint = endpoint;
+	}
+
+	@Override
+	public boolean process(Exchange exchange, AsyncCallback callback) {
+		if (exchange.getIn().getBody() == null) {
+			// fail fast
+			LOG.debug("Received exchange with empty body, skipping");
+			callback.done(true);
+			return true;
+		}
+
+		WhatsAppConfiguration config = endpoint.getConfiguration();
+
+		// Tries to get a message in its OutgoingMessage format
+		// Automatic conversion applies here
+		BaseMessage message = exchange.getIn().getBody(BaseMessage.class);
+		if (message == null) {
+			throw new IllegalArgumentException("Cannot convert the content to a WhatsApp MessageRequest");
+		}

Review Comment:
   I think you can use `ObjectHelper.notNull` here. 



##########
components/camel-whatsapp/src/main/java/org/apache/camel/component/whatsapp/WhatsAppProducer.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.component.whatsapp;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.Exchange;
+import org.apache.camel.component.whatsapp.model.BaseMessage;
+import org.apache.camel.component.whatsapp.model.TextMessageRequest;
+import org.apache.camel.support.DefaultAsyncProducer;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class WhatsAppProducer extends DefaultAsyncProducer {
+	private static final Logger LOG = LoggerFactory.getLogger(WhatsAppProducer.class);
+
+	private WhatsAppEndpoint endpoint;
+
+	public WhatsAppProducer(WhatsAppEndpoint endpoint) {
+		super(endpoint);
+		this.endpoint = endpoint;
+	}
+
+	@Override
+	public boolean process(Exchange exchange, AsyncCallback callback) {
+		if (exchange.getIn().getBody() == null) {
+			// fail fast
+			LOG.debug("Received exchange with empty body, skipping");
+			callback.done(true);
+			return true;
+		}
+
+		WhatsAppConfiguration config = endpoint.getConfiguration();
+
+		// Tries to get a message in its OutgoingMessage format
+		// Automatic conversion applies here
+		BaseMessage message = exchange.getIn().getBody(BaseMessage.class);
+		if (message == null) {
+			throw new IllegalArgumentException("Cannot convert the content to a WhatsApp MessageRequest");
+		}
+
+		final WhatsAppService service = endpoint.getWhatsappService();
+
+		LOG.debug("Message being sent is: {}", message);
+		LOG.debug("Headers of message being sent are: {}", exchange.getIn().getHeaders());
+
+		service.sendMessage(exchange, callback, message);

Review Comment:
   Is there a change of `service` being `null` here? It does not look like the case, so ... just double checking.



##########
components/camel-whatsapp/src/main/java/org/apache/camel/component/whatsapp/service/WhatsAppServiceRestAPIAdapter.java:
##########
@@ -0,0 +1,285 @@
+package org.apache.camel.component.whatsapp.service;
+
+import static org.asynchttpclient.util.HttpUtils.extractContentTypeCharsetAttribute;
+import static org.asynchttpclient.util.MiscUtils.withDefault;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.Exchange;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.whatsapp.WhatsAppService;
+import org.apache.camel.component.whatsapp.model.BaseMessage;
+import org.apache.camel.component.whatsapp.model.ContactMessageRequest;
+import org.apache.camel.component.whatsapp.model.InteractiveMessageRequest;
+import org.apache.camel.component.whatsapp.model.LocationMessageRequest;
+import org.apache.camel.component.whatsapp.model.MediaMessageRequest;
+import org.apache.camel.component.whatsapp.model.MessageResponse;
+import org.apache.camel.component.whatsapp.model.TextMessageRequest;
+import org.apache.camel.component.whatsapp.model.UploadMediaRequest;
+import org.apache.camel.support.GZIPHelper;
+import org.apache.camel.util.IOHelper;
+
+import org.asynchttpclient.AsyncHandler;
+import org.asynchttpclient.AsyncHttpClient;
+import org.asynchttpclient.HttpResponseBodyPart;
+import org.asynchttpclient.HttpResponseStatus;
+import org.asynchttpclient.RequestBuilder;
+import org.asynchttpclient.request.body.multipart.ByteArrayPart;
+import org.asynchttpclient.request.body.multipart.FilePart;
+import org.asynchttpclient.request.body.multipart.MultipartUtils;
+import org.asynchttpclient.request.body.multipart.StringPart;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import io.netty.handler.codec.http.HttpHeaders;
+
+public class WhatsAppServiceRestAPIAdapter implements WhatsAppService {
+	private static final Logger LOG = LoggerFactory.getLogger(WhatsAppServiceRestAPIAdapter.class);
+
+	private final Map<Class<?>, WhatsAppServiceRestAPIAdapter.OutgoingMessageHandler<?>> handlers;
+	private final AsyncHttpClient asyncHttpClient;
+	private final ObjectMapper mapper;
+	private final String baseUri;
+	private final String authorizationToken;
+
+	public WhatsAppServiceRestAPIAdapter(AsyncHttpClient client, String baseUri, String apiVersion, String phoneNumberId, String authorizationToken) {
+		this.asyncHttpClient = client;
+		this.baseUri = baseUri + "/" + apiVersion + "/" + phoneNumberId;
+		this.mapper = new ObjectMapper().registerModule(new JavaTimeModule());
+		this.mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		this.authorizationToken = authorizationToken;
+
+		int bufferSize = 4 * 1024;
+
+		final Map<Class<?>, WhatsAppServiceRestAPIAdapter.OutgoingMessageHandler<?>> m = new HashMap<>();
+		m.put(TextMessageRequest.class, new OutgoingPlainMessageHandler(client, bufferSize, mapper, this.baseUri + "/messages"));
+		m.put(MediaMessageRequest.class, new OutgoingPlainMessageHandler(client, bufferSize, mapper, this.baseUri + "/messages"));
+		m.put(LocationMessageRequest.class, new OutgoingPlainMessageHandler(client, bufferSize, mapper, this.baseUri + "/messages"));
+		m.put(ContactMessageRequest.class, new OutgoingPlainMessageHandler(client, bufferSize, mapper, this.baseUri + "/messages"));
+		m.put(InteractiveMessageRequest.class, new OutgoingPlainMessageHandler(client, bufferSize, mapper, this.baseUri + "/messages"));
+		m.put(UploadMediaRequest.class, new OutgoingMediaMessageHandler(client, bufferSize, mapper, this.baseUri + "/media"));
+
+		this.handlers = m;
+	}
+
+	@Override
+	public void sendMessage(Exchange exchange, AsyncCallback callback, BaseMessage message) {
+		final WhatsAppServiceRestAPIAdapter.OutgoingMessageHandler<BaseMessage> handler =
+				(WhatsAppServiceRestAPIAdapter.OutgoingMessageHandler<BaseMessage>) handlers.get(message.getClass());
+		if (handler == null) {
+			throw new IllegalArgumentException(
+					"Unsupported message type " + (message.getClass().getName()));
+		}

Review Comment:
   You can use `ObjectHelper.notNull` here.



##########
components/camel-whatsapp/src/main/java/org/apache/camel/component/whatsapp/service/WhatsAppServiceRestAPIAdapter.java:
##########
@@ -0,0 +1,285 @@
+package org.apache.camel.component.whatsapp.service;
+
+import static org.asynchttpclient.util.HttpUtils.extractContentTypeCharsetAttribute;
+import static org.asynchttpclient.util.MiscUtils.withDefault;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.Exchange;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.whatsapp.WhatsAppService;
+import org.apache.camel.component.whatsapp.model.BaseMessage;
+import org.apache.camel.component.whatsapp.model.ContactMessageRequest;
+import org.apache.camel.component.whatsapp.model.InteractiveMessageRequest;
+import org.apache.camel.component.whatsapp.model.LocationMessageRequest;
+import org.apache.camel.component.whatsapp.model.MediaMessageRequest;
+import org.apache.camel.component.whatsapp.model.MessageResponse;
+import org.apache.camel.component.whatsapp.model.TextMessageRequest;
+import org.apache.camel.component.whatsapp.model.UploadMediaRequest;
+import org.apache.camel.support.GZIPHelper;
+import org.apache.camel.util.IOHelper;
+
+import org.asynchttpclient.AsyncHandler;
+import org.asynchttpclient.AsyncHttpClient;
+import org.asynchttpclient.HttpResponseBodyPart;
+import org.asynchttpclient.HttpResponseStatus;
+import org.asynchttpclient.RequestBuilder;
+import org.asynchttpclient.request.body.multipart.ByteArrayPart;
+import org.asynchttpclient.request.body.multipart.FilePart;
+import org.asynchttpclient.request.body.multipart.MultipartUtils;
+import org.asynchttpclient.request.body.multipart.StringPart;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import io.netty.handler.codec.http.HttpHeaders;
+
+public class WhatsAppServiceRestAPIAdapter implements WhatsAppService {
+	private static final Logger LOG = LoggerFactory.getLogger(WhatsAppServiceRestAPIAdapter.class);
+
+	private final Map<Class<?>, WhatsAppServiceRestAPIAdapter.OutgoingMessageHandler<?>> handlers;
+	private final AsyncHttpClient asyncHttpClient;
+	private final ObjectMapper mapper;
+	private final String baseUri;
+	private final String authorizationToken;
+
+	public WhatsAppServiceRestAPIAdapter(AsyncHttpClient client, String baseUri, String apiVersion, String phoneNumberId, String authorizationToken) {
+		this.asyncHttpClient = client;
+		this.baseUri = baseUri + "/" + apiVersion + "/" + phoneNumberId;
+		this.mapper = new ObjectMapper().registerModule(new JavaTimeModule());
+		this.mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		this.authorizationToken = authorizationToken;
+
+		int bufferSize = 4 * 1024;
+
+		final Map<Class<?>, WhatsAppServiceRestAPIAdapter.OutgoingMessageHandler<?>> m = new HashMap<>();
+		m.put(TextMessageRequest.class, new OutgoingPlainMessageHandler(client, bufferSize, mapper, this.baseUri + "/messages"));
+		m.put(MediaMessageRequest.class, new OutgoingPlainMessageHandler(client, bufferSize, mapper, this.baseUri + "/messages"));
+		m.put(LocationMessageRequest.class, new OutgoingPlainMessageHandler(client, bufferSize, mapper, this.baseUri + "/messages"));
+		m.put(ContactMessageRequest.class, new OutgoingPlainMessageHandler(client, bufferSize, mapper, this.baseUri + "/messages"));
+		m.put(InteractiveMessageRequest.class, new OutgoingPlainMessageHandler(client, bufferSize, mapper, this.baseUri + "/messages"));
+		m.put(UploadMediaRequest.class, new OutgoingMediaMessageHandler(client, bufferSize, mapper, this.baseUri + "/media"));
+
+		this.handlers = m;
+	}
+
+	@Override
+	public void sendMessage(Exchange exchange, AsyncCallback callback, BaseMessage message) {
+		final WhatsAppServiceRestAPIAdapter.OutgoingMessageHandler<BaseMessage> handler =
+				(WhatsAppServiceRestAPIAdapter.OutgoingMessageHandler<BaseMessage>) handlers.get(message.getClass());
+		if (handler == null) {
+			throw new IllegalArgumentException(
+					"Unsupported message type " + (message.getClass().getName()));
+		}
+		handler.sendMessage(exchange, callback, message, authorizationToken);
+	}
+
+	static class OutgoingMediaMessageHandler extends WhatsAppServiceRestAPIAdapter.OutgoingMessageHandler<UploadMediaRequest> {
+
+		public OutgoingMediaMessageHandler(AsyncHttpClient asyncHttpClient, int bufferSize, ObjectMapper mapper,
+				String uri, Class<? extends MessageResponse> returnType) {
+			super(asyncHttpClient, bufferSize, mapper, uri, "multipart/form-data", returnType);
+		}
+
+		public OutgoingMediaMessageHandler(AsyncHttpClient asyncHttpClient, int bufferSize, ObjectMapper mapper,
+				String uri) {
+			this(asyncHttpClient, bufferSize, mapper, uri, MessageResponse.class);
+		}
+
+		@Override
+		protected void addBody(RequestBuilder builder, UploadMediaRequest message) {
+			FilePart filePart = new FilePart("file", message.getUploadMedia().getFile(), message.getUploadMedia().getContentType());
+			builder.setBodyParts(List.of(
+					filePart,
+					new StringPart("messaging_product", "whatsapp")
+			));
+		}
+
+	}
+
+	static class OutgoingPlainMessageHandler extends WhatsAppServiceRestAPIAdapter.OutgoingMessageHandler<BaseMessage> {
+
+		public OutgoingPlainMessageHandler(AsyncHttpClient asyncHttpClient, int bufferSize, ObjectMapper mapper,
+				String uri, Class<? extends MessageResponse> returnType) {
+			super(asyncHttpClient, bufferSize, mapper, uri, "application/json", returnType);
+		}
+
+		public OutgoingPlainMessageHandler(AsyncHttpClient asyncHttpClient, int bufferSize, ObjectMapper mapper,
+				String uri) {
+			this(asyncHttpClient, bufferSize, mapper, uri, MessageResponse.class);
+		}
+
+		@Override
+		protected void addBody(RequestBuilder builder, BaseMessage message) {
+			try {
+				final String body = mapper.writeValueAsString(message);
+				builder.setBody(body);
+			} catch (JsonProcessingException e) {
+				throw new RuntimeCamelException("Could not serialize " + message, e);
+			}
+		}
+
+	}
+
+	abstract static class OutgoingMessageHandler<T extends BaseMessage> {
+		protected final ObjectMapper mapper;
+		private final AsyncHttpClient asyncHttpClient;
+		private final int bufferSize;
+		private final String contentType;
+		private final String uri;
+		private final Class<? extends MessageResponse> resultClass;
+
+		public OutgoingMessageHandler(AsyncHttpClient asyncHttpClient, int bufferSize, ObjectMapper mapper, String uri,
+				String contentType, Class<? extends MessageResponse> resultClass) {
+			this.resultClass = resultClass;
+			this.asyncHttpClient = asyncHttpClient;
+			this.bufferSize = bufferSize;
+			this.mapper = mapper;
+			this.uri = uri;
+			this.contentType = contentType;
+		}
+
+		public void sendMessage(Exchange exchange, AsyncCallback callback, T message, String authorizationToken) {
+			final RequestBuilder builder = new RequestBuilder("POST")
+					.setUrl(uri);
+			if (contentType != null) {
+				builder.setHeader("Content-Type", contentType);
+			}
+			builder.setHeader("Authorization", "Bearer " + authorizationToken);
+			builder.setHeader("Accept", "application/json");

Review Comment:
   Header constants, if they are available in one of the libraries in use, can make the code easier to read/maintain.



##########
components/camel-whatsapp/src/main/java/org/apache/camel/component/whatsapp/service/WhatsAppServiceRestAPIAdapter.java:
##########
@@ -0,0 +1,285 @@
+package org.apache.camel.component.whatsapp.service;
+
+import static org.asynchttpclient.util.HttpUtils.extractContentTypeCharsetAttribute;
+import static org.asynchttpclient.util.MiscUtils.withDefault;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.Exchange;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.whatsapp.WhatsAppService;
+import org.apache.camel.component.whatsapp.model.BaseMessage;
+import org.apache.camel.component.whatsapp.model.ContactMessageRequest;
+import org.apache.camel.component.whatsapp.model.InteractiveMessageRequest;
+import org.apache.camel.component.whatsapp.model.LocationMessageRequest;
+import org.apache.camel.component.whatsapp.model.MediaMessageRequest;
+import org.apache.camel.component.whatsapp.model.MessageResponse;
+import org.apache.camel.component.whatsapp.model.TextMessageRequest;
+import org.apache.camel.component.whatsapp.model.UploadMediaRequest;
+import org.apache.camel.support.GZIPHelper;
+import org.apache.camel.util.IOHelper;
+
+import org.asynchttpclient.AsyncHandler;
+import org.asynchttpclient.AsyncHttpClient;
+import org.asynchttpclient.HttpResponseBodyPart;
+import org.asynchttpclient.HttpResponseStatus;
+import org.asynchttpclient.RequestBuilder;
+import org.asynchttpclient.request.body.multipart.ByteArrayPart;
+import org.asynchttpclient.request.body.multipart.FilePart;
+import org.asynchttpclient.request.body.multipart.MultipartUtils;
+import org.asynchttpclient.request.body.multipart.StringPart;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import io.netty.handler.codec.http.HttpHeaders;
+
+public class WhatsAppServiceRestAPIAdapter implements WhatsAppService {
+	private static final Logger LOG = LoggerFactory.getLogger(WhatsAppServiceRestAPIAdapter.class);
+
+	private final Map<Class<?>, WhatsAppServiceRestAPIAdapter.OutgoingMessageHandler<?>> handlers;
+	private final AsyncHttpClient asyncHttpClient;
+	private final ObjectMapper mapper;
+	private final String baseUri;
+	private final String authorizationToken;
+
+	public WhatsAppServiceRestAPIAdapter(AsyncHttpClient client, String baseUri, String apiVersion, String phoneNumberId, String authorizationToken) {
+		this.asyncHttpClient = client;
+		this.baseUri = baseUri + "/" + apiVersion + "/" + phoneNumberId;
+		this.mapper = new ObjectMapper().registerModule(new JavaTimeModule());
+		this.mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		this.authorizationToken = authorizationToken;
+
+		int bufferSize = 4 * 1024;

Review Comment:
   Any particular reason for this specific buffer size?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org