Automatische Proxywahl für Mule ESB Webservices

1 Kommentar

Wenn man Services in Mule konfiguriert wird man einige benutzen, welche externe Services aufrufen. Allerdings hängt es von der Umgebung ab, ob und für welche Hosts ein Proxy Server verwendet werden muss. Um die Rekonfiguration von Mule je Umgebung zu vermeiden benutzen wir einen automatischen Proxy Connector. Da ich den ganz nett finde möchte ich Ihn Euch gerne näher bringen. Vielleicht ist er auch für Euch nutzbar

<https:connector name="autoProxy">
  <spring:property name="proxyHostname">
    <spring:bean class="org.springframework.jndi.JndiObjectFactoryBean">
      <spring:property name="jndiName" value="/jndi/config/proxyHost" />
      <spring:property name="defaultObject" value="" />
    </spring:bean>
  </spring:property>
  <spring:property name="proxyPort">
    <spring:bean class="org.springframework.jndi.JndiObjectFactoryBean">
      <spring:property name="jndiName" value="/jndi/config/proxyPort" />
      <spring:property name="defaultObject" value="0" />
    </spring:bean>
  </spring:property>
  <service-overrides dispatcherFactory="de.codecentric.mule.HttpAutoProxyMessageDispatcherFactory" />
  <https:tls-key-store path="/mule.keystore" keyPassword="changeit" storePassword="changeit"/>
  <https:tls-server path="/mule.keystore" storePassword="changeit"/>
</https:connector>

Wie man leicht sieht verwenden wir eine eigene MessageDispatcherFactory, welche die Parameter ProxyHost und ProxyPort aus JNDI ausliest und einen SSL Keystore mit dem berühmten changeit Passwort übergibt.
Diesen Connector verwendet man dann einfach über connector-ref

  <outbound-endpoint address="https://external.service/endpoint" synchronous="true" connector-ref="autoProxy">

Die Factory selbst ist supereinfach:

public class HttpAutoProxyMessageDispatcherFactory
  extends AbstractMessageDispatcherFactory {
  public MessageDispatcher create(OutboundEndpoint endpoint) throws MuleException {
    return new HttpAutoProxyMessageDispatcher(endpoint);
  }
}

Die Implementierung des HttpAutoProxyMessageDispatcher ist auch einfach, enthält hier aber zwei hardcodierte Hosts welche nicht geproxied werden sollen. Hier kann man gerne noch Verbesserungen einfließen lassen.

public class HttpAutoProxyMessageDispatcher
  extends HttpClientMessageDispatcher {
 
  private final boolean hasProxy;
  private final String proxyHost;
  private final int proxyPort;
 
  public HttpAutoProxyMessageDispatcher(OutboundEndpoint endpoint) {
    super(endpoint);
    this.proxyHost = ((HttpConnector) endpoint.getConnector()).getProxyHostname();
    this.proxyPort = ((HttpConnector) endpoint.getConnector()).getProxyPort();
    this.hasProxy = StringUtils.isNotBlank(proxyHost);
  }
 
  @Override
  protected HostConfiguration getHostConfig(URI uri) throws URISyntaxException {
    String host = uri.getHost();
    HostConfiguration config = new HostConfiguration();
    config.setHost(host, uri.getPort(), Protocol.getProtocol(uri.getScheme().toLowerCase()));
    if (hasProxy && !isLocalhost(host)) {
      config.setProxy(proxyHost, proxyPort);
    }
    return config;
  }
 
  private boolean isLocalhost(String host) {
    return "localhost".equals(host) || "127.0.0.1".equals(host);
  }
 
}

Setzt man die Konfiguration so um, muss lediglich im JNDI jeder Umgebung der Proxy eingestellt sein. Mule wird dann automatisch den Proxy verwenden falls gesetzt und die Konfiguration selbst kann unangetastet bleiben.

Update: Mule 3.2

Kürzlich erschienene Versionen von Mule erleichtern das Implementieren des HttpAutoProxyMessageDispatchers:

public class HttpAutoProxyMessageDispatcher extends
    HttpClientMessageDispatcher implements MessageDispatcher {
 
  public HttpAutoProxyMessageDispatcher(OutboundEndpoint endpoint) {
    super(endpoint);
  }
 
  @Override
  protected HostConfiguration getHostConfig(URI uri) throws Exception {
    Protocol protocol = Protocol.getProtocol(uri.getScheme().toLowerCase());
    String host = uri.getHost();
    int port = uri.getPort();
    HostConfiguration config = new HostConfiguration();
    config.setHost(host, port, protocol);
    if (!isLocalhost(host) && StringUtils.isNotBlank(connector.getProxyHostname())) {
      config.setProxy(connector.getProxyHostname(), connector.getProxyPort());
    }
    return config;
  }
 
  private boolean isLocalhost(String host) {
    return "localhost".equals(host) || "127.0.0.1".equals(host); 
  }
}

Fabian Lange ist Lead Agent Engineer bei Instana und bei der codecentric als Performance Geek bekannt. Er baut leidenschaftlich gerne schnelle Software und hilft anderen dabei, das Gleiche zu tun.
Er kennt die Java Virtual Machine bis in die letzte Ecke und beherrscht verschiedenste Tools, die JVM, den JIT oder den GC zu verstehen.
Er ist beliebter Vortragender auf zahlreichen Konferenzen und wurde unter anderem mit dem JavaOne Rockstar Award ausgezeichnet.

Share on FacebookGoogle+Share on LinkedInTweet about this on TwitterShare on RedditDigg thisShare on StumbleUpon

Kommentare

Kommentieren

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.