最近在研究EJB3,经常使用GlassFish。按照JavaEE规范,如果在EJB3的远程接口中需要传递自定义的数据类型,只要让定义的类实现java.io.Serializable接口,然后保证类中每一个字段都是实现了java.io.Serializable接口即可进行远程数据传递。比如一个远程接口的定义如下:
[code]
@javax.ejb.Remote
public interface ProductManager {
java.util.List<po.Product> findAll();
//.....
}
[/code]
则po.Product类的定义则应该如下:
[code]
public class Product implements java.io.Serializable{
private int no;
private String name;
private String from;
//...
}
[/code]
原来经常写这样的代码,也没有出过什么问题。但这次偏偏问题就来了。在创建一个EJB项目,完成代码后,部署到GlassFish之后(项目采用的是GlassFish中的目录部署模式),利用远程的Java客户端调用findAll方法时,却总是出现这样的错误:
[code]
"IOP02400001: (DATA_CONVERSION) 字符未映射至协商的传输代码集"
org.omg.CORBA.DATA_CONVERSION: vmcid: OMG minor code: 1 completed: No
at com.sun.corba.ee.impl.logging.OMGSystemException.charNotInCodeset(OMGSystemException.java:2093)
at com.sun.corba.ee.impl.logging.OMGSystemException.charNotInCodeset(OMGSystemException.java:2111)
at com.sun.corba.ee.impl.encoding.CodeSetConversion$JavaCTBConverter.convertCharArray(CodeSetConversion.java:336)
at com.sun.corba.ee.impl.encoding.CodeSetConversion$JavaCTBConverter.convert(CodeSetConversion.java:249)
at com.sun.corba.ee.impl.encoding.CDROutputStream_1_0.writeString(CDROutputStream_1_0.java:504)
at com.sun.corba.ee.impl.encoding.CDROutputStream_1_0.write_string(CDROutputStream_1_0.java:493)
at com.sun.corba.ee.impl.encoding.CDROutputStream_1_0.write_codebase(CDROutputStream_1_0.java:1379)
at com.sun.corba.ee.impl.encoding.CDROutputStream_1_0.writeValueTag(CDROutputStream_1_0.java:1423)
at com.sun.corba.ee.impl.encoding.CDROutputStream_1_0.writeRMIIIOPValueType(CDROutputStream_1_0.java:815)
at com.sun.corba.ee.impl.encoding.CDROutputStream_1_0.write_value(CDROutputStream_1_0.java:935)
at com.sun.corba.ee.impl.encoding.CDROutputStream_1_0.write_value(CDROutputStream_1_0.java:949)
at com.sun.corba.ee.impl.encoding.CDROutputStream_1_0.write_value(CDROutputStream_1_0.java:690)
at com.sun.corba.ee.impl.encoding.CDROutputStream.write_value(CDROutputStream.java:451)
at com.sun.corba.ee.impl.presentation.rmi.DynamicMethodMarshallerImpl$14.write(DynamicMethodMarshallerImpl.java:376)
at com.sun.corba.ee.impl.presentation.rmi.DynamicMethodMarshallerImpl.writeResult(DynamicMethodMarshallerImpl.java:472)
at com.sun.corba.ee.impl.presentation.rmi.ReflectiveTie._invoke(ReflectiveTie.java:158)
at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.dispatchToServant(CorbaServerRequestDispatcherImpl.java:687)
at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.dispatch(CorbaServerRequestDispatcherImpl.java:227)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequestRequest(CorbaMessageMediatorImpl.java:1846)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequest(CorbaMessageMediatorImpl.java:1706)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleInput(CorbaMessageMediatorImpl.java:1088)
at com.sun.corba.ee.impl.protocol.giopmsgheaders.RequestMessage_1_2.callback(RequestMessage_1_2.java:223)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequest(CorbaMessageMediatorImpl.java:806)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.dispatch(CorbaMessageMediatorImpl.java:563)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.doWork(CorbaMessageMediatorImpl.java:2567)
at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:555)
Caused by: java.nio.charset.UnmappableCharacterException: Input length = 1
at java.nio.charset.CoderResult.throwException(CoderResult.java:261)
at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:771)
at com.sun.corba.ee.impl.encoding.CodeSetConversion$JavaCTBConverter.convertCharArray(CodeSetConversion.java:321)
... 23 more
[/code]
利用调试和跟踪工具,发现就是在findAll方法在回传结果时抛出的异常。开始觉得这个错误有些莫名奇妙,后来发现,我的项目的所在的目录位于Windows的“我的文档”目录中,而我的文档对应的用户名是中文。于是我换了一个纯英文目录存储项目,然后再在GlassFish中部署,就一切OK了!
看来,这是GlassFish的一个Bug:
如果你在远程商业方法中传递的自己定义的类的实例,那么请确保项目部署的目录所在的路径中没有中文的文件夹,否则会产生上述错误。
如果回传的数据是Java中的基础类库中的类型,比如String、int这样的简单数据类型,则不会产生这个错误。
这里也希望各位朋友注意这个问题,其实,这个中文路径的问题不只限于GlassFish,如果你在JavaSE项目中使用基于TopLink的JPA,假如你的程序运行所在的目录是中文,或该目录位于一个包含中文的路径中,也会遇到TopLink报告的不能正常初始化持久单元的错误。所以,在Java开发时,应避免使用包含有中文目录的路径。
[code]
@javax.ejb.Remote
public interface ProductManager {
java.util.List<po.Product> findAll();
//.....
}
[/code]
则po.Product类的定义则应该如下:
[code]
public class Product implements java.io.Serializable{
private int no;
private String name;
private String from;
//...
}
[/code]
原来经常写这样的代码,也没有出过什么问题。但这次偏偏问题就来了。在创建一个EJB项目,完成代码后,部署到GlassFish之后(项目采用的是GlassFish中的目录部署模式),利用远程的Java客户端调用findAll方法时,却总是出现这样的错误:
[code]
"IOP02400001: (DATA_CONVERSION) 字符未映射至协商的传输代码集"
org.omg.CORBA.DATA_CONVERSION: vmcid: OMG minor code: 1 completed: No
at com.sun.corba.ee.impl.logging.OMGSystemException.charNotInCodeset(OMGSystemException.java:2093)
at com.sun.corba.ee.impl.logging.OMGSystemException.charNotInCodeset(OMGSystemException.java:2111)
at com.sun.corba.ee.impl.encoding.CodeSetConversion$JavaCTBConverter.convertCharArray(CodeSetConversion.java:336)
at com.sun.corba.ee.impl.encoding.CodeSetConversion$JavaCTBConverter.convert(CodeSetConversion.java:249)
at com.sun.corba.ee.impl.encoding.CDROutputStream_1_0.writeString(CDROutputStream_1_0.java:504)
at com.sun.corba.ee.impl.encoding.CDROutputStream_1_0.write_string(CDROutputStream_1_0.java:493)
at com.sun.corba.ee.impl.encoding.CDROutputStream_1_0.write_codebase(CDROutputStream_1_0.java:1379)
at com.sun.corba.ee.impl.encoding.CDROutputStream_1_0.writeValueTag(CDROutputStream_1_0.java:1423)
at com.sun.corba.ee.impl.encoding.CDROutputStream_1_0.writeRMIIIOPValueType(CDROutputStream_1_0.java:815)
at com.sun.corba.ee.impl.encoding.CDROutputStream_1_0.write_value(CDROutputStream_1_0.java:935)
at com.sun.corba.ee.impl.encoding.CDROutputStream_1_0.write_value(CDROutputStream_1_0.java:949)
at com.sun.corba.ee.impl.encoding.CDROutputStream_1_0.write_value(CDROutputStream_1_0.java:690)
at com.sun.corba.ee.impl.encoding.CDROutputStream.write_value(CDROutputStream.java:451)
at com.sun.corba.ee.impl.presentation.rmi.DynamicMethodMarshallerImpl$14.write(DynamicMethodMarshallerImpl.java:376)
at com.sun.corba.ee.impl.presentation.rmi.DynamicMethodMarshallerImpl.writeResult(DynamicMethodMarshallerImpl.java:472)
at com.sun.corba.ee.impl.presentation.rmi.ReflectiveTie._invoke(ReflectiveTie.java:158)
at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.dispatchToServant(CorbaServerRequestDispatcherImpl.java:687)
at com.sun.corba.ee.impl.protocol.CorbaServerRequestDispatcherImpl.dispatch(CorbaServerRequestDispatcherImpl.java:227)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequestRequest(CorbaMessageMediatorImpl.java:1846)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequest(CorbaMessageMediatorImpl.java:1706)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleInput(CorbaMessageMediatorImpl.java:1088)
at com.sun.corba.ee.impl.protocol.giopmsgheaders.RequestMessage_1_2.callback(RequestMessage_1_2.java:223)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.handleRequest(CorbaMessageMediatorImpl.java:806)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.dispatch(CorbaMessageMediatorImpl.java:563)
at com.sun.corba.ee.impl.protocol.CorbaMessageMediatorImpl.doWork(CorbaMessageMediatorImpl.java:2567)
at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:555)
Caused by: java.nio.charset.UnmappableCharacterException: Input length = 1
at java.nio.charset.CoderResult.throwException(CoderResult.java:261)
at java.nio.charset.CharsetEncoder.encode(CharsetEncoder.java:771)
at com.sun.corba.ee.impl.encoding.CodeSetConversion$JavaCTBConverter.convertCharArray(CodeSetConversion.java:321)
... 23 more
[/code]
利用调试和跟踪工具,发现就是在findAll方法在回传结果时抛出的异常。开始觉得这个错误有些莫名奇妙,后来发现,我的项目的所在的目录位于Windows的“我的文档”目录中,而我的文档对应的用户名是中文。于是我换了一个纯英文目录存储项目,然后再在GlassFish中部署,就一切OK了!
看来,这是GlassFish的一个Bug:
如果你在远程商业方法中传递的自己定义的类的实例,那么请确保项目部署的目录所在的路径中没有中文的文件夹,否则会产生上述错误。
如果回传的数据是Java中的基础类库中的类型,比如String、int这样的简单数据类型,则不会产生这个错误。
这里也希望各位朋友注意这个问题,其实,这个中文路径的问题不只限于GlassFish,如果你在JavaSE项目中使用基于TopLink的JPA,假如你的程序运行所在的目录是中文,或该目录位于一个包含中文的路径中,也会遇到TopLink报告的不能正常初始化持久单元的错误。所以,在Java开发时,应避免使用包含有中文目录的路径。