LoginSignup
5
6

More than 5 years have passed since last update.

Spring(Java)からCORBAサービスを呼び出してみる

Last updated at Posted at 2017-08-11

Springを使っているアプリからCORBAサービスを呼び出す必要にせまられそうなので、どうすればいいのかな〜と思ってちょっと試してみました。

検証バージョン

  • Java SE 8 (JDK 1.8.0_121)
  • Spring Boot 1.5.6.RELEASE (Spring Framework 4.3.10.RELEASE)

JavaでCORBAサービスを作ってみる

まずIDLファイルを作ります。

Greeting.idl
module com {
  module example {
    module democorba {
      interface Greeting
      {
        string hello(in string message);
      };
    };
  };
};

つぎに、JDKから提供されているidljコンパイラを使ってJavaコードを生成します。

$ idlj -fall -td src/main/java src/main/resources/Greeting.idl
$ tree src/main/java
src/main/java
└── com
    └── example
        └── democorba
            ├── Greeting.java
            ├── GreetingHelper.java
            ├── GreetingHolder.java
            ├── GreetingOperations.java
            ├── GreetingPOA.java
            └── _GreetingStub.java

最後に、サービスの実装を行います。

package com.example.democorba.server;

import com.example.democorba.GreetingPOA;

public class GreetingImpl extends GreetingPOA {

  public String hello(String message) {
    return "Hello !! (" + message + ")";
  }

}

JavaでCORBAサービスを公開してみる

JDK(JRE)から提供されているorbdコマンドを利用して、作成したCORBAサービスを公開するためのクラスを作ります。

package com.example.democorba.server;

import com.example.democorba.Greeting;
import com.example.democorba.GreetingHelper;
import org.omg.CORBA.ORB;
import org.omg.CORBA.ORBPackage.InvalidName;
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;
import org.omg.CosNaming.NamingContextPackage.CannotProceed;
import org.omg.CosNaming.NamingContextPackage.NotFound;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAHelper;
import org.omg.PortableServer.POAManagerPackage.AdapterInactive;
import org.omg.PortableServer.POAPackage.ServantNotActive;
import org.omg.PortableServer.POAPackage.WrongPolicy;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class GreetingServer {

  public static final String[] ORB_OPTIONS = new String[]{"-ORBInitialPort", "1050", "-ORBInitialHost", "localhost"};

  public static void main(String args[]) throws IOException, InterruptedException {

    List<String> orbdStartupCommands = new ArrayList<>();
    orbdStartupCommands.add("orbd");
    orbdStartupCommands.addAll(Arrays.asList(ORB_OPTIONS));

    Process orbdProcess = new ProcessBuilder(orbdStartupCommands).start();
    Runtime.getRuntime().addShutdownHook(new Thread(() -> {
      System.out.println("GreetingService Exiting ...");
      orbdProcess.destroy();
    }));

    TimeUnit.SECONDS.sleep(1);

    try {
      bindService(ORB_OPTIONS);
    } catch (Exception e) {
      System.err.println("ERROR: " + e);
      e.printStackTrace(System.out);
    }

  }

  private static void bindService(String[] options) throws InvalidName, AdapterInactive, ServantNotActive, WrongPolicy, org.omg.CosNaming.NamingContextPackage.InvalidName, NotFound, CannotProceed {
    ORB orb = ORB.init(options, null);

    POA poa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
    poa.the_POAManager().activate();

    GreetingImpl greeting = new GreetingImpl();

    org.omg.CORBA.Object ref = poa.servant_to_reference(greeting);
    Greeting href = GreetingHelper.narrow(ref);

    org.omg.CORBA.Object objRef =
      orb.resolve_initial_references("NameService");
    NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);

    NameComponent path[] = ncRef.to_name("Greeting");
    ncRef.rebind(path, href);

    System.out.println("GreetingService ready started and waiting request ...");

    orb.run();
  }

}

作成したクラスを実行すると・・・

コンソール
GreetingService ready started and waiting request ...

となります。

停止は、IDEが提供している停止機能や「Ctrl+C」を使ってください。停止すると・・・

コンソール
...
GreetingService Exiting ...

となります。

JavaからCORBAサービスを呼び出してみる

CORBAサービスを呼び出すJUnitを作ってみます。

package com.example.democorba;

