使用EjbContainer和GlassFish测试时未找到证书

时间:2013-08-19 12:36:21

标签: glassfish certificate java-ee-6

我有一个通过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复制到嵌入式上创建的临时目录的问题集装箱开始时间。

我怎么能带头呢?

1 个答案:

答案 0 :(得分:1)

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

  

如果为true,则不对现有配置文件和临时服务器进行任何更改   不为嵌入式运行创建实例。而是针对现有服务器实例执行。如果正在运行的GlassFish Server正在使用重用的服务器实例,请不要使用此选项。

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