我有一个通过https与站点通信的EJB。逻辑是在请求中发送xml文件并在响应中接收另一个。在将站点证书添加到GlassFish域内的cacerts之后,这在开发环境中工作正常。当使用EJBContainer在测试环境中进行通信时,会出现问题。即使定义了 org.glassfish.ejb.embedded.glassfish.installation.root 和 org.glassfish.ejb.embedded.glassfish.instance.root 属性并将证书添加到cacerts ,测试执行结束于:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
我的EJB实现如下:
@Stateless
@LocalBean
public class CommunicationService {
public String communicate() {
try {
URL url = new URL("https://www.comprasnet.gov.br/XML/treinamento/consultamatserv.asp");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
writer.flush();
String line;
BufferedReader reader = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
StringBuilder resposta = new StringBuilder();
while ((line = reader.readLine()) != null) {
resposta.append(line);
}
writer.close();
reader.close();
return resposta.toString();
} catch (Exception e) {
return null;
}
}
}
我的测试配置使用TestNG 6.8.5,GlassFish 3.1.2.2和EJBContainer。配置开始在GlassFish中创建另一个域,以避免在运行时与默认域发生端口冲突。为此,我运行命令:
asadmin create-domain --portbase 9100 domain-test
我已经定义了一个带有@BeforeSuite
注释方法的超类,它使用以下内容启动嵌入式容器:
public abstract class GlassfishEmbeddedBaseTest {
protected Context ic;
protected UserTransaction tx;
private static EJBContainer ejbContainer;
@BeforeSuite
protected void beforeSuite() throws Exception {
String glassfishHome = System.getenv("GLASSFISH_HOME");
Properties properties = new Properties();
properties.put(EJBContainer.MODULES, new File[] { new File(
"target/classes") });
properties.put("org.glassfish.ejb.embedded.glassfish.installation.root",
glassfishHome + "/glassfish");
properties.put("org.glassfish.ejb.embedded.glassfish.instance.root",
glassfishHome + "/glassfish/domains/domain-test");
properties.put(EJBContainer.APP_NAME, "app-name");
ejbContainer = EJBContainer.createEJBContainer(properties);
}
@BeforeClass
protected void load() throws Exception {
ic = ejbContainer.getContext();
}
@BeforeMethod
protected void beforeMethod() throws Exception {
tx = (UserTransaction) ic.lookup("java:comp/UserTransaction");
tx.begin();
}
@AfterMethod
protected void rollBack() throws Exception {
tx.rollback();
}
}
在测试类中,我查看了我的EJB并调用了通过https与站点通信的逻辑:
public class CommunicationServiceTest extends GlassfishEmbeddedBaseTest {
private CommunicationService communicationService;
@BeforeClass
public void init() throws NamingException {
communicationService = (CommunicationService) ic
.lookup("java:global/app-name/classes/CommunicationService");
}
@Test
public void testCommunicate() {
String response = communicationService.communicate();
Assert.assertNotNull(response);
}
}
我在GlassFish Jira中发现了与此问题相关的错误: https://java.net/jira/browse/GLASSFISH-17179,并且由于EJBContainer基于域测试,并且认证安装在来自此域的cacerts中,我认为这可能是将实例root属性上定义的cacerts复制到嵌入式上创建的临时目录的问题集装箱开始时间。
我怎么能带头呢?
答案 0 :(得分:1)
EJBContainer提供了一个名为org.glassfish.ejb.embedded.glassfish.instance.reuse的属性,用于确定:
如果为true,则不对现有配置文件和临时服务器进行任何更改 不为嵌入式运行创建实例。而是针对现有服务器实例执行。如果正在运行的GlassFish Server正在使用重用的服务器实例,请不要使用此选项。
在创建EJBContainer之前添加值为true的属性,解决了问题,因为证书已经添加到域domain-test中的cacerts中,并且不会再将任何内容复制到临时文件夹。