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ファイルを作ります。
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.)"));
}
}
まとめ
とりあえずサービス呼び出すだけなら楽勝?っぽいけど、こんなんでいいのかな〜?