import org.hamcrest.core.Is;
import org.junit.Assert;
import org.junit.Test;
import org.omg.CORBA.ORB;
import org.omg.CORBA.ORBPackage.InvalidName;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;
import org.omg.CosNaming.NamingContextPackage.CannotProceed;
import org.omg.CosNaming.NamingContextPackage.NotFound;

public class GreetingTest {

  private static final String[] ORB_OPTIONS = new String[]{"-ORBInitialPort", "1050", "-ORBInitialHost", "localhost"};

  @Test
  public void test() throws InvalidName, CannotProceed, org.omg.CosNaming.NamingContextPackage.InvalidName, NotFound {
    ORB orb = ORB.init(ORB_OPTIONS, null);

    org.omg.CORBA.Object objRef =
      orb.resolve_initial_references("NameService");
    NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);

    Greeting greeting = GreetingHelper.narrow(ncRef.resolve_str("Greeting"));

    System.out.println("Obtained a handle on server object: " + greeting);

    String returnMessage = greeting.hello("I'm Kazuki!");

    Assert.assertThat(returnMessage, Is.is("Hello !! (I'm Kazuki!)"));

  }

}

Note:

クライアントで必要になるクラス・インタフェースは・・・

  • Greeting
  • GreetingOperations
  • _GreetingStub
  • GreetingHelper

の4つです。

Springの機能を使ってCORBAサービスを呼び出してみる

Spring Frameworkから提供されているJndiRmiProxyFactoryBeanを使うと、CORBAサービスのインターフェースを実装したBeanをDIコンテナ登録することができます。(=アプリケーションコードの中でCORBAを意識する必要はありません!!)

package com.example.democorba;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.remoting.rmi.JndiRmiProxyFactoryBean;

import javax.naming.Context;
import java.util.Properties;

@SpringBootApplication
public class DemoCorbaApplication {

  public static void main(String[] args) {
    SpringApplication.run(DemoCorbaApplication.class, args);
  }

  @Bean
  CommandLineRunner demo(Greeting greeting) {
    return args -> System.out.println(greeting.hello("Hi Shimizu."));
  }

  @Bean
  JndiRmiProxyFactoryBean greeting() {
    JndiRmiProxyFactoryBean factoryBean = new JndiRmiProxyFactoryBean();
    Properties properties = new Properties();
    properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.cosnaming.CNCtxFactory");
    properties.setProperty(Context.PROVIDER_URL, "iiop://localhost:1050");
    factoryBean.setJndiEnvironment(properties);
    factoryBean.setJndiName("Greeting");
    factoryBean.setServiceInterface(Greeting.class);
    return factoryBean;
  }

}

このクラスを実行すると・・・

コンソール
...

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.5.6.RELEASE)

2017-08-11 15:33:52.199  INFO 12777 --- [           main] c.e.democorba.DemoCorbaApplicationTests  : Starting DemoCorbaApplicationTests on Kazuki-no-MacBook-Pro.local with PID 12777 (started by shimizukazuki in /usr/local/apps/demo-corba)
2017-08-11 15:33:52.202  INFO 12777 --- [           main] c.e.democorba.DemoCorbaApplicationTests  : No active profile set, falling back to default profiles: default
2017-08-11 15:33:52.241  INFO 12777 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@3eb738bb: startup date [Fri Aug 11 15:33:52 JST 2017]; root of context hierarchy
Hello !! (Hi Shimizu.)
2017-08-11 15:33:52.906  INFO 12777 --- [           main] c.e.democorba.DemoCorbaApplicationTests  : Started DemoCorbaApplicationTests in 1.436 seconds (JVM running for 2.242)
2017-08-11 15:33:52.952  INFO 12777 --- [       Thread-3] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@3eb738bb: startup date [Fri Aug 11 15:33:52 JST 2017]; root of context hierarchy

となります。

Note:

クライアントで必要になるクラス・インタフェースは・・・

  • Greeting
  • GreetingOperations
  • _GreetingStub

の3つです。(=GreetingHelperは不要です)

ちなみに・・・テストを書くなら以下のような感じになります。

package com.example.democorba;

import org.hamcrest.CoreMatchers;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.rule.OutputCapture;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoCorbaApplicationTests {

  @ClassRule
  public static OutputCapture outputCapture = new OutputCapture();

  @Test
  public void contextLoads() {
    outputCapture.expect(CoreMatchers.containsString("Hello !! (Hi Shimizu.)"));
  }

}

まとめ

とりあえずサービス呼び出すだけなら楽勝?っぽいけど、こんなんでいいのかな〜?

参考サイト

5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6