First of all I need to warn about the limitations. I’m going to tell how to prevent particular type of exceptions related to unreachable host:port. The approach allows for application to start up in case of this exception without the problematic route(s). Without the described below approach the entire application fails. It’s up to you to decide if the failure in a route should stop the application.
So, the trick is to check if the host:port, which are to be passed into route’s endpoint, is reachable. Sample route (please note the call of CustomSocketUtils.isReachable() which short short circuits the creation of route if the crucial host:port is unreachable):
package ru.outofrange.camel.as2.send; import ru.outofrange.camel.certloader.MendelsonCertLoader; import ru.outofrange.model.test.ArtemisTestMessage; import ru.outofrange.util.CustomSocketUtils; import com.sun.istack.ByteArrayDataSource; import org.apache.camel.*; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.as2.api.*; import org.apache.camel.component.as2.api.entity.DispositionNotificationMultipartReportEntity; import org.apache.camel.component.jackson.JacksonDataFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.mail.BodyPart; import javax.mail.Header; import javax.mail.MessagingException; import javax.mail.internet.MimeMultipart; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Enumeration; @Component public class MendelsonAs2ClientRouteBuilder extends RouteBuilder { private static final Logger LOG = LoggerFactory.getLogger(MendelsonAs2ClientRouteBuilder.class); private static final boolean NEED_SIGNED_ENCRYPTED = true; @Autowired CamelContext camelContext; @Autowired private MendelsonCertLoader mendelsonCertLoader; @Value("${as2.version}") private String as2Version; private String remoteHost = "testas2.mendelson-e-c.com"; private int remotePort = 8080; private static org.apache.http.entity.ContentType contentTypeEdifact = org.apache.http.entity.ContentType.create("application/edifact", (Charset) null); @Override public void configure() throws Exception { // if the remote host:port is unreachable, then exit early if (!CustomSocketUtils.isReachable(remoteHost, remotePort)) { LOG.warn("MendelsonAs2ClientRouteBuilder wasn't instantiated - remote " + remoteHost + ":" + remotePort + " unreachable"); return; } // expected format {"edi":"message_dk2k"} from("jetty:http://localhost:3400/link") .routeId("as2ClientMendelson") .unmarshal(new JacksonDataFormat(ArtemisTestMessage.class)) .process(new Processor() { @Override public void process(Exchange exchange) throws Exception { if (exchange.getIn() != null) { ArtemisTestMessage messageIn = exchange.getIn().getBody(ArtemisTestMessage.class); LOG.debug("Request Body Message: " + messageIn); if (messageIn != null) { exchange.getIn().setBody(messageIn.getEdi()); } else { exchange.getIn().setBody("_error"); } } // enriching exchange.getIn().setHeader("CamelAS2.as2To", "mendelsontestAS2"); exchange.getIn().setHeader("CamelAS2.as2From", "mycompanyAS2"); exchange.getIn().setHeader("CamelAS2.as2Version", "1.1"); exchange.getIn().setHeader("CamelAS2.ediMessageContentType", contentTypeEdifact); exchange.getIn().setHeader("CamelAS2.server", "DKAS2Client"); exchange.getIn().setHeader("CamelAS2.subject", "testDK"); exchange.getIn().setHeader("CamelAS2.from", "DKEdi"); exchange.getIn().setHeader("CamelAS2.dispositionNotificationTo", "dk2k@mail.ru"); exchange.getIn().setHeader("CamelAS2.requestUri", "/as2/HttpReceiver"); if (NEED_SIGNED_ENCRYPTED) { exchange.getIn().setHeader("CamelAS2.as2MessageStructure", AS2MessageStructure.SIGNED_ENCRYPTED); exchange.getIn().setHeader("CamelAS2.signingAlgorithm", AS2SignatureAlgorithm.SHA1WITHRSA); exchange.getIn().setHeader("CamelAS2.encryptingAlgorithm", AS2EncryptionAlgorithm.DES_EDE3_CBC); exchange.getIn().setHeader("CamelAS2.signingCertificateChain", mendelsonCertLoader.getChain()); exchange.getIn().setHeader("CamelAS2.signingPrivateKey", mendelsonCertLoader.getPrivateKey()); exchange.getIn().setHeader("CamelAS2.encryptingCertificateChain", mendelsonCertLoader.getChain()); } else { exchange.getIn().setHeader("CamelAS2.as2MessageStructure", AS2MessageStructure.PLAIN); } } }) .to("as2://client/send?targetHostName=" + remoteHost + "&targetPortNumber=" + remotePort + // http "&inBody=ediMessage" + "&requestUri=/as2/HttpReceiver" ) .id("DKAS2sender") .process(new Processor() { @Override public void process(Exchange exchange) throws Exception { String messageIn = exchange.getIn().getBody(String.class); LOG.debug("MDN Message: " + messageIn); processMultipartMessage(exchange.getIn()); } }); LOG.debug("Mendelson route created"); } private void processMultipartMessage(Message message) { //org.apache.camel.component.as2.api.entity.DispositionNotificationMultipartReportEntity if (message.getBody() instanceof DispositionNotificationMultipartReportEntity) { DispositionNotificationMultipartReportEntity dispositionNotificationMultipartReportEntity = (DispositionNotificationMultipartReportEntity) message.getBody(); try { InputStream inputStream = dispositionNotificationMultipartReportEntity.getContent(); ByteArrayDataSource datasource = new ByteArrayDataSource(inputStream.readAllBytes(), "multipart/report"); MimeMultipart multipart = new MimeMultipart(datasource); int count = multipart.getCount(); LOG.debug("count " + count); for (int i = 0; i < count; i++) { BodyPart bodyPart = multipart.getBodyPart(i); if (bodyPart.isMimeType("text/plain")) { LOG.info("text/plain"); LOG.debug(bodyPart.getContent().getClass().getName()); Enumeration<Header> headerEnumeration = bodyPart.getAllHeaders(); while (headerEnumeration.hasMoreElements()) { Header header = headerEnumeration.nextElement(); LOG.debug(header.getName() + ": " + header.getValue()); } LOG.debug("----"); LOG.debug(bodyPart.getContent().toString()); LOG.debug("----"); //processTextData(bodyPart.getContent()); } else if (bodyPart.isMimeType("application/octet-stream")) { LOG.info("application/octet-stream"); LOG.debug(bodyPart.getContent().getClass().getName()); //processBinaryData(bodyPart.getInputStream()); } else if (bodyPart.isMimeType("message/disposition-notification")) { // MDN! LOG.info("message/disposition-notification"); Enumeration<Header> headerEnumeration = bodyPart.getAllHeaders(); while (headerEnumeration.hasMoreElements()) { Header header = headerEnumeration.nextElement(); LOG.debug(header.getName() + ": " + header.getValue()); } if (bodyPart.getContent() instanceof ByteArrayInputStream) { ByteArrayInputStream byteArrayInputStream = (ByteArrayInputStream) bodyPart.getContent(); int n = byteArrayInputStream.available(); byte[] bytes = new byte[n]; byteArrayInputStream.read(bytes, 0, n); String s = new String(bytes, StandardCharsets.UTF_8); LOG.debug("----"); LOG.debug(new String(bytes)); LOG.debug("----"); } } else { LOG.debug(bodyPart.getContent().getClass().getName()); LOG.warn("default " + bodyPart.getContentType()); } } } catch (IOException | MessagingException e) { e.printStackTrace(); } } } } |
package ru.outofrange.util; import java.io.IOException; import java.net.Socket; public class CustomSocketUtils { // checks if remote host:port is reachable public static boolean isReachable(String host, int port) { try (Socket ss = new Socket(host, port)) { return true; } catch (IOException e) { } finally { } return false; } } |