0
votes

I am rather new to spring boot and have implemented a way of placing a datasource in JNDI context by following the advice given in How to create JNDI context in Spring Boot with Embedded Tomcat Container

I got it to work by adding these beans to the application, which enable naming and place the datasource in JNDI-context like this:

@Autowired
Environment env;

public static void main(final String[] args) {
 SpringApplication.run(MyApplication.class, args);
}


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

  @Override
  public TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(final Tomcat tomcat) {
    tomcat.enableNaming();
    return super.getTomcatEmbeddedServletContainer(tomcat);
  }

  @Override
  public void postProcessContext(final Context context) {
    final String dataSourceURL = env.getProperty("datasource.url");
    // more properties

    final ContextResource resource = new ContextResource();
    resource.setType(DataSource.class.getName());
    resource.setProperty("url", dataSourceURL);
    // more properties

    resource.setName("jdbc/myDB");
    resource.setAuth("Container");
    resource.setType("javax.sql.DataSource");
    resource.setScope("Sharable");

    resource.setProperty("factory", "org.apache.commons.dbcp.BasicDataSourceFactory");

    context.getNamingResources().addResource(resource);
  }
};
}

@Bean(destroyMethod = "")
public DataSource jndiDataSource() throws IllegalArgumentException, NamingException {
  final JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
  bean.setJndiName("java:comp/env/jdbc/myDB");
  bean.setProxyInterface(DataSource.class);
  bean.setLookupOnStartup(false);
  bean.afterPropertiesSet();
  return (DataSource)bean.getObject();
}

So far so good, it worked. But now the specification of the project has changed. In addition of delivering a fat JAR that starts up an embedded Tomcat (as initially planned), I need to be able to deliver a WAR that has no references to the embedded Tomcat. So i created extra projects for packaging and handled the optional inclusion of embedded Tomcat via Maven dependencies. Problem is, I had to move the code that is shown above out of my main class and into a seperate package which i include via Maven dependency. And now it no longer does the trick.

I admit that I am not too familiar with how the Spring-magic with @Autowired and @Bean works, so I am kind off stumbling around here.

What do i have to do to make the creation of JNDI context work outside of my main class?

1
Don't.. Just don't... Let the user decide. Just create a WAR file (which is as executable as the jar) and if people want to use JNDI bound datasource specify the spring.dataosurce.jndi-name property else configure the database using the other spring.datasoure properties. Don't try to shoehorn all that into embedded tomcat with JNDI as that makes things way too complex.M. Deinum
Wouldn't I still have to enable naming to do that? Seems to me it would fall back to the same problem.BFR
No you don't need that.M. Deinum
I´m still not sure i understand. You suggest to not use JNDI at all or make it optional? The problem is that i´m reusing an old, established persistence-layer which requires the datasource to be placed in JNDI, so i can't avoid it. Would you mind elaborating on your suggestion?BFR
Judging from your configuration it requires a DataSource where it comes from shouldn't matter. Spring boot supports either.M. Deinum

1 Answers

0
votes

The solution turned out to be quite simple and i could find it by learning more about spring beans. I created another class in which the beans were created, annotated it with @Configuration and added it to the @ComponentScan specification of the main class. Looks like this:

@ComponentScan(basePackages = {"myBasePackage",
                           "externalPackageContainingConfiguration"})

externalPackageContainingConfiguration is only found when it´s artifact is added via Maven Dependency. A little hacky, but does the trick.