My application is currently working fine on weblogic. But due to upgrade the application, I want to use spring boot and embedded tomcat. I have a JndiTemplate bean such as:
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">${java.naming.factory.initial}</prop>
<prop key="java.naming.provider.url">${java.naming.provider.url}</prop>
</props>
</property>
</bean>
This template is a helper to lookup for jndi objects like datasources and jms.
As you know the factory is weblogic.jndi.WLInitialContextFactory and url is t3://SERVER:PORT when we are on weblogic. but speaking of tomcat I dont know how to configure this template.
Tomcat is not a Java EE container like Weblogic. If you really want to keep using JNDI, have a look at TomEE.
Personally, I would let Spring manage the database connection. The advantage of using a framework like Spring is that it takes alot of responsibilities away from the container your application is running in, like eg. the database connection.
Spring Boot autoconfigures a DataSource by looking at:
your application.yml for the JDBC url and username/password
your pom.xml to see which database driver it will use (Spring Boot can also derive that from your JDBC url, but you'll have to add the driver library)
There's really nothing more to do.
You can now autowire the DataSource or use Spring's JdbcTemplate to avoid alot of boilerplate code.
This can be configured using Config files using #Bean annotation to initialize the TomcatEmbeddedServletContainerFactory . Please see below code snippet which might be helpful. Below is one of the format that needs to be updated as per your need.
#Bean
public TomcatEmbeddedServletContainerFactory tomcatFactory() {
return new TomcatEmbeddedServletContainerFactory() {
#Override
protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(Tomcat tomcat) {
tomcat.enableNaming();
return super.getTomcatEmbeddedServletContainer(tomcat);
}
/* (non-Javadoc)
* #see org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory#postProcessContext(org.apache.catalina.Context)
*/
#Override
protected void postProcessContext(Context context) {
ContextResource resource = new ContextResource();
resource.setName("your_app_DS_name");
resource.setType("your_app_property");
resource.setProperty("driverClassName", "your_app_Drive");
resource.setProperty("factory", "your_app_factory_property_details");
//similarly configure other needed and dependent properties.
context.getNamingResources().addResource(resource);
}
};
}
Related
I have an old spring app, and I want to update it to use a jndi looked up ejb.
The old spring app has a config file defining beans like so :
<bean id="myBean" class="uk.co.mycompany.mypackage">
<property name="dependentDao" ref="myOtherDaoBean"/>
</bean>
In my new applications I use ejbs to looked up like so :
#EJB(lookup = "java:global/myApp/myModule/MyOtherDaoBean!uk.co.mycompany.mypackage.MyOtherDaoBeanImpl")
private MyOtherDaoBean myOtherDaoBean;
How can I specify the spring app to use the new way ? I can include the bean interfaces as a dependent jar, but I want the runtime instance looked up using jndi.
I am using Hessian in a Spring MVC project. I create server side implementation and then would like to configure the client. Client can be configured with code that uses HessianProxyFactory for the initialization of the client. The URL that is used is now hard coded in the code, but I would like to wire the service some how as a Spring bean so that the code side config would be handled with #Autowired annotation.
How to make this? All help is appreciated.
It is described in 20.3.3 Linking in the service on the client:
<bean id="accountService" class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
<property name="serviceUrl" value="http://remotehost:8080/remoting/AccountService"/>
<property name="serviceInterface" value="example.AccountService"/>
</bean>
Where example.AccountService is the service interface that the server implements. The client also needs that interface, but you probably know that.
Alternatively use Java configuration:
#Bean
public HessianProxyFactoryBean accountService() {
HessianProxyFactoryBean factory = new HessianProxyFactoryBean();
factory.setServiceUrl("http://remotehost:8080/remoting/AccountService");
factory.setServiceInterface(AccountService.class);
return factory;
}
Now you are capable of simply injecting:
#Autowired
private AccountService accountService;
The HessianProxyFactoryBean allows you to configure various other features like security and timeouts.
I have a spring mvc app that I want to refactor out, speficially removing the spring related code and wiring.
It is a simple spring mvc at this point, so the key things I have to do our dependancy injection.
My application.xml has wirings for my Dao objects, injecting the datasource into my Dao objects.
How can I use a spring agnostic DI now? What do I have to change? I want to use guice unless you guys recommend otherwise
application.xml:
<bean id="userDao" class="com.blah.dao.UserDaoImpl">
<property name="dataSource" ref="dataSource" />
</bean>
What do you suggest I use to setup my datasource and connection pooling now?
The actual page/url mapping is specific to if I choose servlets or a jetty handler.
You can use the standard annotation #Inject for dependency injection. Both Spring and Guice support it.
I am using Spring to expose an MBean and register it with the JBoss MBean server. This works fine when the war is dropped into an instance of JBoss. It does not work however when running unit tests (which makes sense since there is no instance of JBoss running)
Here is the extract from the spring configuration
<bean id="updateConfigMBean" class="mypackage.UpdateConfigMBean"/>
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="server">
<bean class="org.jboss.mx.util.MBeanServerLocator" factory-method="locateJBoss"/>
</property>
<property name="beans">
<map>
<entry key="mypackage:name=configurationMBean" value-ref="updateConfigMBean"/>
</map>
</property>
</bean>
What I am looking for is an elegant way of dealing with this issue(don't want to have two spring configurations (for testing and for deployment) and disabling the spring config validation test is not an option.
Thanks!
I am using #Bean to solve that problem. #Bean is tailor-made for doing environment-specific bean creation.
The logic below is basically, in development (Tomcat) and test (JUnit), use MBeanServerFactoryBean. Otherwise use the JBoss MBean Server.
#Bean
def mbeanServer: MBeanServer = {
val server = if (environment == "development" || environment == "test") {
val factory = new MBeanServerFactoryBean
factory.setLocateExistingServerIfPossible(true)
factory.setRegisterWithFactory(true)
factory.afterPropertiesSet()
log.info("using default MBeanServer")
factory.getObject
} else {
val clazz = Class.forName("org.jboss.mx.util.MBeanServerLocator")
val locateJboss = clazz.getMethod("locateJBoss", List.empty[Class[_]].toArray: _*)
log.info("using JBoss MBeanServer")
locateJboss.invoke(null,
List.empty[java.lang.Object].toArray: _*).asInstanceOf[MBeanServer]
}
log.info("mbeanServer: " + server)
server
}
In Spring 3.1 you are able to solve this problem and still use XML configuration by using profiles. But the above works with Spring 3.0.
This is one of those situations where you are probably going to have to have two configs, one for testing and one for deployment.
This is where Maven is good, as you have a clear separation between your deployment configs and your test configs. If you are worried about keeping two configs up todate, then you need to structure your configs in such a way that all the common bits are imported into the other configs (that is how we did it).
I would like to configure a DataSource using JNDI in a Java SE app. What is the best way to do this?
So far, I've come across 2 projects:
Apache Naming. The project page has a specific example for configuring a data source, but it looks like the project is super old and no longer active.
JBossNS. It looks like it's easy to configure a local-only JNDI using LocalOnlyContextFactory, but I haven't found any docs on how to actually configure a data source.
If possible, I would like to also configure the data source with a JTA transaction manager (using JOTM?).
Why are you using JNDI for this? It's not that it's a bad solution if you have a provider but there are alternatives such as dependency injection (IoC: via Spring or Guice).
The Spring JDBC data access is described here. The great thing is that you can use Spring to inject a DataSource into your code:
<bean class="com.my.Persister">
<property name="dataSource" ref="dataSource" />
</bean>
The data source can be defined using a JNDI-lookup:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/MyDataSource" />
In a test environment, you could inject the data source directly:
<bean id="dataSource" class="apache.db.PoolingDataSource">
<!-- config goes here -->
</bean>
These references are pretty old but may help to use jnpserver (JBoss Naming Service provider):
Working With JNDI In A J2SE Application
Standalone JNDI server using jnpserver.jar
A very easy to use solution for stand-alone JNDI is simple-jndi. It works like a charm as long as you only need it within a single JVM, since it's a library no network server.
The Simple-JNDI version, referenced by klenkes74, is not under active development any more. Because I encountered some issues with it I forked it, did some bug fixes and implemented some new features. I already used the old version not only for testing but in production too because I prefer a Service Locator pattern over Dependency Injection although the latter one is more trendy nowadays.
You can easily use Simple-JNDI to define a DataSource or a connection pool declaratively and get it bound to a JNDI Context.
Define a jndi.properties file in your classpath:
java.naming.factory.initial=org.osjava.sj.SimpleContextFactory
org.osjava.sj.root=[absolute_or_relative_path_to_a_property_file]
The property file looks like:
type=javax.sql.DataSource
driver=org.gjt.mm.mysql.Driver
url=jdbc:mysql://localhost/testdb
user=testuser
password=testing
Now you can access your DataSource from inside your code this way:
InitialContext ctxt = new InitialContext();
DataSource ds = (DataSource) ctxt.lookup("name_of_your_datasource");
For more information see https://github.com/h-thurow/Simple-JNDI