Changing the database used by JBossMQ
By default JBossMQ uses hsqldb for persistence and caching. From 3.2.4 it also uses it
for saving durable topic subscriptions and authentication.
Do not use hypersonic in production
hsqldb is not a production quality database. It is suitable for demos and testing. JBoss ships with the database to help you get something working out of the box.
Known problems with hsqldb:
No transaction isolation
Thread and socket leaks - connection.close() does not tidy up resources
Persistence quality - the database is held in a file in the JBoss data directory, it is a common problem that log becomes corrupted after a failure, leaving you to manually edit the file to recover the database.
Stability under load - strange problems have been seen under load, including the database process "vanishing", i.e. it stops processing when too much data is sent, usually because of an OutOfMemory problem, but not necessarily.
hsqldb uses a file on the local server - although this can be changed to use a remote hsqldb instance, this negates many of the benefits of using hsqldb. The local file makes it impossible to use in a clustered environment.
Please go to the Don't use Hypersonic in production wiki for more information.
Approach 1: Easy, use "DefaultDS"
In this section we will be using "DefaultDS" as the jndi name for the datasource. Since all JBoss services using persistence are configured by default to use a datasource with jndi name "DefaultDs", the number of changes is reduced to a minimum.
Throughout the intructions we will be using an Oracle datasource as an
example. You can find other example configurations for popular database systems in $JBOSS_HOME/docs/examples/jca and
$JBOSS_HOME/docs/examples/jms.
Installing the jdbc driver
JDBC drivers are provided in JAR archives by the database vendor or a third-party company.
- Copy the jar file to server/[your server config]/lib
Deploying the datasource descriptor for your database
Datasource examples for the most popular databases are available in $JBOSS_HOME/docs/examples/jca.
- Copy docs/examples/jca/oracle-ds.xml to deploy{-hasingleton} - Replace the <jndi-name> property value with "DefaultDS" - Configure the datasource (server url, user, password, etc...) - Remove deploy{-hasingleton}/hsqldb-ds.xml
Updating the Persistence Manager service
The persistence manager is using database-specific queries to create tables and other indexes.
Alternate persistence configurations can be found in $JBOSS_HOME/docs/examples/jms.
- Copy docs/examples/jms/oracle-jdbc2-service.xml to deploy{-hasingleton}/jms - Remove deploy{-hasingleton}/hsqldb-jdbc2-service.xml
You may now restart the server instance.
Approach 2: Advanced, use your own datasource name
In this section, we describe the various changes required when the datasource's jndi name is NOT "DefaultDS".
Throughout the intructions we will be referencing an Oracle datasource named "OracleDS"
Installing the jdbc driver
JDBC drivers are provided in JAR archives by the database vendor or a third-party company.
- Copy the jar file to server/[your server config]/lib
Deploying the datasource descriptor for your database
Datasource examples for the most popular databases are available in $JBOSS_HOME/docs/examples/jca.
- Copy docs/examples/jca/oracle-ds.xml to deploy{-hasingleton} - Update the <jndi-name> property if needed - Configure the datasource (server url, user, password, etc...) - Remove deploy{-hasingleton}/hsqldb-ds.xml
Note: An XA datasource is not required for JBossMQ persistence. All work is done is separate transactions that only includes work on the JBossMQ tables. i.e. there is a single branch so there is no need for two phase commit.
Updating the Persistence Manager service
The persistence manager is using database-specific queries to create tables and other indexes.
Alternate persistence configurations can be found in $JBOSS_HOME/docs/examples/jms.
- Copy docs/examples/jms/oracle-jdbc2-service.xml to deploy{-hasingleton}/jms - Remove deploy{-hasingleton}/hsqldb-jdbc2-service.xml
Updating the State Manager service (3.2.4+)
The state Manager holds durable subscriptions. You need to point the service at the correct datasource. In deploy{-hasingleton}/hsqldb-jdbc-state-service.xml
<depends optional-attribute-name="ConnectionManager">jboss.jca:service=LocalTxCM,name=OracleDS</depends>
for JBoss4 this is
<depends optional-attribute-name="ConnectionManager">jboss.jca:service=DataSourceBinding,name=OracleDS</depends>
You can also rename the config file to oracle-jdbc-state-service.xml if you like.
Changing the login config (3.2.4+)
Additionally the JBossMQ login config needs to be changed to use your chosen datasource. In
conf/login-config.xml update the module option dsJndiName.
<!-- Security domain for JBossMQ --> <application-policy name = "jbossmq"> <authentication> <login-module code = "org.jboss.security.auth.spi.DatabaseServerLoginModule" flag = "required"> <module-option name = "unauthenticatedIdentity">guest</module-option> <module-option name = "dsJndiName">java:/OracleDS</module-option> <module-option name = "principalsQuery">SELECT PASSWD FROM JMS_USERS WHERE USERID=?</module-option> <module-option name = "rolesQuery">SELECT ROLEID, 'Roles' FROM JMS_ROLES WHERE USERID=?</module-option> </login-module> </authentication> </application-policy>
Note: If you get a JMSSecurity exception during the deployment, check out WhyDoIGetNullIsNOTAuthenticated
Updating the timer service
The Timer service is not used by JBossMQ although by removing any datasource with jndi name "DefaultDS" it will fail to deploy.
So in /deploy/ejb-deployer.xml, please update the optional attribute "Datasource" on the EJBTimerService MBean as follows:
<!-- A persistence policy that persistes timers to a database --> <mbean code="org.jboss.ejb.txtimer.DatabasePersistencePolicy" name="jboss.ejb:service=EJBTimerService,persistencePolicy=database"> <!-- DataSource JNDI name --> <depends optional-attribute-name="DataSource">jboss.jca:service=DataSourceBinding,name=OracleDS</depends> ...
Updating the HiLo generator service
The HiLo generator service is not used by JBossMQ although by removing any datasource with jndi name "DefaultDS" it will fail to deploy.
in /deploy/uuid-key-generator/META-INF, update the optional attribute "Datasource" on the KeyGeneratorFactory MBean as follows:
<!-- HiLoKeyGeneratorFactory --> <mbean code="org.jboss.ejb.plugins.keygenerator.hilo.HiLoKeyGeneratorFactory" name="jboss:service=KeyGeneratorFactory,type=HiLo"> <depends>jboss:service=TransactionManager</depends> <!-- Attributes common to HiLo factory instances --> <!-- DataSource JNDI name --> <depends optional-attribute-name="DataSource">jboss.jca:service=DataSourceBinding,name=OracleDS</depends> ....
Updating the juddi-service
The juddi service is not used by JBossMQ although by removing any datasource with jndi name "DefaultDS" it will fail to deploy.
Modify /deploy/juddi-service.sar/META-INF/jboss-service.xml to reflect new datasource name it depends on:
.... <depends>jboss.jca:service=DataSourceBinding,name=OracleDS</depends> ....
Other considerations
The schema is not optimized!
As noted in the persistence configuration the schema created by JBoss is not optimized. You may want to create the schema by hand in the database. This will also include creating indexes. A commonly used access path is select ... from JMS_MESSAGES where TXID=? and TXOP=? so creating an index over TXID and TXOP improves performance.
Issues using MySQL and JBoss 4.0.3 / 4.0.3SP1
Using the example configuration for MySQL you may see the following error: -
org.jboss.mq.SpyJMSException: Could not resolve uncommited transactions. Message recovery may not be accurate; - nested throwable: (java.sql.SQLException: Every derived table must have its own alias)
Edit the persistence configuration and change the line :-
SELECT_MAX_TX = SELECT MAX(TXID) FROM (SELECT MAX(TXID) AS TXID FROM JMS_TRANSACTIONS UNION SELECT MAX(TXID) AS TXID FROM JMS_MESSAGES)
to: -
SELECT_MAX_TX = SELECT MAX(TXID) FROM JMS_MESSAGES
See http://jira.jboss.com/jira/browse/JBAS-2425
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=39066723906672
Also using MySQL 4.1.10 this query was causing JBoss to hang for me, upgrading to MySQL 4.1.12 resolved this for me.
Issues using Postgres 8.1.3 and JBoss 4.0.3 / 4.0.3SP1
Using the example configuration for Postgres you may see the following error: -
org.postgresql.util.PSQLException: ERROR: subquery in FROM must have an alias
Edit the persistence configuration and change the line :-
SELECT_MAX_TX = SELECT MAX(TXID) FROM (SELECT MAX(TXID) AS TXID FROM JMS_TRANSACTIONS UNION SELECT M AX(TXID) AS TXID FROM JMS_MESSAGES)
to: -
SELECT_MAX_TX = SELECT MAX(TXID) FROM (SELECT MAX(TXID) AS TXID FROM JMS_TRANSACTIONS UNION SELECT M AX(TXID) AS TXID FROM JMS_MESSAGES) AS TXID
See http://jira.jboss.com/jira/browse/JBAS-2956
http://www.jboss.com/index.html?module=bb&op=viewtopic&t=79227
Issues using Postgres with JBoss 4.2.x
The /docs/examples/jms/postgres-jdbc2-service.xml differs from the standard deploy{-hasingleton}/hsqldb-jdbc2-service.xml. The jboss.mq:service=DestinationManager mbean has the following extra configuration in the hsql version:
<depends optional-attribute-name="ThreadPool">jboss.mq:service=ThreadPool</depends> <depends>jboss:service=Naming</depends>
Without this configuration in the Postgres file, the number of JMSThread (the actual thread name) instances spawned by the application server is not managed. When this is added to the Postgres file, the application server will not spawn more threads than set in the ThreadPool configuration.
Comments