Showing posts with label spring. Show all posts
Showing posts with label spring. Show all posts

Saturday, December 18, 2010

grails - providing your own plugins configuration

sometimes you want to share some services in a plugin, which needs to be configured at runtime.

The easiest way is to provide a simple file in the grails conf diretory of your plugin and just read it and access it at runtime.

How to?

our little helper:


package binbase.core

import grails.util.GrailsUtil
import org.codehaus.groovy.grails.commons.GrailsApplication

/**
* Created by IntelliJ IDEA.
* User: wohlgemuth
* Date: 12/18/10
* Time: 1:00 AM
* To change this template use File | Settings | File Templates.
*/
class BinBaseConfigReader {

private static ConfigObject config = initialize()

/**
* initializes the object
* @return
*/
static ConfigObject initialize() {
return new ConfigSlurper().parse(new GroovyClassLoader(BinBaseConfigReader.class.getClassLoader()).loadClass('BinBaseConfig'))
}

/**
* returns the server
* @return
*/
static String getServer() {
if (GrailsUtil.getEnvironment().equals(GrailsApplication.ENV_TEST)) {
return config.binbase.test.server.toString()
}
else if (GrailsUtil.getEnvironment().equals(GrailsApplication.ENV_DEVELOPMENT)) {
return config.binbase.development.server.toString()
}
else if (GrailsUtil.getEnvironment().equals(GrailsApplication.ENV_PRODUCTION)) {
return config.binbase.production.server.toString()

}
else {
throw new RuntimeException("unexspected enviroment found")
}
}
}



our configuration


/**
* this file contains the binbase configuration for this plugin.
*
*/
binbase {
production {
key = "dasdasd"
server = "10.1.1.1"
}
test {
key = "dasdasd"
server = "10.2.2.2"
}
development {
key = "dasdasd"
server = "127.0.0.1"
}
}


and to access it in your, say spring configuration?


jndiBinBaseTemplate(org.springframework.jndi.JndiTemplate) {

environment = [
"java.naming.factory.initial": "org.jnp.interfaces.NamingContextFactory",
"java.naming.factory.url.pkgs": "org.jboss.naming:org.jnp.interfaces",
"java.naming.provider.url": "${BinBaseConfigReader.getServer()}:1099".toString()
]
}


easy, isn't it?

grails - testing service, which accesses ejb's

this night I just wanted to write a quick grails plugin to access my BinBase database system.

Since I'm a smart developer I start with a simple spring dsl file and write a test.



// Place your Spring DSL code here
beans = {

jndiBinBaseTemplate(org.springframework.jndi.JndiTemplate) {

environment = [
"java.naming.factory.initial": "org.jnp.interfaces.NamingContextFactory",
"java.naming.factory.url.pkgs": "org.jboss.naming:org.jnp.interfaces",
"java.naming.provider.url": "localhost:1099"
]
}

/**
* connection to the cluster configuration
*/
clusterConfigService(SimpleRemoteStatelessSessionProxyFactoryBean) { bean ->
businessInterface = "edu.ucdavis.genomics.metabolomics.binbase.cluster.ejb.delegate.ClusterConfigService"
jndiName = "clusterservice/ClusterConfigServiceBean/remote"
jndiTemplate = ref(jndiBinBaseTemplate)
}

}


and the test code is simple enough



class BinBaseSchedulingServiceTests extends GroovyTestCase {


ClusterConfigService clusterConfigService

protected void setUp() {
super.setUp()
}

protected void tearDown() {
super.tearDown()
}

public void testTest(){
assertTrue(clusterConfigService.username != null)
}
}


the variable 'ClusterConfigService' is an stateless session bean in a jboss container and I know it works...

except grails is complaining:



org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clusterConfigService': Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: Name [clusterservice/ClusterConfigServiceBean/remote] not bound; 0 bindings: []
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1412)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.codehaus.groovy.grails.commons.spring.ReloadAwareAutowireCapableBeanFactory.doCreateBean(ReloadAwareAutowireCapableBeanFactory.java:135)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at
....lots and lots of more...
Caused by: javax.naming.NameNotFoundException: Name [clusterservice/ClusterConfigServiceBean/remote] not bound; 0 bindings: []
at org.springframework.mock.jndi.SimpleNamingContext.lookup(SimpleNamingContext.java:132)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:154)
at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:87)
at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:152)
at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:178)
at org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:95)
at org.springframework.jndi.JndiObjectLocator.lookup(JndiObjectLocator.java:105)
at org.springframework.ejb.access.AbstractRemoteSlsbInvokerInterceptor.lookup(AbstractRemoteSlsbInvokerInterceptor.java:100)
at org.springframework.ejb.access.AbstractSlsbInvokerInterceptor.refreshHome(AbstractSlsbInvokerInterceptor.java:122)
at
...lots and lots of more...
[23:59:35,938] [ERROR] [main] [StackTrace] [Sanitizing stacktrace:]
javax.naming.NameNotFoundException: Name [clusterservice/ClusterConfigServiceBean/remote] not bound; 0 bindings: []
at org.springframework.mock.jndi.SimpleNamingContext.lookup(SimpleNamingContext.java:132)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at org.springframework.jndi.JndiTemplate$1.doInContext(JndiTemplate.java:154)
at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:87)
at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:152)




mhm doesn't make much sense. Reason for the failure is that grails decides to mock the access, which is normally ok. But in our case really really not desired.

After all we want to access the application server context!

But it keeps jumping to the 'org.springframework.mock.jndi.SimpleNamingContext' mocking context.

So the only solution is this slightly dirty hack...


/***
* we do not need mocking in this plugin...
*/
if (org.springframework.mock.jndi.SimpleNamingContextBuilder.currentContextBuilder) {
org.springframework.mock.jndi.SimpleNamingContextBuilder.currentContextBuilder.deactivate()
}



and promptly it passes.

Since we only want to change this for test cases, we add yet another conditon and our resources.groovy file ends up looking like


import org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean
import grails.util.GrailsUtil
import org.codehaus.groovy.grails.commons.GrailsApplication

/** *
* we do not need mocking in this plugin...
*/
if (GrailsUtil.getEnvironment().equals(GrailsApplication.ENV_TEST)) {
println "warning disabling mocking context!!! to make remote ejb's work"
if (org.springframework.mock.jndi.SimpleNamingContextBuilder.currentContextBuilder) {
org.springframework.mock.jndi.SimpleNamingContextBuilder.currentContextBuilder.deactivate()
}
}

// Place your Spring DSL code here
beans = {

jndiBinBaseTemplate(org.springframework.jndi.JndiTemplate) {

environment = [
"java.naming.factory.initial": "org.jnp.interfaces.NamingContextFactory",
"java.naming.factory.url.pkgs": "org.jboss.naming:org.jnp.interfaces",
"java.naming.provider.url": "eros.fiehnlab.ucdavis.edu:1099"
]
}

/**
* connection to the cluster configuration
*/
clusterConfigService(SimpleRemoteStatelessSessionProxyFactoryBean) { bean ->
businessInterface = "edu.ucdavis.genomics.metabolomics.binbase.cluster.ejb.delegate.ClusterConfigService"
jndiName = "clusterservice/ClusterConfigServiceBean/remote"
jndiTemplate = ref(jndiBinBaseTemplate)
}

}