この記事は GMOインターネットグループ Advent Calendar 2024 12日目の記事です。
GMOペイメントゲートウェイの羽鳥です。主にクレジットカード決済システムや、カード会社様向けシステムの開発にプログラマーとして携わっています。
今回お話しするのは、今携わっているプロジェクトで、システム間連携のロジックをApache Camelを使用して一か所に集約したときのお話です。
目次
プロジェクトについて
現在携わっているプロジェクトは、クレジットカードの発行を行うお客様向けのシステムです。システムの内部は、
- 入会審査を行うシステム
 - 売上情報を処理するシステム
 - 債権を扱うシステム
 
に分かれています。これらのシステムは互いにファイルでデータをやり取りします。
課題について
全てのシステムが同じファイル送受信の方式を採用していれば簡単なのですが、実際はそれぞれHULFT、SFTPといった具合にそれぞれ異なっていました。

このため、以下の課題がありました。
- 各システムの中にファイル送受信をするサーバは複数存在するため、相手方のサーバの接続するためのロジックの重複が発生
 
- 接続方式が変更になると、全てのサーバに変更が必要
 
これでは非効率なため、代理でファイル送受信を行うサーバを構築する必要がありました。ここで、代理でファイル送受信を行うアプリケーションを構築するのに最適だったのがApache Camelです。
Apache Camelとは
Apache Camelは、統合パターン (Enterprise Integration Patterns: EIP) を実装するためのオープンソースフレームワークです。分散システム間のデータ連携やプロトコル変換を効率的に行うためのツールであり、多数のコンポーネントを使用して、ファイル、メッセージング、HTTPなど、さまざまなシステム間での通信を簡単に構築できます。
Camelの主要な特徴は次の通りです。
- EIPに基づく柔軟なルーティングと処理:シンプルなDSL(Domain Specific Language)を使用し、データ処理の流れをルートとして記述可能。
 - 豊富なコンポーネント:FTP、SFTP、JMS、HTTPなどのプロトコル、さらにAWS、Azureといった外部サービスの連携用コンポーネントを提供。
 - Producer、Consumer、Processorの概念:データの送信、受信、加工をシンプルにモデル化。
 
サンプルコード
from("sftp://[email protected]:22/source?password=sourceSecret") // Consumer: SFTPからデータを取得
                    .process(exchange -> { // Processor: データ内容を加工
                        String body = exchange.getIn().getBody(String.class);
                        body = body.replace("oldValue", "newValue"); // 例: 文字列を置換
                        exchange.getMessage().setBody(body);
                    })
                    .to("sftp://[email protected]:22/target?password=targetSecret"); // Producer: SFTPにデータを送信上記はDSLを使用したApache Camelのルート定義の例です。分解して説明します。
Consumer:ファイルを取得
from("sftp://[email protected]:22/source?password=sourceSecret")Consumerはデータの入力元を定義します。RouteBuilder.fromメソッドの引数にコンポーネント(sftp)とそのパラメータを指定することで、ファイルの取得方法を定義できます。
Processor:ファイルの内容を加工
.process(exchange -> { // Processor: データ内容を加工
                        String body = exchange.getIn().getBody(String.class);
                        body = body.replace("oldValue", "newValue"); // 例: 文字列を置換
                        exchange.getMessage().setBody(body);
                    })ProcessorはConsumerが取得したデータを加工します。データの内容や、取得したファイル名といった情報を格納するのがExchangeクラスですが、このクラスを引数に受け取るラムダ式として定義します。処理した結果は、再びExchangeに設定することで、続く処理で受け取ることが可能となります。
Producer:ファイルを送信
.to("sftp://[email protected]:22/target?password=targetSecret");Producerはファイルの出力先を定義します。ProcessorDefinition.toメソッドの引数にコンポーネント(sftp)とそのパラメータを指定することで定義します。
なお、Consumer、Producerはコンポーネントを変更することで、容易にプロトコルの変更が可能です。こうした柔軟性もCamelの大きな特徴と言えます。
適用例
あるシステム内のサーバが、他のシステムにファイルを送信するときは、同一の方式で受け取り、送信先に応じてそれぞれの方式に応じて送信できるようにしました。ポイントは以下となります。
- HTTPリクエストで送信要求を受ける
 - 代理サーバから送信するファイルを取得する
 - 送信先に応じて方式を変えて送信
 

