1

我有一个通过 https 与站点通信的 EJB。逻辑是在请求中发送一个 xml 文件并在响应中接收另一个。将站点证书添加到 GlassFish 域内的 cacerts 后,这在开发环境中运行良好。在使用 EJBContainer 的测试环境中进行通信时会出现此问题。即使定义了org.glassfish.ejb.embedded.glassfish.installation.rootorg.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 复制到嵌入式容器启动时创建的临时目录可能是一个问题。

我该如何领导呢?

4

1 回答 1

1

EJBContainer 提供了一个名为 org.glassfish.ejb.embedded.glassfish.instance.reuse 的属性,它确定:

如果为 true,则不会对现有配置文件进行任何更改,并且不会为嵌入式运行创建临时服务器实例。相反,执行发生在现有的服务器实例上。如果正在运行的 GlassFish Server 可能正在使用重用的服务器实例,请不要使用此选项。

在创建 EJBContainer 之前添加值为 true 的此属性解决了该问题,因为证书已添加到域 domain-test 中的 cacerts 中,并且不再将任何内容复制到临时文件夹中。

于 2013-09-04T20:45:41.657 回答