2 つの異なるサーバー上の EJB を介して互いに通信する 2 つの Java アプリケーションがあります。
EJB は Spring で定義され、ejb 名が Web ロジックの外部 JNDI としてセットアップされます。
<bean id="codingRemote" class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean">
<property name="jndiName" value="ejb/myEjb" />
<property name="businessInterface" value="com.my.ej.binterface" />
<property name="refreshHomeOnConnectFailure" value="true" />
</bean>
refreshHomeOnConnectFailure を true に設定し、リモート サーバーを再起動して再接続できますが、リモート サーバーに再デプロイすると問題が発生します (デプロイ プロセスで Web ロジック ドメインが完全に削除され、再作成され、新しいアーティファクトがデプロイされます)。接続を試みますが、セキュリティ上の問題があります。
リモート マシンでは、「再展開」プロセスの後に次の例外が発生し、クライアントから呼び出しが行われます。そのため、クライアントは呼び出しを試みていますが、リモート マシン/JVM は呼び出しを受け付けていません。
<Aug 28, 2014 11:20:23 AM CAT> <Warning> <RMI> <WL-080003> <A RuntimeException was generated by the RMI server: weblogic.jndi.internal.AdminRoleBasedDispatchServerRef@9, implementation: 'weblogic.jndi.internal.RootNamingNode@ac24b13', oid: '9', implementationClassName: 'weblogic.jndi.internal.RootNamingNode'
java.lang.SecurityException: [Security:090398]Invalid Subject: principals=[weblogic, Administrators].
java.lang.SecurityException: [Security:090398]Invalid Subject: principals=[weblogic, Administrators]
at weblogic.security.service.SecurityServiceManager.seal(SecurityServiceManager.java:833)
at weblogic.security.service.SecurityServiceManager.getSealedSubjectFromWire(SecurityServiceManager.java:522)
at weblogic.rjvm.MsgAbbrevInputStream.getSubject(MsgAbbrevInputStream.java:355)
at weblogic.rmi.internal.BasicServerRef.acceptRequest(BasicServerRef.java:1022)
at weblogic.rmi.internal.BasicServerRef.dispatch(BasicServerRef.java:350)
Truncated. see log file for complete stacktrace
環境 Java7 / Weblogic12 / Spring2.5
これを渡して、ログインまたはユーザー資格情報のログインを再度実行できるようにする方法はありますか?
----------
2つの可能な解決策を見つけましたが、どちらを使用するのが最適か、また使用する際に問題があるかどうかは完全にはわかりません.
解決策 1: - JNDI テンプレートを指定しますが、それを行うと weblogic 内で定義する目的が無効になり、アプリケーション自体の一部になります。
<bean id="codingRemote" class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean">
<property name="jndiName" value="ejb/myEjb" />
<property name="businessInterface" value="com.my.ej.binterface" />
<property name="refreshHomeOnConnectFailure" value="true" />
<property name="jndiTemplate">
<ref local="myProcessJndiTemplate" />
</property>
</bean>
<bean id="myProcessJndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">${specify.the.context}</prop>
<prop key="java.naming.provider.url">${specify.the.url}</prop>
<prop key="java.naming.security.authentication">none</prop>
</props>
</property>
</bean>
Solution2: - このサイトで、SimpleRemoteStatelessSessionProxyFactoryBean をオーバーライドすると、セキュリティを再度インスタンス化できることがわかりました。
public class WebLogicSimpleRemoteStatelessSessionProxyFactoryBean extends SimpleRemoteStatelessSessionProxyFactoryBean {
@Override protected Object create() throws NamingException, InvocationTargetException {
try {
return getJndiTemplate().execute(new JndiCallback() {
public Object doInContext(final Context context) throws NamingException {
try {
return WebLogicSimpleRemoteStatelessSessionProxyFactoryBean.super.create();
} catch (final InvocationTargetException ite) {
throw new RuntimeException(ite);
}
}
});
} catch (final RuntimeException re) {
throw (InvocationTargetException) re.getCause();
}
}
protected void removeSessionBeanInstance(final EJBObject ejbObject) {
try {
getJndiTemplate().execute(new JndiCallback() {
public Object doInContext(final Context context) throws NamingException {
WebLogicSimpleRemoteStatelessSessionProxyFactoryBean.super.removeSessionBeanInstance(ejbObject);
return null;
}
});
} catch (final NamingException e) {
throw new RuntimeException(e);
}
}
protected Object doInvoke(final MethodInvocation methodInvocation) throws Throwable {
try {
return getJndiTemplate().execute(new JndiCallback() {
public Object doInContext(final Context context) throws NamingException {
try {
return WebLogicSimpleRemoteStatelessSessionProxyFactoryBean.super.doInvoke(methodInvocation);
} catch (final Throwable t) {
if (t instanceof NamingException) {
throw (NamingException) t;
} else {
throw new RuntimeException(t);
}
}
}
});
} catch (final RuntimeException re) {
throw re.getCause();
}
}
}