これにより、
- サーバ接続ロジックの集約を実現
 - 接続方式の変更があっても、一か所の修正で完結
 
とすることができました。さらに、
- 代理サーバからファイルを取得することで、ログインするための認証情報を代理サーバ側で一元管理
 - HTTPリクエストで送信要求を受け取ることで、送信側はシンプルなHTTPリクエストの送信処理だけで実装が完結
 
とすることで、サーバ間を疎結合にできました。
以下は送信要求を受信する箇所のコードです。
        from("jetty:http://0.0.0.0:8080/transfer/{routeType}") // Jettyのリスナーアドレスを指定
                .process(
                        exchange -> {
                            String path =
                                    exchange.getIn().getHeader(Exchange.HTTP_PATH, String.class);
                            String[] paths = path.split("/");
                            // CamelHttpPathは"/transfer/hulft"のようになるため、splitすると{"","transfer",hulft"}になる
                            exchange.getIn().setHeader(HeaderKeys.TRANS_ROUTE, paths[1]);
                            exchange.getIn().setHeader(HeaderKeys.ROUTE_TYPE, paths[2]);
                        })
                .toD(
                        "direct:${header."
                                + HeaderKeys.TRANS_ROUTE
                                + "}-${header."
                                + HeaderKeys.ROUTE_TYPE
                                + "}")
                .end();また、リクエストパラメータとして送信先の情報を受け取り、それぞれのファイル送信用ルートに転送するように定義しました。これにより、ファイル受信用ルート1つに対して複数の送信用ルートを定義でき、コードの重複を避けることを実現しました。
以下は送信処理のコードです。directコンポーネントを使用することで、指定したIDのルートに転送することが出来ます。
        from("direct:transfer-" + this.routeId)
                .process(
                        exchange -> {
                            // SFTPでアクセスするユーザをプロパティから取得
                            String srcHost =
                                    exchange.getIn().getHeader(HeaderKeys.SRC_HOST, String.class);
                            String accessUserKey =
                                    String.format(PropertyKeys.SSH_ACCESS_USER_KEY_FORMAT, srcHost);
                            exchange.getIn()
                                    .setHeader(
                                            HeaderKeys.ACCESS_USER,
                                            exchange.getContext()
                                                    .resolvePropertyPlaceholders(accessUserKey));
                            exchange.getIn().setHeader(HeaderKeys.SEND_DIR, this.sendDir);
                        })
                .process(new SftpRetrieveProcessor()) //ファイルを取得するためのSFTPコマンドを設定
                .to("exec:command?useStderrOnEmptyStdout=true&exitValues=0") //ExecモジュールでSFTP実行
                .to("direct:" + this.sendRouteName) //送信用ルートへ転送
                .end();まとめ
システム間連携を代理するサーバは、ファイル送受信、HTTPリクエストの送受信等の似たような処理の、微妙な違いを吸収するために構築します。このため処理が重複しがちなのですが、Apache Camelを使うことで重複を省きつつ、異なる箇所だけ実装をすることができました。また、ルートの追加にもアドホックに対応できるため、今後の拡張性にも期待できます。
私たちが扱うシステムは様々なシステムと連携することが多いので、今後は必ずApache Camelを導入するように啓蒙していきたいなと思いました。
ブログの著者欄
採用情報
関連記事
KEYWORD
CATEGORY
- 
                  技術情報(516)
 - 
                  イベント(193)
 - 
                  カルチャー(50)
 - 
                  デザイン(47)
 
