I am using jms to send messages between two apps, here is the code for receiver app
xmlns amq:"http://activemq.apache.org/schema/core"
amq.'broker'(
useJmx: '${grails.jms.useJmx}',
persistent:'${grails.jms.persistent}',
dataDirectory: '${grails.jms.dataDirectory}'){
amq.'transportConnectors'{
amq.'transportConnector'(uri:'${grails.jms.transportConnector}')
}
}
amqConnectionFactory(ActiveMQConnectionFactory) {
brokerURL = '${grails.jms.brokerUrl}'
}
jmsConnectionFactory(SingleConnectionFactory) { bean ->
targetConnectionFactory = ref(amqConnectionFactory)
}
I am able to run the app but getting error like
"Store limit is 102400 mb, whilst the data directory: /my-activemq-data/localhost/KahaDB only has 7438 mb of usable space" in console. I just want to configure the temp memory usage, can anyone help me on this. thanks
Are you using the https://grails.org/plugin/activemq plugin?
If so, I added precisely that functionality to the plugin.
The plugin allows the following configuration options (just put them in your Config.groovy):
grails.activemq.active = (true|false) default to true
grails.activemq.useJms = (true|false) default to false
grails.activemq.startBroker = (true|false) default to true
grails.activemq.brokerId = (string) default to "brokerId"
grails.activemq.brokerName = (string) default to "localhost"
grails.activemq.persistent = (true|false) default to false
grails.activemq.port = (int) default to 61616
grails.activemq.tempUsageLimit = (size in bytes) defaults to 64Mb
grails.activemq.storeUsageLimit = (size in bytes) defaults to 64Mb
If you aren't using the plugin maybe you should :)
For reference, this is the resources.groovy file I use for most projects (which rely on an application server jndi based JMS service for test and production and use activemq for development):
import grails.util.Environment
import org.apache.activemq.ActiveMQConnectionFactory
import org.springframework.jms.connection.SingleConnectionFactory
import org.springframework.jndi.JndiObjectFactoryBean
beans = {
switch(Environment.current) {
case Environment.PRODUCTION:
case Environment.TEST:
jmsConnectionFactory(JndiObjectFactoryBean) {
jndiName = "java:/ConnectionFactory"
}
break
case Environment.DEVELOPMENT:
jmsConnectionFactory(SingleConnectionFactory) {
targetConnectionFactory = { ActiveMQConnectionFactory cf ->
brokerURL = 'vm://localhost'
}
}
break
}
}
I had the same problem as you while using ActiveMQ with the activemq plugin, so I made a pull request adding those configuration options and setting them to a more reasonable default (for development) of 64Mb.
If you use the plugin you just need to add it to your BuildConfig plugins section, and it should work ok without further configuration, just the resources.groovy inside config/spring.
Anyway, the options I described should go into Config.groovy if you need any of them.
Finally, I got solution to my problem. here is the updated resource.groovy
activeMQTempUsage(TempUsage) {
activeMQTempUsage.limit = 1024 * 1024 * 1024
}
activeMQStoreUsage(StoreUsage) {
activeMQStoreUsage.limit = 1024 * 1024 * 1024
}
activeMQSystemUsage(SystemUsage){
activeMQSystemUsage.tempUsage = ref('activeMQTempUsage')
activeMQSystemUsage.storeUsage = ref('activeMQStoreUsage')
}
tcpConnector(TransportConnector,uri:'tcp://localhost:61616') {
}
connectors(ArrayList,[ref('tcpConnector')]){
}
myBrokerService(XBeanBrokerService){bean->
myBrokerService.useJmx = false
myBrokerService.persistent = true
myBrokerService.dataDirectory = 'my-activemq-data'
myBrokerService.systemUsage = ref('activeMQSystemUsage')
myBrokerService.transportConnectors = ref('connectors')
}
amqConnectionFactory(ActiveMQConnectionFactory) {
brokerURL = 'vm://localhost'
}
jmsConnectionFactory(SingleConnectionFactory) { bean ->
targetConnectionFactory = ref(amqConnectionFactory)
}
Using XbeanBrokerService properties we can achieve this, if you we want add more configuration we can add by using properties of XbeanBrokerService as like above.
Related
In Grails 2, we had the following block of code in our Config.groovy file. The ConfigurationManagement class did a runtime lookup in a Configuration Management Database to determine if the quartz.autoStartup parameter should be true or false. We also used similar configuration to load additional Quartz properties.
quartz {
def autoStartupOnTheseServers = ConfigurationManagement.getValue("myApp.quartz.autoStartupOnTheseServers", "").split(",")
if ( autoStartupOnTheseServers.any { it.trim().toUpperCase() == hostName.toUpperCase() } ) {
autoStartup = true
}
else {
autoStartup = false
}
// Default for clustering (jdbcStore) has to be "false" so the app will run locally.
// Clustering (jdbcStore) will be true for DEV, TEST, QA, and PROD (set by Configuartion Management).
jdbcStore = ConfigurationManagement.getValue("myApp.quartz.jdbcStore", "false").toBoolean()
// don't set the props if not enabling quartz clustering...causes an exception.
if(jdbcStore == true) { props(quartzProps) }
}
In Grails 3, similar code used in application.groovy doesn't work and there isn't any facility for conditionals that I can find for application.yml. Is there any way in Grails 3 to do a similar dynamic configuration?
In Grails 3, it seems that you can't set these values directly, but you can declare a local variable and use that to set the property. So, for my example above, the following works:
def extServerList = ConfigurationManagement.getValue("myApp.quartz.autoStartupOnTheseServers", "").split(",")
def extAutoStartup = extServerList.any { it.trim().toUpperCase() == hostName.toUpperCase() }
def extJdbcStore = ConfigurationManagement.getValue("myApp.quartz.jdbcStore", "false").toBoolean()
quartz {
autoStartupOnTheseServers = extServerList
autoStartup = extAutoStartup
jdbcStore = extJdbcStore
}
Using Jms plugin for grails and add dependencies for ActiveMQ worked perfect. No problems.
Now I want to go beyond and perform some customization and fine tuning to make ActiveMQ behaves as I need, so I need to configure the broker instance.
e.g. I want to use JDBC storage.
How is possible to do that with grails and the vm embedded broker?
I've actually followed the reference documentation for the JMS grails plugin ... I add jms plugin and activemq dependencies and place this on resources:
jmsConnectionFactory(SingleConnectionFactory) {
targetConnectionFactory = { ActiveMQConnectionFactory cf ->
//brokerURL = 'vm://localhost'
brokerURL = 'tcp://localhost:61616?jms.useAsyncSend=true'
}
}
As I've said this is fine ... but I need more tuning here, so I've tried to go adding this in the resources, so I can access the broker to fine tuning:
/* Establish the broker */
amq.broker(useJmx: false, persistent: true) {
amq.transportConnectors() {
amq.transportConnector(uri: "tcp://localhost:61616")
}
}
amqConnectionFactory(ActiveMQConnectionFactory) {
brokerURL = "vm://localhost"
}
jmsConnectionFactory(SingleConnectionFactory) {
targetConnectionFactory = ref(amqConnectionFactory)
}
But I start to have dependency problems like:
2015-03-18 13:44:14 - spring.RuntimeSpringConfigUtilities [RuntimeConfiguration] Unable to load beans from resources.groovy
org.springframework.beans.FatalBeanException: NamespaceHandler class [org.apache.xbean.spring.context.v2.XBeanNamespaceHandler] for namespace [http://activemq.apache.org/schema/core] not found; nested exception is java.lang.ClassNotFoundException: org.apache.xbean.spring.context.v2.XBeanNamespaceHandler
So I start adding dependencies:
compile 'org.apache.activemq:activemq-spring:5.7.0'
compile 'org.springframework:spring-beans:4.1.1.RELEASE'
compile 'org.apache.xbean:xbean-spring:4.1'
But still have problems:
java.lang.NoClassDefFoundError: org/springframework/core/OrderComparator$OrderSourceProvider
At this point I get the feeling that I am doing something wrong since I see too much complexity.
Is there a best way to do this?
In order to be able to configure ActiveMQ you'll need:
Dependencies:
compile 'org.apache.activemq:activemq-core:5.7.0'
compile 'org.apache.activemq:activemq-spring:5.7.0'
compile 'org.springframework:spring-beans:4.0.6.RELEASE'
compile 'org.apache.xbean:xbean-spring:4.1'
Resources.groovy:
xmlns amq:"http://activemq.apache.org/schema/core"
...
/* Establish the broker */
amq.broker(useJmx: false, persistent: true) {
amq.transportConnectors() {
amq.transportConnector(uri: "tcp://localhost:61616")
}
//HERE YOU CAN CONFIGURE BROKER
}
amqConnectionFactory(ActiveMQConnectionFactory) {
brokerURL = "vm://localhost"
}
jmsConnectionFactory(SingleConnectionFactory) {
targetConnectionFactory = ref(amqConnectionFactory)
}
The above answer of Rafael is very useful just a small change you need to do if you are working with Grails 3.2.+ it took me few hrs to figure it out.
Depedencies (add them in build.gradle)
compile 'org.grails.plugins:jms:2.0.0.RC2'
compile 'org.apache.activemq:activemq-core:5.7.0'
compile 'org.apache.activemq:activemq-spring:5.14.5'
compile 'org.apache.xbean:xbean-spring:4.1'
Resources.groovy (should look something like)
import org.apache.activemq.ActiveMQConnectionFactory
import org.springframework.jms.connection.SingleConnectionFactory
beans = {
....
xmlns amq:"http://activemq.apache.org/schema/core"
amq.broker(useJmx: false, persistent: true) {
amq.transportConnectors() {
amq.'transportConnector'(uri: "tcp://localhost:61616")
// optional if you want to do something with mqtt
amq.'transportConnector'(uri:'mqtt://0.0.0.0:61612')
}
}
jmsConnectionFactory(SingleConnectionFactory) {
targetConnectionFactory = { ActiveMQConnectionFactory cf ->
brokerURL = 'vm://localhost'
}
}
...
}
I know that, at some point between Grails 1.X and Grails 2.X, the default connection pooling library changed from commons-dbcp to tomcat-dbcp.
Now, I'm trying to configure either BoneCP or HikariCP as the connection pooling library for my Grails application.
However, I see that this answer offers a solution which might only apply to Grails 1.X.
I also found this Gist, but again, I don't know which Grails version it applies to.
So, is it possible to define a custom connection pool inside a Grails 2.3.6 application? Thanks!
UPDATE: OK so you actually need to tell Grails not to pool the datasources, since HikariCP is now taking care of this.
I saw connection weirdness in my apps if I left that switch on. So instead say:
pooled = false
OK yeah, #Joshua Moore is right.
I tried doing it with updated Grails methods and this is the relevant section of my resources.groovy file. As far as I can understand, the configuration values in Datasource.groovy are pulled into resources.groovy at runtime, after the target runtime environment has been identified (development, test or production).
def config = Holders.config
def dataSources = config.findAll {
it.key.toString().contains("dataSource_")
}
dataSources.each { key, value ->
def ds = value
"${key}"(HikariDataSource, { bean ->
def hp = new Properties()
hp.username = ds.username
hp.password = ds.password
hp.connectionTimeout = 6000
hp.maximumPoolSize = 60
hp.jdbcUrl = ds.url
hp.driverClassName = ds.driverClassName
HikariConfig hc = new HikariConfig(hp)
bean.constructorArgs = [hc]
})
}
And this is the relevant section of my DataSource.groovy configuration:
// environment specific settings
environments {
development {
dataSource_myapp1 {
pooled = false
username = "CONFIGURE_ME_EXTERNALLY"
password = "CONFIGURE_ME_EXTERNALLY"
driverClassName = 'oracle.jdbc.OracleDriver'
dialect = 'org.hibernate.dialect.Oracle10gDialect'
url = 'jdbc:oracle:thin:#MYDBHOST1:1521/MYSERVICEID1'
}
dataSource_myApp2 {
pooled = false
username = "CONFIGURE_ME_EXTERNALLY"
password = "CONFIGURE_ME_EXTERNALLY"
driverClassName = 'oracle.jdbc.OracleDriver'
dialect = 'org.hibernate.dialect.Oracle10gDialect'
url = 'jdbc:oracle:thin:#MYDBHOST2:1521/MYSERVICEID2'
}
}
}
In my case, it's pretty much the same for test and production environments. Thanks!
I'm a beginner at grails and jms, and i was trying to do a simple message listener of messages coming from glassfish.
my grails-app/spring/resources.groovy
beans = {
myQueueFactory(SingleConnectionFactory) {
targetConnectionFactory = { ActiveMQConnectionFactory cf ->
brokerURL = 'tcp://localhost:7676'
}
}
grails-app/Config.groovy
jms {
containers {
standard {
autoStartup = true
connectionFactoryBean = "myQueueFactory"
}
}
}
MyService.groovy
class MyService {
static exposes = ['jms']
static destination = 'myQueue'
def onMessage(msg) {
println msg
}
}
But when i send a message, nothings happens! There's something wrong?
Both glassfish and grails app are running in the same localhost.
thanks in advance!
did you look at http://gpc.github.io/grails-jms/docs/manual/index.html?
Do you have ActiveMQ setup and running?
How would static destination = 'myQueue' make the jump to use 'myQueueFactory'?
I installed the Grails JMS pluign into my application, but am not receiving any messages. My config is as follows:
In resources.groovy
jmsConnectionFactory(package.OracleAqFactoryBean) {
dataSource = ref("dataSource")
}
In config.groovy
jms {
containers {
standard {
autoStartup = true
connectionFactoryBean = "jmsConnectionFactory"
}
}
}
In my Grails Service:
class MyService {
static exposes = ["jms"]
static destination = "queuename"
static listenerCount = 5
void onMessage(msg) {
// handle message
println "WE GOT A MESSAGE...."
}
}
In Datasource.groovy
dataSource {
driverClassName = "oracle.jdbc.pool.OracleDataSource"
url = "jdbc:oracle:thin:#restofurl"
username = "xxx"
password = "xxxx"
}
We have a connection to the queue working using standard Spring config in a standard Java app, but that spring config does not work if imported in the Grails app, which is why we are trying to use the jms plugin.