オープンソースを使う事
オープンソースを使うからバグを治せると言っても実際に治した後の対処が大変。
しかし、この記事のように横から置き換える事ができると気軽に治せる。
治した後はコミュニティにスタックトレースでも送ってくださいね。
今回の例の場合では翌日には修正されていました。
デフォルト値とバグ
全く違うような話だがそうでもない。
どちらもデフォルトの動作を書き換えようという話だから。
そして、どちらも業務的な実装を書き換える事はしなくて済む話をする。
不具合の例
サンプルコード
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で修正される
回避方法
不具合を起こす設定を書き換えてあげる
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を付けたクラスならどこに書いても良い
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に書き換える
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のコンポーネントを切り替える
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;
}
}