簡単にコンポーネントのデフォルト値を書き換える・バグを避ける（Apache Camel）


# オープンソースを使う事

オープンソースを使うからバグを治せると言っても実際に治した後の対処が大変。
しかし、この記事のように横から置き換える事ができると気軽に治せる。

治した後はコミュニティにスタックトレースでも送ってくださいね。
今回の例の場合では翌日には修正されていました。


# デフォルト値とバグ

全く違うような話だがそうでもない。
どちらもデフォルトの動作を書き換えようという話だから。
そして、どちらも業務的な実装を書き換える事はしなくて済む話をする。

# 不具合の例

サンプルコード

```java
from("direct:in")
        .to("netty4-http:http://camel.apache.org")
        .to("log:test");
```

発生する例外
java.lang.IllegalArgumentException: port out of range:-1

Camel2.17.0で発生し、2.17.1で修正される

# 回避方法

## 不具合を起こす設定を書き換えてあげる

```java:MyNettyHttpComponent.java
package hello.camel;

import org.apache.camel.Endpoint;
import org.apache.camel.component.netty4.NettyConfiguration;
import org.apache.camel.component.netty4.http.NettyHttpComponent;
import org.apache.camel.component.netty4.http.NettyHttpEndpoint;

import java.util.Map;

public class MyNettyHttpComponent extends NettyHttpComponent {

    // .to("netty4-http:xxxxx")が呼び出される度に、ここで初期化される
    @Override
    protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
        Endpoint endpoint = super.createEndpoint(uri, remaining, parameters);
        NettyHttpEndpoint nettyHttpEndpoint = (NettyHttpEndpoint) endpoint;
        // configurationのポート番号が-1に設定されるバグなので、書き換え
        NettyConfiguration configuration = nettyHttpEndpoint.getConfiguration();
        if (configuration.getPort() == -1) {
            if (remaining.startsWith("http:")) {
                configuration.setPort(80);
            } else if (remaining.startsWith("https:")) {
                configuration.setPort(443);
            }
        }
        return nettyHttpEndpoint;
    }
}
```

## netty4-httpのコンポーネントを自作したコンポーネントに切り替える

@Componentを付けたクラスならどこに書いても良い

```java:MyConfig.java
package hello.camel;

import org.apache.camel.component.netty4.http.NettyHttpComponent;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class MyConfig {
    // to("netty4-http:xxxxx")は自作のコンポーネントに書き換える
    @Bean(name = "netty4-http")
    public NettyHttpComponent netty4http() {
        NettyHttpComponent component = new MyNettyHttpComponent();
        return component;
    }
}
```

これだけでバグ修復完成！
動かないけどどうしても使いたいコンポーネントがあれば、これで修復できる場合がある。
ランタイム部分の実装を修正するには別の機会にでも・・・

# Timerコンポーネントのデフォルト値の書き換え

## デフォルト値を設定してあげる

やり方は同じ
今回はTimerコンポーネントのperiodデフォルト値を5sに書き換える

```java:MyTimerComponent.java
package hello.camel;

import org.apache.camel.Endpoint;
import org.apache.camel.component.timer.TimerComponent;

import java.util.Map;

public class MyTimerComponent extends TimerComponent {
    @Override
    protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
        // periodが設定されていない場合、ここで設定してあげる
        if (!parameters.containsKey("period"))
            parameters.put("period", "5s");
        return super.createEndpoint(uri, remaining, parameters);
    }
}
```

## Timerのコンポーネントを切り替える

```java:MyConfig2.java
package hello.camel;

import org.apache.camel.component.timer.TimerComponent;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class MyConfig2 {
    @Bean(name = "timer")
    public TimerComponent timerComponent() {
        TimerComponent component = new MyTimerComponent();
        return component;
    }
}
```


# ソースコード

https://github.com/d7kuro/HelloCamelNettyHttp