SpringBoot Tomcat嵌入式全局JNDI资源

时间:2017-09-17 00:01:00

标签: java tomcat spring-boot spring-jms

我知道在tomcat嵌入式中有很多关于JNDI资源的问题,但是我尝试了所有我找不到的解决方案。

我有一个为我的客户公开Rest API的应用程序。在这个应用程序中,我们有一个使用JMS和Amazon SQS的异步解决方案。该应用程序使用第三方库,使用JNDI获取sql.Datasource,因此,我需要使用JNDI数据源。

问题是,当App在Rest Controller的同一个线程中调用这个libs时,JNDI Lookup工作,并且数据源被获取。

当我的@JmsListener调用这个libs时,我得到一个NamingNotFoungException。

我在代码的2个点中使用了context.list(“java”),并确认在JmsListener中没有JNDI Context。

我的tomcat工厂类:     组态 public class CustomTomcatEmbeddedServletContainerFactory {

@Value("${spring.log.datasource.jndiName}")
private String logJndiName;

@Value("${spring.log.datasource.password}")
private String logPassword;

@Value("${spring.log.datasource.url}")
private String logUrl;

@Value("${spring.log.datasource.username}")
private String logUsername;

@Bean
public TomcatEmbeddedServletContainerFactory tomcatFactory() {
    return new TomcatEmbeddedServletContainerFactory() {

        @Override
        protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(Tomcat tomcat) {
            tomcat.enableNaming();

            return super.getTomcatEmbeddedServletContainer(tomcat);
        }

        @Override
        protected void postProcessContext(Context context) {
            // LogDS
            context.getNamingResources()
                .addResource(
                    getContextResource(logJndiName, logUrl, logUsername, logPassword)
                );
            ContextResourceLink contextResourceLink = new 
                    ContextResourceLink();
                             contextResourceLink.setGlobal(logJndiName);
                             contextResourceLink.setName(logJndiName);
                             contextResourceLink.setType("javax.sql.DataSource");
                             context.getNamingResources().addResourceLink(contextResourceLink);

        }

        private ContextResource getContextResource(
                final String name
                , final String url
                , final String username
                , final String password
            ) {
            ContextResource resource = new ContextResource();
            resource.setName(name);
            resource.setType(DataSource.class.getName());
            resource.setProperty("factory", "com.zaxxer.hikari.HikariJNDIFactory");
            resource.setProperty("jdbcUrl", url);
            resource.setProperty("dataSource.user", username);
            resource.setProperty("dataSource.password", AESCrypto.decrypt(password));
            resource.setScope("Sharable");
            return resource;
            }
        };
    }
}

对这个问题有什么看法吗?

-------更新---------

当我使用下面的代码时,JMSListener中的上下文解决但我的RestController不再回答,发生404 http状态。

 protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(Tomcat tomcat) {
            tomcat.enableNaming();
            TomcatEmbeddedServletContainer container = super.getTomcatEmbeddedServletContainer(tomcat);
            for (Container child : container.getTomcat().getHost().findChildren()) {
                if (child instanceof Context) {
                    ClassLoader contextClassLoader = ((Context) child).getLoader().getClassLoader();
                    Thread.currentThread().setContextClassLoader(contextClassLoader);
                    break;
                }
            }
            return container;
        }

------- UPDATE2 --------- 我的问题已解决。而不是像我上面所说的那样返回“容器”,而是返回super.getTomcatEmbeddedServletContainer(tomcat);我的第一次更新中的手册GlobalContext运行良好!

1 个答案:

答案 0 :(得分:0)

我的问题已解决。而不是像上面说的那样返回" container"而是返回super.getTomcatEmbeddedServletContainer(tomcat);我的第一次更新中的手册GlobalContext运行良好!