TAG
- "eVTOL"
 - "Japan Drone"
 - "ロボティクス"
 - "空飛ぶクルマ"
 - 5G
 - Adam byGMO
 - AGI
 - AI
 - AI人財
 - APT攻撃
 - AWX
 - BIT VALLEY
 - Blade
 - blockchain
 - Canva
 - ChatGPT
 - ChatGPT Team
 - Claude Team
 - cloudflare
 - cloudnative
 - CloudStack
 - CM
 - CNDO
 - CNDT
 - CODEGYM Academy
 - ConoHa
 - ConoHa、Dify
 - CS
 - CSS
 - CTF
 - DC
 - design
 - Designship
 - Desiner
 - DeveloperExper
 - DeveloperExpert
 - DevRel
 - DevSecOpsThon
 - DiceCTF
 - Dify
 - DNS
 - Docker
 - DTF
 - Expert
 - Felo
 - GitLab
 - GMO AIR
 - GMO AIロボティクス大会議&表彰式
 - GMO DESIGN AWARD
 - GMO Developers Day
 - GMO Developers Night
 - GMO Developers ブログ
 - GMO Flatt Security
 - GMO GPUクラウド
 - GMO Hacking Night
 - GMO kitaQ
 - GMO SONIC
 - GMOアドパートナーズ
 - GMOアドマーケティング
 - GMOイエラエ
 - GMOインターネット
 - GMOインターネットグループ
 - GMOクラウド]
 - GMOグローバルサイン
 - GMOサイバーセキュリティbyイエラエ
 - GMOサイバーセキュリティ大会議
 - GMOサイバーセキュリティ大会議&表彰式
 - GMOソリューションパートナー
 - GMOデジキッズ
 - GMOブランドセキュリティ
 - GMOペイメントゲートウェイ
 - GMOペパボ
 - GMOメディア
 - GMOリサーチ
 - GMO大会議
 - Go
 - GPU
 - GPUクラウド
 - GTB
 - Hardning
 - Harvester
 - HCI
 - iOS
 - IoT
 - ISUCON
 - JapanDrone
 - Java
 - JJUG
 - K8s
 - Kaigi on Rails
 - Kids VALLEY
 - KidsVALLEY
 - LLM
 - MCP
 - MetaMask
 - MySQL
 - NFT
 - NVIDIA
 - NW構成図
 - NW設定
 - Ollama
 - OpenStack
 - Perl
 - perplexity
 - PHP
 - PHPcon
 - PHPerKaigi
 - PHPカンファレンス
 - QUIC
 - Rancher
 - RPA
 - Ruby
 - Selenium
 - Slack
 - Slack活用
 - Spectrum Tokyo Meetup
 - splunk
 - SRE
 - SSL
 - Terraform
 - TLS
 - TypeScript
 - UI/UX
 - vibe
 - VLAN
 - VS Code
 - Webアプリケーション
 - WEBディレクター
 - XSS
 - アドベントカレンダー
 - イベントレポート
 - インターンシップ
 - インハウス
 - オブジェクト指向
 - オンボーディング
 - お名前.com
 - カルチャー
 - クリエイター
 - クリエイティブ
 - コーディング
 - コンテナ
 - サイバーセキュリティ
 - システム研修
 - スクラム
 - スペシャリスト
 - セキュリティ
 - ソフトウェアテスト
 - チームビルディング
 - デザイン
 - ドローン
 - ネットのセキュリティもGMO
 - ネットワーク
 - ビジネス職
 - ヒューマノイド
 - ヒューマノイドロボット
 - プログラミング教育
 - ブロックチェーン
 - ベイズ統計学
 - マルチプレイ
 - ミドルウェア
 - モバイル
 - ゆめみらいワーク
 - リモートワーク
 - レンタルサーバー
 - ロボット
 - 京大ミートアップ
 - 人材派遣
 - 出展レポート
 - 動画
 - 協賛レポート
 - 基礎
 - 多拠点開発
 - 大学授業
 - 宮崎オフィス
 - 展示会
 - 応用
 - 技育プロジェクト
 - 技術広報
 - 採用
 - 採用サイトリニューアル
 - 採用活動
 - 新卒
 - 新卒研修
 - 日本科学未来館
 - 映像
 - 映像クリエイター
 - 暗号
 - 業務効率化
 - 業務時間削減
 - 機械学習
 - 決済
 - 物理暗号
 - 生成AI
 - 視覚暗号
 - 開発生産性
 - 開発生産性向上
 - 階層ベイズ
 - 高機能暗号
 
PICKUP
- 
                  
                    
                                        東京・福島・福岡の専門学校3校でConoHa AI Canvasを用いた講義を実施しました
技術情報
 - 
                  
                    
                                        【協賛レポート・前編】Designship 2025|参加者と“共につくる”デザインのかたち──私たちの挑戦を振り返る
デザイン
 - 
                  
                    
                                        NFSのパフォーマンストラブルに対応した話
技術情報
 - 
                  
                    
                                        Microsoft Entra アプリケーション プロキシ × Windows 統合認証環境での NTLM 廃止影響と対策
技術情報
 - 
                  
                    
                                        GMOインターネットグループ合同テクノロジーインターンシップ2025 体験記~ML/Webコース編①~
カルチャー
 - 
                  
                    
                                        ChatGPTとConoHa AI Canvasで検証:生成AIが変えるクリエイティブ制作
技術情報