I've got a bean defined in resource.groovy like
beans = {
jmsConnectionFactory(org.apache.activemq.pool.PooledConnectionFactory) {bean ->
connectionFactory = {org.apache.activemq.ActiveMQConnectionFactory cf ->
brokerURL = brokerDestination
}
}
}
Now, is there a way to dynamically change the brokerURL at runtime and therefore also restart the activemq connection?
An easier solution will be to define multiple connection factories for each of your brokers and corresponding bean destinations. You can then swap out the destinations conditionally in your code based on your requirement - there would not be a easy way to go back and modify the bean definitions once the beans have been initialized.
Related
I am new to grails and while working with Spring Security LDAP plugin it was identified that it accepts the ldap server password in plain text only. The task in hand is to pass an encrypted password which is decrypted before it is consumed by the plugin during its initialization phase.
I have already searched for all possible blogs and stackoverflow questions but could not find a way to extend the main plugin class to simply override the doWithSpring() method so that i can simply add the required decryption logic for the Ldap server password. Any help here will be appreciated.
I have already seen and tried jasypt plugin but it also does not work well if the password is stored in some external file and not application yml. So I am looking for a solution to extend the Spring security plugin main class, add the required behavior and register the custom class.
EDIT
Adding the snippet from Grails LDAP Security plugin, which I am trying to override. So If i am successfully able to update the value of securityConfig object before the plugin loads, the purpose is solved.
Some snippet from the plugin:
def conf = SpringSecurityUtils.securityConfig
...
...
contextSource(DefaultSpringSecurityContextSource, conf.ldap.context.server) { // 'ldap://localhost:389'
authenticationSource = ref('ldapAuthenticationSource')
authenticationStrategy = ref('authenticationStrategy')
userDn = conf.ldap.context.managerDn // 'cn=admin,dc=example,dc=com'
**password = conf.ldap.context.managerPassword // 'secret'**
contextFactory = contextFactoryClass
dirObjectFactory = dirObjectFactoryClass
baseEnvironmentProperties = conf.ldap.context.baseEnvironmentProperties // none
cacheEnvironmentProperties = conf.ldap.context.cacheEnvironmentProperties // true
anonymousReadOnly = conf.ldap.context.anonymousReadOnly // false
referral = conf.ldap.context.referral // null
}
ldapAuthenticationSource(SimpleAuthenticationSource) {
principal = conf.ldap.context.managerDn // 'cn=admin,dc=example,dc=com'
**credentials = conf.ldap.context.managerPassword // 'secret'**
}
You don't need to override the doWithSpring() method in the existing plugin. You can provide your own plugin which loads after the one you want to affect and have your doWithSpring() add whatever you want to the context. If you add beans with the same name as the ones added by the other plugin, yours will replace the ones provided by the other plugin as long as you configure your plugin to load after the other one. Similarly, you could do the same think in resources.groovy of the app if you don't want to write a plugin for this.
You have other options too. You could write a bean post processor or bean definition post processor that affects the beans created by the other plugin. Depending on the particulars, that might be a better idea.
EDIT:
After seeing your comment below I created a simple example that shows how you might use a definition post processor. See the project at https://github.com/jeffbrown/postprocessordemo.
The interesting bits:
https://github.com/jeffbrown/postprocessordemo/blob/master/src/main/groovy/demo/SomeBean.groovy
package demo
class SomeBean {
String someValue
}
https://github.com/jeffbrown/postprocessordemo/blob/master/src/main/groovy/demo/SomePostProcessor.groovy
package demo
import org.springframework.beans.BeansException
import org.springframework.beans.MutablePropertyValues
import org.springframework.beans.PropertyValue
import org.springframework.beans.factory.config.BeanDefinition
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory
import org.springframework.beans.factory.support.BeanDefinitionRegistry
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
class SomePostProcessor implements BeanDefinitionRegistryPostProcessor{
#Override
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
BeanDefinition definition = registry.getBeanDefinition('someBean')
MutablePropertyValues values = definition.getPropertyValues()
PropertyValue value = values.getPropertyValue('someValue')
def originalValue = value.getValue()
// this is where you could do your decrypting...
values.addPropertyValue('someValue', "MODIFIED: ${originalValue}".toString())
}
#Override
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
https://github.com/jeffbrown/postprocessordemo/blob/master/grails-app/conf/spring/resources.groovy
beans = {
someBean(demo.SomeBean) {
someValue = 'Some Value'
}
somePostProcessor demo.SomePostProcessor
}
https://github.com/jeffbrown/postprocessordemo/blob/master/grails-app/init/postprocessordemo/BootStrap.groovy
package postprocessordemo
import demo.SomeBean
class BootStrap {
SomeBean someBean
def init = { servletContext ->
log.info "The Value: ${someBean.someValue}"
}
def destroy = {
}
}
At application startup you will see log output that looks something like this...
2017-10-23 19:04:54.356 INFO --- [ main] postprocessordemo.BootStrap : The Value: MODIFIED: Some Value
The "MODIFIED" there is evidence that the bean definition post processor modified the property value in the bean. In my example I am simply prepending some text to the string. In your implementation you could decrypt a password or do whatever you want to do there.
I hope that helps.
After trying Jasypt plugin and BeanPostProcessor solutions unsuccessfully for my use case, I found below solution to work perfectly.
To describe again the problem statement here,
a) we had to keep the passwords in an encrypted format inside properties files
b) and given we were packaging as a war file so the properties must not be kept inside the war to allow automated deployment scripts update the encrypted passwords depending on the environment
Jasypt plugin was a perfect solution for the use case a), but it was not able to cover the b) scenario
Moreover, the Grails LDAP Security plugin was getting loaded quite early hence Bean Post processors were also not helping out here.
Solution:
Created a new class by implementing the interface SpringApplicationRunListener. Extended its methods and parsed the properties file using YamlPropertySourceLoader
Sample code:
YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
PropertySource<?> applicationYamlPropertySource = loader.load(
"application.yml", new ClassPathResource("application.yml"),"default");
return applicationYamlPropertySource;
Once the properties were loaded inside the MapPropertySource object, parsed them for the encrypted values and applied the decryption logic.
This whole implementation was executed before any plugins were initialized during Grails bootup process solving the purpose.
Hope it will help others.
So, Grails already sets up datasources backed by connection pools. Is there a way to leverage those for use with DBAppender in Logback so that I don't have to create a separate parallel datasource/connection pool?
logback.groovy is somewhat external to Grails, so it doesn't accept Spring autowiring, and other tricks like grails.util.Holders.findApplication() don't appear to work.
Woof, this was a chore. Frankly, I'm a bit disillusioned with Logback. Logback creates it's own Spring ApplicationContext. So we have two separate contexts. Ugh. Also, it certainly doesn't help that the DSL that Logback uses for configuring Spring in Groovy is different than Grails'.
Since Logback gets fired up before Grails is completely started, we need to tell Logback to create some dummy appenders that will just store log messages until we fire up appenders from within Grails. We use the logback extension for Spring to do this.
build.gradle:
compile 'org.logback-extensions:logback-ext-spring:0.1.4'
logback.groovy:
import ch.qos.logback.ext.spring.DelegatingLogbackAppender
appender('DB', DelegatingLogbackAppender)
appender('STDOUT', DelegatingLogbackAppender)
resources.groovy:
import ch.qos.logback.ext.spring.ApplicationContextHolder
import ch.qos.logback.classic.encoder.PatternLayoutEncoder
import ch.qos.logback.classic.db.DBAppender
import ch.qos.logback.core.ConsoleAppender
import ch.qos.logback.core.db.DataSourceConnectionSource
import org.slf4j.LoggerFactory
beans = {
applicationContextHolder(ApplicationContextHolder)
loggerContext(LoggerFactory) { bean ->
bean.factoryMethod = "getILoggerFactory"
}
patternLayoutEncoder(PatternLayoutEncoder) { bean ->
bean.initMethod = 'start'
bean.destroyMethod = 'stop'
context = ref(loggerContext)
pattern = "%level %logger - %msg%n"
}
STDOUT(ConsoleAppender) { bean ->
bean.initMethod = 'start'
bean.destroyMethod = 'stop'
context = ref(loggerContext)
encoder = ref(patternLayoutEncoder)
}
connectionSource(DataSourceConnectionSource) { bean ->
bean.initMethod = 'start'
bean.destroyMethod = 'stop'
context = ref(loggerContext)
dataSource = ref(dataSource)
}
DB(DBAppender) { bean ->
bean.initMethod = 'start'
bean.destroyMethod = 'stop'
context = ref(loggerContext)
connectionSource = ref(connectionSource)
}
}
The ref(dataSource) in the DataSourceConnectionSource references the dataSource you have configured in application.yml or application.groovy.
Say you have multiple dataSources (or even one configured just for logback called dataSources.logging. In that case the bean reference would be dataSource_logging. The default dataSource in that case (called dataSources.dataSource bean reference is just dataSource. Took me a while to figure that one out.
All in all, i miss the days of configuring Log4j from within the Grails config file using the Grails DSL. I get that separating logging from Grails means one less thing for Graeme and the Grails team to deal with, but this was a major PITA for something that I thought would be common. ¯\_(ツ)_/¯
I am making both a Grails plugin and several Grails apps that will use the plugin.
I want to define a few properties and give them defaults in the plugin, but allow apps to override their values (optional). This question surrounds the mechanical details of how to wire both plugin and child app alike in this manner.
Say I want my plugin (grails-myplugin) to define the following properties in its Config.groovy:
myplugin {
fizz {
whistles = true // Default for all child apps using this plugin
buzz = 3 // Default for all child apps using this plugin
}
}
grails.plugins.anotherPlugin.widget = 'auto'
grails.plugins.anotherPlugin.foo = '${myplugin.fizz.buzz}-40' // Hence, by default, is '3-40'
Now, I would like a child Grails app, say, myapp.war (which uses grails-myplugin) to override the 2 fizz properties:
// myapp's Config.groovy:
myplugin {
fizz {
// whistles property not defined here so this app uses the
// plugin's default of "true"
// Overrides the plugin's value of 3; this imples
// grails.plugins.somePlugin.foo is '12-40'
buzz = 12
}
}
A few issues here:
Have I placed everything correctly for the desired functionality?
With the above configuration, in grails-myplugin's Config.groovy, I have an error message:
Multiple markers at this line: - The type groovy.lang.MetaClass cannot be resolved. It is indirectly referenced from required .class files. - The type groovy.lang.GroovyObject cannot be resolved. It is indirectly referenced from required .class files.
The fact that I'm getting this error tells me that I'm ether trying to do something that is impossible in Grails, or that I'm just doing it wrong. Ideas?
Here you have how the quartz plugin resolved it:
https://github.com/grails-plugins/grails-quartz/blob/master/QuartzGrailsPlugin.groovy
Take a look at loadQuartzConfig method.
Also be aware that grails plugin exclude some parts of it to avoid problems when installing. It's configured on the plugin file like this:
def pluginExcludes = [
'grails-app/jobs/**',
'src/docs/**',
'web-app/**'
]
Hi quick question about injecting an alternative data-source during integration testing of an (EJB 3.0) EJB through its raw POJO API using junit.
I have been converting raw POJO services to EJB3 session beans. To do so has really just meant annotating the POJOs directly. The services are also accompanied by existing junit integration tests (that check the result of methods that query a real test database).
Several of these services require a direct java.sql.Connection and so I intend to configure this through an injected DataSource. The intention of this is so that I can deploy the bean directly to an app server (WLS, as it happens). However, I also want the existing integration tests to continue to work. These tests run against their own test database so I need to be able to inject the test configuration when running the integration tests (in a POJO/ non-container environment).
The question is:
Once I've set up my EJB, is there no way that I can override the injected bean without operating inside a container?
Put another way, is there no straightforward way to inject a new JNDI configuration when running the raw POJO integration tests?
An example service resembles the following:
#Stateless(mappedName="MyInterface")
public class MyClassImpl implements MyInterface {
...
#Resource(name="jdbc/MyAppServerDataSourceJNDIName")
DataSource ds;
Connection conn;
...
}
N.B. I don't intend to leave the DataSource and Connection in the services, I just want to get something sensible working before organically refactoring it.
Solutions I'm considering:
One (pretty awful) notion I have is to just provide a setter on the Connection in the service that is package-private. This way, my junit tests can set the Connection prior to execution. Then, in an app-server environment, the injected DS will be used. Not pretty though.
I've taken a look at ejb3unit (BaseSessionBeanFixture) and am considering that.
I also understand that I could create an EJB container in the junit and run within the container. The thing is, I'd like to test the base functionality using straightforward junit tests and against the POJOs (not the EJBs).
I know this can be done in spring (I'm a bit of an EJB novice) and am considering wiring the EJBs using spring config.
There's a lot of info out there but nothing specific (mostly JPA). Some good pointers elsewhere on SO though.
Thanks in advance.
My recommendations:
Remove the conn field, and use ds.getConnection() (and conn.close()) consistently. In your unit testing environment, you can mock DataSource/Connection (or otherwise provide obtain and provide "real" objects that are connected to a test database).
Add a setter to the EJB class. In fact, you can annotate the method for injection so that your container and unit test environments are even closer. You state that adding a setter would be "pretty awful", but I'm not sure why; setters are very much in the spirit of dependency injection. I agree that adding the setter to the business interface makes no sense, but it seems fine to add one to the bean class.
Example of #2:
#Resource(name="jdbc/MyAppServerDataSourceJNDIName")
public void setDataSource(DataSource ds) {
this.ds = ds;
}
This is the skeleton of the additional boilerplate to provide an injectable Connection to your service (package-private only) so that the EJB is usable as an EJB in an app-container but also as a POJO for junit testing with locally configurable Connection. Note, there is additional boiler-plate and we rely on tests calling #closeConnection to manage it properly.
This solution harks back to the original question and bkail's response:
#Stateless(mappedName = "MyClass")
...
public class MyClass {
// DataSource as configured for app-server environment
#Resource(name="app-dataSource")
private DataSource appDataSource;
private Connection conn;
/**
* Injectable {#code Connection} for injection by unit tests.
*/
/*package-private*/ void setConnection(Connection conn) {
this.conn = conn;
}
/**
* Get {#code Connection}. Use injected Connection if supplied, otherwise
* obtain one from the datasource. Client is responsible for closing this
* through call to #closeConnection (only!).
*/
final Connection getConnection() {
if (this.conn != null) {
return this.conn;
} else {
//Needs exception handling
//
return getDataSource().getConnection)
}
}
/*package-private*/ final void closeConnection(Connection conn) {
if (conn != null && conn != this.conn) {
try{
conn.close();
} catch ... {}
}
}
/*
* Accessor for the {#code DataSource}.
* #return the DataSource
*/
private DataSource getDataSource() {
if (ds == null) {
...
ds = (DataSource) ctx.lookup(jndiName);
...
}
return ds;
}
...
}
public class TestMyClass {
private Connection conn = null;
#BeforeClass
public void setUpBeforeClass() throws Exception {
...
conn = DriverManager.getConnection(...);
}
#Test
public void testMyMethod {
MyClass mc = new MyClass();
mc.setConnection(conn); // Set our own connection
// do test stuff
...
}
...
}
This article suggests Tomcat 7 apps should use a JDBC connection pool instead of a commons-dbcp connection pool. However, the latter is the default for a Grails app, and it's not obvious how to change it.
My guess is that I need to define a Spring bean in resources.groovy that overrides a bean that is normally created by default, but I've no idea what this bean should be named or what properties I need to set.
The easiest thing to do would probably be to use the jdbc-pool plugin. Since the configuration options for this pool are intentionally very similar to Commons DBCP (they're documented here) you can use the plugin to define the jar dependency and manage switching the class for you. The plugin hasn't been updated in a year so it's a little out of date (the plugin uses version 1.0.9.0 but the latest is 1.0.9.3) so you might want to define the plugin dependency excluding the jar, and add one for the newer version. It's in the ebr repo, so you'll need to add that to your BuildConfig.groovy (see the plugin's version for how he did it).
There are configuration notes for the pool here and a series of blog posts by the author here.
If you do want to configure this without using the plugin, add the ebr repo and the jar dependency to BuildConfig.groovy:
repositories {
inherits true
...
ebr()
}
dependencies {
runtime('org.apache.tomcat:com.springsource.org.apache.tomcat.jdbc:1.0.9.3') {
transitive = false
}
}
and create an override for the dataSource bean in resources.groovy:
import org.apache.tomcat.jdbc.pool.DataSource
beans = {
dataSource(DataSource) {
// mandatory
driverClassName = '${dataSource.driverClassName}'
username = '${dataSource.username}'
password = '${dataSource.password}'
url = '${dataSource.url}'
// optional
minEvictableIdleTimeMillis=1800000
timeBetweenEvictionRunsMillis=1800000
numTestsPerEvictionRun=3
testOnBorrow=true
testWhileIdle=true
testOnReturn=true
validationQuery="SELECT 1"
}
}
It's convenient to use single-quoted strings with ${} placeholders to take advantage of Spring's property placeholder functionality and keep things DRY since you've already set the driver and connect info in DataSource.groovy.
In DataSource.groovy I use the following:
environments {
integration {
dataSource {
pooled = false
jndiName = "java:/comp/env/jdbc/myJndiName"
}
}
}
And everything else is defined by Tomcat - this just needs to match it. There is no need to define any dataSource bean in resources.groovy