我有一个通过 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 中,我认为将实例根属性上定义的 cacerts 复制到嵌入式容器启动时创建的临时目录可能是一个问题。
我该如何领导呢?