Application Server
Deployment in weblogi10
To Deploy:Lock & Edit -> Deployments -> Install -> specify location of your WAR/EAR file -> Next -> Finish -> Activate Changes
To Test:Deployments -> navigate to your application -> select checkbox next to your application -> Start -> Servicing all requests -> Yes -> again navigate to your application -> click on your application -> Testing....
A data source is a Java Naming and Directory Interface (JNDI) object used to obtain a connection from a connection pool to a database. In order to create a DataSource (so that you can use JDBC connectivity) you need to create a file ending with -ds.xml under the "deploy" directory of your server.
The default Datasource file The default data source configured with JBoss 4.0 is the HypersonicDB data source.
Here's the hsqldb-ds.xml that is shipped with jboss :
As you can see from this file, JDBC connectivity uses Connection pools to dispatch Connections. The initial size and the max size of the Connection pool can be configured with <min-pool-size> and <max-pool-size>.
With <idle-timeout-minutes> you can indicate the maximum time a connection may be idle before being closed and returned to the pool. If not specified it's 15 minutes.
<track-statements/> is a debugging feature: it checks that all statements are closed when the connection is returned to the pool: remember to disable it in production environment.
<security-domain> tells to use the security domain defined in conf/login-config.xml : in our case:
<prepared-statement-cache-size> is the number of prepared statements per connection to be kept open and reused in subsequent requests. They are stored in a LRU cache. The default is 0 (zero), meaning no cache.
Enterprise datasources
I) Local Datasource This is a sample Oracle local datasource configuration: a local DataSource is one that does not support two phase commit using a java.sql.Driver.
Notice the <query-timeout> tag which configures the maximum of seconds before a query times out ( avaliable since Jboss 4.0.3). The <exception-sorter-class-name> is used to Check the Oracle error codes and messages for fatal errors.
Remember: In order to use an Oracle datasource you need to put the jdbc driver in jBoss's server's lib directory.
II) XA Datasource This is a sample XA Datasource: XA DataSources support two phase commit using a javax.sql.XADataSource
Notice the <isSameRM-override-value> set to false to fix problems with Oracle. The element <track-connection-by-tx/> can be omitted on JBoss 5 where it's enabled by default.
At last, the <no-tx-separate-pools> means that Oracles XA datasource cannot reuse a connection outside a transaction once enlisted in a global transaction and vice-versa
Configuring your datasource to connect to Oracle RAC Oracle RAC allows multiple computers to run the Oracle RDBMS software simultaneously while accessing a single database thus providing a clustered database.
In order to benefit from Oracle RAC features like fault tolerance and load balancing all you have to do is configuring the connection url with the list of Oracle hosts which belongs to the cluster.
In this example we are configuring our datasource to connect to a RAC made up of host1 and host2:
<connection-url>jdbc:oracle:thin:@(description=(address_list=(load_balance=on)(failover=on)(address=(protocol=tcp)(host=host1)(port=1521))(address=(protocol=tcp)(host=host2)(port=1521)))(connect_data=(service_name=xxxxsid)(failover_mode=()(method=basic))))
</connection-url>
Where to put Datasources if JBoss is clustered ? In a clustered setup, position the file -ds.xml in the JBOSS_HOME\server\all\farm\ directory, it will be replicated on all members of the cluster.
Monitoring your Connection Pool Each datasource translates into several MBeans that you can interact with in the JMX Console. All the datasource-related objects are in the jboss.jca domain. You can find them by searching through the JMX Console page, or by using jboss.jca:* as the query filter.
Supposing you want to monitor your OracleDS datasource from the previous example: you could use a more specific filter, such as jboss.jca:name=OracleDS,*, to see only the OracleDS entries. In either case, four MBeans will be related to the OracleDS datasource:
· name=OracleDS ,service=DataSourceBinding
· name=OracleDS ,service=LocalTxCM
· name=OracleDS ,service=ManagedConnectionFactory
· name=OracleDS ,service=ManagedConnectionPool
While each plays a critical role in providing the datasource functionality in JBoss, you are most likely to need to interact with the connection pool. Click the connection pool MBean to expose the management attributes and operations.
In our datasource file we've been using specified a minimum connection pool size of 2 and a maximum pool size of 10. You'll see those values reflected in the MinSize and MaxSize attributes. You can change the values in the running server by adjusting the values and clicking Apply Changes.
Setting the values here affects the connection pool only in memory. To change the configuration permanently, update the datasource file. Try setting the pool sizes there. When you save the file, JBoss will redeploy the datasource and the new pool sizes will be displayed when you reload the page.
You might occasionally want to adjust the pool size to account for usage; you are more likely to be curious how much of the connection pool is being used. The ConnectionCount attribute shows how many connections are currently open to the database. However, open connections are not necessarily in use by application code. The InUseConnectionCount attribute shows how many of the open connections are in use. Viewing the statistic from the other direction, AvailableConnectionCount shows how much room is left in the pool.
Finally, the MBean has several statistics that track connection pool usage over the pool's lifetime. ConnectionCreatedCount and Connection-DestroyedCount keep running totals of the number of connections created and destroyed by the pool. If IdleTimeout is greater than 0, connections will eventually timeout, be destroyed, and be replaced by fresh connections. This will cause the created and destroyed counts to rise constantly. The MaxConnectionsInUseCount attribute keeps track of the highest number of connections in use at a time.
If you notice anything awkward in the connection pool, or you just want to reset the statistics, you can flush the connection pool using the flush operation on the MBean. This will cause a new connection pool to be created, abandoning the previous connection pool.
A Graph is worth 100 words or so ! if you read our recent Recipes (and we really appreciate that you are a faithful visitor !) then you know that JBoss Web Console is able to show you graphically the value of many MBeans attribute (those who have a numeric value).
So look for the MBean "name=OracleDS ,service=ManagedConnectionPool", there you can choose to add a graph to any of the attributes: in this picture you can see a sample graph of the JMX Attribute Connection Count
How do I configure a Queue/Topic to work in a cluster?
Just set the Clustered attribute to "true" in your Queue/Topic definition. Here's a Queue example:
How to configure a queue in jboss ?
Simply drop a file ending in -service.xml in the deploy folder, containing the Queue definition.
<server>
<mbean code="org.jboss.mq.server.jmx.Queue"
name="jboss.mq.destination:service=Queue,name=MyQueue">
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>
</server>
Verify in the Jmx-console under the jboss.mq.destination tab that the Queue is correctly deployed.
How to a dump of jndi tree with jmx console ?
Quite easy. Open your JMX console:
http://localhost:8080/jmx-console
and look for the Service "JNDIView" (it's under the object name jboss)
Now simply find the method "list", click it et voilà !
without writing a line of code but simply using the JMX Console
How to call a stored procedure with hibernate ?
JBoss recipe of the day
Supposing you have the following Oracle Stored procedure:
CREATE FUNCTION agenda RETURN SYS_REFCURSOR
AS
my_cursor SYS_REFCURSOR;
BEGIN
OPEN my_cursor FOR
SELECT id,person_name,person_surname,person_address
FROM Person;
RETURN my_cursor;
END;
Invoking it from Hibernate requires mapping the Stored Procedure in the Person class.
Supposing you have to fetch a large resultset and update the single objects. By using the standard Query Object you would retrieve the whole set of Objects in Memory:
If you need to operate on an online cursor, then you can use the ScrollableResults:
Notice the counter which flushes the objects every 100 items to free memory.
HOW DO YOU BIND THE ID OF AN ENTITY EJB 3.0 TO A SEQUENCE ?
You can define a SequenceGenerator which points to the DB Sequence. Then you link your Id to the SequenceGenerator through the @GeneratedValue annotation. Example:
Retrieving a large amount of data and returning them to the client can be quite paniful....however with EJB 3 it's quite easy to paginate a large resultset: for example supposing you want to retrieve only the first "page" of 100 Users:
You could further optimize the query with "setFetchSize" which sets a fetch size for the underlying JDBC query.
I have tested with a (rather complex) resultset of 100.000 records on JBoss AS 5.0 + Oracle 10.1. Retrieving the full Resultset took about 12 seconds (not too bad, with plain SQL it took about 7.5 seconds). Retrieving the single page of 100 records took just 0.5 seconds.
HOW DO I LOOKUP FROM A WEB APPLICATION AN EJB DEPLOYED STANDALONE ?
Supposing you have deployed an Enterprise Java Bean as stand alone application and you want to access it from your Servlet / Jsp layer. What you need to do is adding the appropriate references to your web.xml and jboss-web.xml.
So if you have an EJB named "HelloBean" add to your web.xml
Then modify jboss-web.xml by adding:
Now you can safely lookup your EJB from your Servlet:
Context ic = new InitialContext();
Object ejbHome = ic.lookup("java:comp/env/HelloBean");
HOW TO USE NATIVE QUERIES WITH EJB 3.0 ?
You can use the createNativeQuery method of the EntityManager interface to create a
dynamic query using SQL as follows:
here we pass two parameters to the method createNativeQuery: the first is the SQL and
the second is the Entity which will be populated.
What about if your query returns more than one Entity ? You have to use the @SqlResultSetMapping
which will be passed to the method instead of the Entity:
At first we define the mapping:
@SqlResultSetMapping(name = "MyMapping",
entities = @EntityResult(entityClass = sample.Person.User.class))
then we can specify the mapping in the Query as follows:
Are your SFSB eating too much memory ? if you want, you can specify the maximum number of Stateful Session Beans at Container level. You have to change the default maximun (100000 ) in ejb3-aop-interceptors.xml.
Look for the tag "container-pool-conf". It has an element Maximum Size which is the maximum number of SFSB created by the container.
You can specify in your annotations the fetch strategy (fetch = FetchType.LAZY)
HOW TO CREATE A MDB 3.0 SINGLETON ?
EJB3 uses the resource adapter. When using the resource adapter, you need to constrain the number of Sessions: so you set the minimum for the sessions. This will essentially give you a singleton.
You can set the maxSession in your bean with an annotation by adding :
@ActivationConfigProperty(propertyName = "maxSession", propertyValue = "1")
You can add this by default in the server/$/deploy/ejb3-interceptors-aop.xml file
This will set the default for all message driven beans.
Will it work in a cluster too ?
No , if you want a clustered singleton MDB you need to deploy your mdb in
deploy-hasingleton
or create your own clustered singleton deployment.
HOW DO YOU LIMIT THE NUMBER OF RECORDS IN A QUERY WITH EJB 3.0 ?
Use the setMaxResults method from the Java persistence API Query
Example:
@PersistenceContext(unitName="myPersistenceUnit")
private EntityManager em;
private int maxRecords = 100;
public void getNextItems() {
Query q = em.createQuery("select object(o) from Item as o");
q.setMaxResults(maxRecords);
items= q.getResultList();
}
HOW TO SET EJB TIMEOUT PERIOD ?
Use Container managed transactions.
Open jboss-service.xml ( in the conf directory)
Modify the TransactionTimeout attribute as you need.
Note: The timeout attribute is in seconds not in milliseconds ! HOW DO YOU KEEP YOUR EJB CALLBACKS SEPARATED FROM BIZ. METHODS?
If you have need to use callback methods in your EJB Entity Beans then it's likely that your code is a mess! With EJB 3.0 you can add the @EntityListeners annotation to indicate that the callback methods are located in another class.
Example: recall the Note class in the EJB 3.0 tutorial:
and this is the Class holding the listener:
· First you have to remove the default Web application that ships with JBoss (ROOT.war).
· Then deploy your web application taking care to add in your application the file WEB-INF\jboss-web.xml
HOW TO USE JPA FROM A JBOSS WEB APPLICATION ?
The @PersistenceUnit and <persistence-unit-ref> elements can be used within Servlets and JSPs to access EntityManagerFactory only.
You cannot inject EntityManagers directly into web components. Unfortunately, again, Tomcat doesn't support them, so you have to lookup the EntityManagerFactory in JNDI.
To be able to do that you need to set the jboss.entity.manager.factory.jndi.name property in yourpersistence.xml file:
WHAT IS A WEB SERVICE ONE WAY INVOCATION?
@Oneway indicates that the given web method has only an input message and no output. Typically, a oneway method returns the thread of control to the calling application prior to executing the actual business method.
@WebMethod
@Oneway
public void ping()
{
log.info("ping");
feedback = "ok";
}
This Web service expose the method ping as web service and returns the thread of execution before executing the method.
HOW DO I RELOAD DYNAMICALLY MY JSP FROM AN EAR ?
Deploy your Jsp as part of an application deployed in exploded format. (That is create a folder named yourapplication.ear and inside it create a folder yourwebapplication.war).
This is the suggested deployment strategy when you're developing your applications because changes to the jsps take effect immediately and you dont need to redeploy the application nor restart the server
HOW TO AVOID HARDCODING CONNECTION DETAILS IN THE DATASOURCE FILE?
If you don't want to hardcode the Connection details of your Datasource in the -ds.xml file, then you can just specify the Connection as a property:
<connection-url>${database.url}</connection-url>
then you can start-up JBoss passing the parameter database-url with the -D flag. Example:
run.sh -Ddatabase.url=jdbc:mysql://localhost:3306/myschema
You can even set up an additional Connection URL which will be used in case the first one (parameterized) will fail:
<connection-url>${database.url:jdbc:mysql://localhost:3306/myschema}</connection-url>
HOW TO USE CLOB AND BLOB WITH EJB 3 ?
You can use @javax.persistence.Lob annotation to fetch Clob and Blob elements from the Database. Example:
view plaincopy to clipboardprint?
Blob:
org.hibernate.Hibernate.createBlob(byte[] bytes)
org.hibernate.Hibernate.createBlob(InputStream stream, int length)
org.hibernate.Hibernate.createBlob(InputStream stream)
Clob:
org.hibernate.Hibernate.createClob(String string)
org.hibernate.Hibernate.createClob(Reader reader, int length)
HOW TO DEPLOY THE PERSISTENCE UNIT IN THE GLOBAL JNDI ?
By default the persistence unit are available in the java: Context. If you wish to make them available also in theglobal naming Context you have to add two properties to your persistence.xml configuration file:
view plaincopy to clipboardprint?
HOW DO YOU CONNECT A DATASOURCE TO A CLUSTER ?
We'll examine two popular Database: Oracle and MySQL
Oracle cluster (RAC)
Oracle RAC allows multiple computers to run the Oracle RDBMS software simultaneously while accessing a single database thus providing a clustered database.
In order to benefit from Oracle RAC features like fault tolerance and load balancing all you have to do is configuring the connection url with the list of Oracle hosts which belongs to the cluster.
In this example we are configuring our datasource to connect to a RAC made up of host1 and host2:
<connection-url>
jdbc:oracle:thin:@(description=(address_list=(load_balance=on)(failover=on) (address=(protocol=tcp)(host=host1)(port=1521))(address=(protocol=tcp)(host=host2)(port=1521)))(connect_data=(service_name=xxxxsid)(failover_mode=()(method=basic))))
</connection-url>
My SQL cluster
MySQL Cluster is a real-time open source transactional database designed for fast, always-on access to data under high throughput conditions.
In order to achieve load-balancing and failover across MySQL cluster you need to modify your jdbc Connection string adding the "loadbalance" keyword
to do load-balancing across the SQL nodes in MySQL Cluster, you would use a different JDBC connection string with the "loadbalance" keyword added
<connection-url>
jdbc:mysql:loadbalance://host-1,host-2,...host-n/database?loadBalanceBlacklistTimeout=5000
</connection-url>
Notice the "loadBalanceBlacklistTimeout" adds the needed feature that failed connections in a connection pool are put aside for the specified time, and only working connections are utilized. This parameter is essential for proper failover.
HOW TO CHOOSE WHICH COLUMN TO UPDATE WITH EJB CMP ?
If you need to select which columns need update when executing a CMP statement you might use the "updatable" attribute on the @Column annotation.
Setting "updatable" = false will assume that the column is not always included in the SQL update statement.
@Column(name="colname" updatable="false")
At the moment this feature is available only with TopLink JPA.
HOW TO CREATE VIEW OF OBJECTS WITH EJB QL ?
One nice feature of EJB QL is the ability to create new Type safe instances of an Object simply using the new construct. Here is an example:
select new Family(mother, mate, offspr)
from DomesticCat as mother
join mother.mate as mate
left join mother.kittens as offspr
Here we are returning an Object type of Family provided that we have a Constructor Family(mother, mate, offspr) in the class.
This option is useful to create View of Object structures, similarly like RDBMS create view of tables
HOW DO YOU HANDLE A DEADLOCK WITH JBOSS ?
When your application is trying to access the same entity bean within 2 different transaction in a different order a DeadLock can happen. When jBoss detects this situation will issue aorg.jboss.util.deadlock.ApplicationDeadlockException.So you should write your application so that it can retry a transaction if the invocation fails because of theApplicationDeadlockException. Unfortunately, this exception can be deeply embedded within aRemoteException, so you have to search for it in your catch block. For example:
HOW TO ADD CONNECTION PROPERTIES TO YOUR JBOSS DATASOURCE ?
You can include connection properties in your DataSource configuration that will get passed in the DriverManager.getConnection(props) call. Here's how to do it:
Local Datasource
<local-tx-datasource>
...
<connection-property name="char.encoding">UTF-8</connection-property>
<!-- Tells an Oracle 10g driver to properly implement clobs. -->
<connection-property name="SetBigStringTryClob">true</connection-property>
..
</local-tx-datasource>
XA Datasource
<xa-datasource-property name="ConnectionProperties">SetBigStringTryClob=true</xa-datasource-property>
HOW DO I ACCESS THE SPECIFIC DRIVER CONNECTION WITH JBOSS ?
If you need to access to the specific driver connection (for example the OracleConnection instead of the java.sql.Connection) then you need to use the WrappedConnection object and get its underlying connection:
Or another way, using reflection:
HOW TO CHANGE JBOSS CONNECTION POOL SIZE DYNAMICALLY ?
Supposing you need to change at runtime the size of your datasource named "CatalogDB", then you can use twiddle command (or modify it manually from the JMX-Console)
$ twiddle.sh set jboss.jca:name=CatalogDB,service=ManagedConnectionPool MaxSize 300
This sets the Max ConnectionPool size to 300
HOW TO DEPLOY A HAR FILE INSIDE AN EAR ?
Hibernate archives can be deployed as top level packages or can be deployed as a component of an EAR file. Since Hibernate archives are not a standard J2EE deployment type, we need to declare them in the jboss-app.xml file of an EAR file to use them that context.
This is done with a module/har element as shown in the following example.
With this, a Hibernate archive can be deployed along side a WAR or EAR file in any EAR file.
HOW CAN I RETRIEVE THE ID OF A TRANSACTION STARTED BY JBOSS ?
Sometimes it an be useful for debugging purpose to retrieve the id of a transaction; one typical scenario could be a transaction started by an EJB deployed as CMT.
Most application server provide some methods to obtain this information : with JBoss you can use the methodcom.arjuna.ats.jta.TransactionManager.transactionManager().getTransaction()It's not portable, however should you need it......
HOW TO USE MULTIPLE DATABASE IN PERSISTENCE.XML?
The Java Persistence API allows you to define multiple persistence units, each of which can map to a separate database. If you look at the persistence.xml file :
@PersistenceContext(unitName="sample-db1",
.TRANSACTION)
private EntityManager em1;
@PersistenceContext(unitName="sample-db2",
.TRANSACTION)
private EntityManager em2;
HOW TO USE AN ENV VARIABLE IN YOUR PERSISTENCE.XML ?
Simply wrap your env variable in into ${variable}
Example:
then pass the variable to the runs.h script
run.sh -Dmyds=$myds
HOW TO CREATE AN INDEX ON YOUR ENTITY BEANS?
You can use the @Index annotation with EJB3 in Hibernate 3.2.X to create indexes automatically when an entity is deployed.
This annotation can be put either on the Table annotation or directly on the entity property.
Examples:
@javax.persistence.Table(name = "items")
@org.hibernate.annotations.Table(appliesTo = "items", indexes = { @Index(name = "INDX", columnNames = { "idItem" }) })
@Index(name = "IDX", columnNames = { "idItem" })
public String getIdItem() {
return timestamp;
}
HOW TO CONNECT TO A DATASOURCE FROM A REMOTE CLIENT?
If you want to connect to your JBoss Connection Pool from a remote client ( that is a client that is not deployed on JBoss) you need to tell JBoss NOT to bind the Datasource under the "java:/"
namespace.
As a matter of fact this restricts the lookup to the same VM as the JBoss server.
Simply use tag <use-java-context>false</use-java-context> in your -ds.xml file
This is a sample Datasource file for mysql configured to accept remote client access
HOW TO DEPLOY A DATASOURCE IN JBOSS AT APPLICATION LEVEL ?
Do you need to deploy your DataSource along with your Enterprise Application ? (that is without having to install it in the "deploy" dir )
So, In your EAR file, create a jboss-app.xml file containing the following:
Code:
<jboss-app>
<module>
<service>myapp-ds.xml</service>
</module>
</jboss-app>
Place this jboss-app.xml in the META-INF folder of your EAR. And place the -ds.xml at the root of the EAR.
HOW TO DEPLOY AN APPLICATION REMOTELY WITH JBOSS AS ?
If you are running a JBoss AS release 5.1.0, there's a web application named admin-console which is going to replace the jmx-console for monitoring the application server.
You can launch it this way:
http://xx.xx.xx.xx/admin-console(Replace the xx.xx.xx.xx with your IP Address)
Now, in order to deploy an application select in the left tree view the type of Application you wish to deploy (Web, EJB or other) and click on the folder node
In the central frame just select "Add a new resource" and upload your application.
HOW TO FORCE JBOSS TO DEPLOY THE EJB FIRST IN AN EAR ?
Sometimes the order of deployed units, in an Enterprise application matters. For example, if you are deploying an EAR which is made up of a WEB application an EJB, it can be necessary that the EJB application is deployed at first.
A typical scenario is a Web application uses ServletContextListeners. If the ServletContextListener tries to access the EJB, as soon as the Web component is deployed, a NamingException might be the outcome of it, because the EJB hasn't been still bound in the JNDI.
The quick fix to it is adding a ContextComparator in conf\bootstrap\deployers.xml file:
HOW TO ADD A CUSTOM JBOSS ARCHIVE IN AN EAR ?
JBoss custom archives (like .sar or .har) are not recognized by the application.xml descriptors, so in order to deploy them in an EAR you have to declare them in jboss-app.xml. This file is located in the META-INF folder of your EAR.
For example, if you want to include an Hibernate Archive (HAR), you have to provide the following jboss-appl.xml configuration:
HOW TO RESTRICT ACCESS TO JBOSS WEB APPLICATION BY IP OR HOST?
You can create easily Access control list based on the IP address/Host name using Tomcat Valves. A Valveelement represents a component that will be inserted into the request processing pipeline for the associated Catalina container.
The Remote Address Filter allows you to compare the IP address of the client that submitted this request against one or more regular expressions, and either allow the request to continue or refuse to process the request from this client.
For example, to block all requests coming in except those from the local host:
<Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127.0.0.1" />
The Remote Host filter is much like the Remote Address Valve, except it allows you to compare the remote host address of the client that submitted this request instead of the fixed IP address. A Remote Host filter can be associated with a Tomcat Engine , Host, or Context container. An example entry using the org.apache.catalina.valves.RemoteHostValve can be found in the following code snippet.
<Valve className="org.apache.catalina.valves.RemoteHostValve" deny="badhost*"/>
This valve entry denies access to the assigned container for the host whose name starts with badhost. If I assign this valve entry to the host container localhost, then all clients beginning with badhost will see a 403 - Forbidden page.
THE JNDI.PROPERTY PITFALL
A piftall which is sometimes reported in JBoss forum is that JBoss refuses to start up correclty after an ear deployment unit has been added.
javax.naming.CommunicationException: Failed to connect to server localhost:1099 [Root exception is javax.naming.ServiceUnavailableException: Failed to connect to server localhost:1099 [Root exception is java.net.ConnectException: Connection refused]
If the problem disappear when you undeploy the ear deployment unit it is likely that you have added a jndi.properties file in the ear package.
The file jndi.properties is generally used when you connect to jBoss environment from remote resources.
#jboss JNDI properties
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://localhost:1099
java.naming.factory.url.pkgs=org.jnp.interfaces
Adding to the Ear deployment interfers with JBoss binding process, so JBoss refuses to start-up. Get rid of it and the problem will disappear!
HOW TO DEPLOY AN APPLICATION TEMPORARLY WITH JBOSS ?
One way to do it, is using the jboss.system:service=MainDeployer Mbean.
In practice, if you deploy an application using this MBean your application will be temporarlydeployed on the application server. Why temporarly ? because it's not copied into the "deploy" directory but simply deployed where it is.
The location of the application is not persisted, JBoss keeps in memory the location of the application, so at server shutdown the application will exit from JBoss.
One way to reach this MBean is via the twiddle utility:
twiddle invoke "jboss.system:service=MainDeployer" deploy C:\TempApp.war
Here the web application TempApp.war is deployed from C:\ . Until JBoss is running.
HOW TO DEPLOY AN EXPLODED APPLICATION ON JBOSS SAFELY ?
Have you ever tried to deploy a large application as exploded directory ? one common issue arises from the fact that if JBoss reads the deployment descriptors before the whole application is deployed. JBoss usually complains that the application was deployed as incomplete application.
This can happen for example if you are transferring the files on a slow network, or if the application is quite big.
One workaround is not to copy files but rather moving
mv mylargeapp.ear $JBOSS_HOME/server/default/deploy
why this should work ? because on most OS mv is treated as an atomic operation, that is, files are made available only when the transfer is completed (like for example when we issue a commit to the database).
I cannot guarantee that this will work on all situations (for example on the HP docs I have read that mv is atomic only within the same filesystem. Across filesystems mv is not atomic.)...however it's worth a try, isn't it ??
HOW TO INJECT SYSTEM PROPERTIES INTO JBOSS ?
One cool way to add a list of System properties to JBoss is the Properties MBean Service.
In the deployment folder look for "properties-service.xml". (if you don't have it in your release you can create it at any time) :
Now add your properties either in the URLList Attribute or in the Properties Attribute:
view plaincopy to clipboardprint?
As you can see the The "URLList" is a comma-separated list of URL strings from which to load properties file-formatted content while the "Properties" is a specification of multiple property name=value pairs
Now you can access your properties with standard:
System.getProperty("property1");
HOW TO RUN 2 JBOSS ON THE SAME COMPUTER ?
Running 2 JBoss instances on the same computer requires changing default ports in order to avoid conflicts.
· Open /deploy/jbossweb-tomcat55.sar/server.xml and change port 8080
· Open conf/jboss-service.xml and change ports 8083,1099,1098,4444,4445
· Open deploy/jms/uil2-service.xml and change port 8093
Hint: An easier solution would be to add a virtual address to your pc and simply bind each jboss to a different address with the -b option
HOW DO I CHANGE MULTICAST ADDRESS OF JBOSS CLUSTER ?
Since JBoss AS 4.0.3, the jboss.partition.udpGroup property can be used to change the multicast address of JBoss cluster. A command line option can be used also:
$ run.sh -c all --udp 233.3.4.5
HOW TO CREATE A CUSTOM JBOSS CONFIGURATION ?
JBoss ships with 3 configurations:
· default: the standard jBoss standalone configuration
· all: same as standard but with Clustering enabled
· minimal: barebones JMX services
However you re not limited to the existing configurations: you can create a custom server configuration that suits your needs best.
The easiest way to do it is starting from one existing configuration and adjust for your needs.
for example if you need a standard JBoss configuration but without JMS support, simply copy the "default" configuration and remove the "deploy/jms" folder which contains all the JMS related services.
The name of the new directory you created is the name of the server configuration. You will need to pass the server configuration name to instruct JBoss to use the new configuration. For example, if your new configuration directory is named "myconfig" then you would need to start JBoss using "run -c myconfig".
HOW TO CONFIGURE LOG4J IN YOUR EAR ?
Have you got exceptions when tried to configure log4j at application level ? this is due to the fact that JBoss ships already with log4j classes: you need to isolate the classes from other deployments. Without isolation, you can see common errors like ClassCastException, IllegalAccessErrors, VerifyErrors and in general, strange behavior.
Here's how to do it:
Create a log4j.properties file and package it with your application and make it visible to JBoss classpath (see image at the bottom). The log4j.properties has just a minimal content:
log4j.logger.com.sample=TRACE
Within your application you need to add the appropriate version of log4j jar (this is important because you will have to ensure that log4j initializes separately for your application and picks up the log4j.properties file). Place this log4j jar file in the lib folder of your EAR (as depicted in the picture).
Finally you need to enable classloader isolation for your application. In order to achieve classloader isolation you need to add an entry in jboss-app.xml file and place it in the META-INF folder of the EAR. The jboss-app.xml looks like:
This is how your application EAR should look like:
HOW DO I CHANGE THE DEFAULT LIB DIRECTORY IN AN EAR FILE?
Supposing you have an Enterprise application which has been packaged in an ear and its libraries are placed in another folder like Weblogic's APP-INF/lib. How can I deploy this application to JBoss ?
You might resort to the "library-directory" parameter of jboss-app.xml
Here's an example:
<application>
<display-name>My Application</display-name>
<module>
<web>
<web-uri>myapp.war</web-uri>
<context-root>/myapp</context-root>
</web>
</module>
<module>
<ejb>myapp.jar</ejb>
</module>
<library-directory>APP-INF/lib</library-directory>
</application>
HOW TO CONFIGURE JBOSS TO DISABLE HOT DEPLOYMENT ?
For performance reason you might want to disable JBoss hot deployment's feature.
Simply open the conf/jboss-service.xml file and find the line:
<!-- A flag to disable the scans -->
<attribute name="ScanEnabled">true</attribute>
Simply change to false and hot deployment will be disabled.
If on the other hand you simply want to reduce scan polling time, look for a few lines before:
<!-- Frequency in milliseconds to rescan the URLs for changes -->
<attribute name="ScanPeriod">5000</attribute>
This will set the scan time (in milliseconds)
To Deploy:Lock & Edit -> Deployments -> Install -> specify location of your WAR/EAR file -> Next -> Finish -> Activate Changes
To Test:Deployments -> navigate to your application -> select checkbox next to your application -> Start -> Servicing all requests -> Yes -> again navigate to your application -> click on your application -> Testing....
A data source is a Java Naming and Directory Interface (JNDI) object used to obtain a connection from a connection pool to a database. In order to create a DataSource (so that you can use JDBC connectivity) you need to create a file ending with -ds.xml under the "deploy" directory of your server.
The default Datasource file The default data source configured with JBoss 4.0 is the HypersonicDB data source.
Here's the hsqldb-ds.xml that is shipped with jboss :
- <?xml version="1.0" encoding="UTF-8"?>
- <datasources>
- <local-tx-datasource>
- <jndi-name>DefaultDS</jndi-name>
- <connection-url>jdbc:hsqldb:${jboss.server.data.dir}${/}hypersonic${/}localDB</connection-url>
- <driver-class>org.hsqldb.jdbcDriver</driver-class>
- <user-name>sa</user-name>
- <password></password>
- <min-pool-size>5</min-pool-size>
- <max-pool-size>20</max-pool-size>
- <idle-timeout-minutes>0</idle-timeout-minutes>
- <track-statements/>
- <security-domain>HsqlDbRealm</security-domain>
- <prepared-statement-cache-size>32</prepared-statement-cache-size>
- <metadata>
- <type-mapping>Hypersonic SQL</type-mapping>
- </metadata>
- <depends>jboss:service=Hypersonic,database=localDB</depends>
- </local-tx-datasource>
- <mbean code="org.jboss.jdbc.HypersonicDatabase"
- name="jboss:service=Hypersonic,database=localDB">
- <attribute name="Database">localDB</attribute>
- <attribute name="InProcessMode">true</attribute>
- </mbean>
- </datasources>
As you can see from this file, JDBC connectivity uses Connection pools to dispatch Connections. The initial size and the max size of the Connection pool can be configured with <min-pool-size> and <max-pool-size>.
With <idle-timeout-minutes> you can indicate the maximum time a connection may be idle before being closed and returned to the pool. If not specified it's 15 minutes.
<track-statements/> is a debugging feature: it checks that all statements are closed when the connection is returned to the pool: remember to disable it in production environment.
<security-domain> tells to use the security domain defined in conf/login-config.xml : in our case:
- <application-policy name = "HsqlDbRealm">
- <authentication>
- <login-module code = "org.jboss.resource.security.ConfiguredIdentityLoginModule"
- flag = "required">
- <module-option name = "principal">sa</module-option>
- <module-option name = "userName">sa</module-option>
- <module-option name = "password"></module-option>
- <module-option name = "managedConnectionFactoryName">jboss.jca:service=LocalTxCM,name=DefaultDS</module-option>
- </login-module>
- </authentication>
- </application-policy>
<prepared-statement-cache-size> is the number of prepared statements per connection to be kept open and reused in subsequent requests. They are stored in a LRU cache. The default is 0 (zero), meaning no cache.
Enterprise datasources
I) Local Datasource This is a sample Oracle local datasource configuration: a local DataSource is one that does not support two phase commit using a java.sql.Driver.
- <datasources>
- <local-tx-datasource>
- <jndi-name>OracleDS</jndi-name>
- <connection-url>jdbc:oracle:thin:@youroraclehost:1521:yoursid</connection-url>
- <driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
- <user-name>x</user-name>
- <password>y</password>
- <min-pool-size>5</min-pool-size>
- <max-pool-size>100</max-pool-size>
- <query-timeout>60</query-timeout>
- <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
- <metadata>
- <type-mapping>Oracle9i</type-mapping>
- </metadata>
- </local-tx-datasource>
- </datasources>
Notice the <query-timeout> tag which configures the maximum of seconds before a query times out ( avaliable since Jboss 4.0.3). The <exception-sorter-class-name> is used to Check the Oracle error codes and messages for fatal errors.
Remember: In order to use an Oracle datasource you need to put the jdbc driver in jBoss's server's lib directory.
II) XA Datasource This is a sample XA Datasource: XA DataSources support two phase commit using a javax.sql.XADataSource
- <datasources>
- <xa-datasource>
- <jndi-name>XAOracleDS</jndi-name>
- <track-connection-by-tx></track-connection-by-tx>
- <isSameRM-override-value>false</isSameRM-override-value>
- <xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
- <xa-datasource-property name="URL">jdbc:oracle:oci8:@tc</xa-datasource-property>
- <xa-datasource-property name="User">scott</xa-datasource-property>
- <xa-datasource-property name="Password">tiger</xa-datasource-property>
- <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
- <no-tx-separate-pools></no-tx-separate-pools>
- <metadata>
- <type-mapping>Oracle9i</type-mapping>
- </metadata>
- </xa-datasource>
- <mbean code="org.jboss.resource.adapter.jdbc.vendor.OracleXAExceptionFormatter"
- name="jboss.jca:service=OracleXAExceptionFormatter">
- <depends optional-attribute-name="TransactionManagerService">jboss:service=TransactionManager</depends>
- </mbean>
- </datasources>
Notice the <isSameRM-override-value> set to false to fix problems with Oracle. The element <track-connection-by-tx/> can be omitted on JBoss 5 where it's enabled by default.
At last, the <no-tx-separate-pools> means that Oracles XA datasource cannot reuse a connection outside a transaction once enlisted in a global transaction and vice-versa
Configuring your datasource to connect to Oracle RAC Oracle RAC allows multiple computers to run the Oracle RDBMS software simultaneously while accessing a single database thus providing a clustered database.
In order to benefit from Oracle RAC features like fault tolerance and load balancing all you have to do is configuring the connection url with the list of Oracle hosts which belongs to the cluster.
In this example we are configuring our datasource to connect to a RAC made up of host1 and host2:
<connection-url>jdbc:oracle:thin:@(description=(address_list=(load_balance=on)(failover=on)(address=(protocol=tcp)(host=host1)(port=1521))(address=(protocol=tcp)(host=host2)(port=1521)))(connect_data=(service_name=xxxxsid)(failover_mode=()(method=basic))))
</connection-url>
Where to put Datasources if JBoss is clustered ? In a clustered setup, position the file -ds.xml in the JBOSS_HOME\server\all\farm\ directory, it will be replicated on all members of the cluster.
Monitoring your Connection Pool Each datasource translates into several MBeans that you can interact with in the JMX Console. All the datasource-related objects are in the jboss.jca domain. You can find them by searching through the JMX Console page, or by using jboss.jca:* as the query filter.
Supposing you want to monitor your OracleDS datasource from the previous example: you could use a more specific filter, such as jboss.jca:name=OracleDS,*, to see only the OracleDS entries. In either case, four MBeans will be related to the OracleDS datasource:
· name=OracleDS ,service=DataSourceBinding
· name=OracleDS ,service=LocalTxCM
· name=OracleDS ,service=ManagedConnectionFactory
· name=OracleDS ,service=ManagedConnectionPool
While each plays a critical role in providing the datasource functionality in JBoss, you are most likely to need to interact with the connection pool. Click the connection pool MBean to expose the management attributes and operations.
In our datasource file we've been using specified a minimum connection pool size of 2 and a maximum pool size of 10. You'll see those values reflected in the MinSize and MaxSize attributes. You can change the values in the running server by adjusting the values and clicking Apply Changes.
Setting the values here affects the connection pool only in memory. To change the configuration permanently, update the datasource file. Try setting the pool sizes there. When you save the file, JBoss will redeploy the datasource and the new pool sizes will be displayed when you reload the page.
You might occasionally want to adjust the pool size to account for usage; you are more likely to be curious how much of the connection pool is being used. The ConnectionCount attribute shows how many connections are currently open to the database. However, open connections are not necessarily in use by application code. The InUseConnectionCount attribute shows how many of the open connections are in use. Viewing the statistic from the other direction, AvailableConnectionCount shows how much room is left in the pool.
Finally, the MBean has several statistics that track connection pool usage over the pool's lifetime. ConnectionCreatedCount and Connection-DestroyedCount keep running totals of the number of connections created and destroyed by the pool. If IdleTimeout is greater than 0, connections will eventually timeout, be destroyed, and be replaced by fresh connections. This will cause the created and destroyed counts to rise constantly. The MaxConnectionsInUseCount attribute keeps track of the highest number of connections in use at a time.
If you notice anything awkward in the connection pool, or you just want to reset the statistics, you can flush the connection pool using the flush operation on the MBean. This will cause a new connection pool to be created, abandoning the previous connection pool.
A Graph is worth 100 words or so ! if you read our recent Recipes (and we really appreciate that you are a faithful visitor !) then you know that JBoss Web Console is able to show you graphically the value of many MBeans attribute (those who have a numeric value).
So look for the MBean "name=OracleDS ,service=ManagedConnectionPool", there you can choose to add a graph to any of the attributes: in this picture you can see a sample graph of the JMX Attribute Connection Count
How do I configure a Queue/Topic to work in a cluster?
Just set the Clustered attribute to "true" in your Queue/Topic definition. Here's a Queue example:
- <mbean code="org.jboss.jms.server.destination.QueueService"
- name="jboss.messaging.destination:service=Queue,name=SampleQueue"
- xmbean-dd="xmdesc/Queue-xmbean.xml">
- <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
- <depends>jboss.messaging:service=PostOffice</depends>
- <attribute name="Clustered">true</attribute>
- </mbean>
How to configure a queue in jboss ?
Simply drop a file ending in -service.xml in the deploy folder, containing the Queue definition.
<server>
<mbean code="org.jboss.mq.server.jmx.Queue"
name="jboss.mq.destination:service=Queue,name=MyQueue">
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>
</server>
Verify in the Jmx-console under the jboss.mq.destination tab that the Queue is correctly deployed.
How to a dump of jndi tree with jmx console ?
Quite easy. Open your JMX console:
http://localhost:8080/jmx-console
and look for the Service "JNDIView" (it's under the object name jboss)
Now simply find the method "list", click it et voilà !
without writing a line of code but simply using the JMX Console
How to call a stored procedure with hibernate ?
JBoss recipe of the day
Supposing you have the following Oracle Stored procedure:
CREATE FUNCTION agenda RETURN SYS_REFCURSOR
AS
my_cursor SYS_REFCURSOR;
BEGIN
OPEN my_cursor FOR
SELECT id,person_name,person_surname,person_address
FROM Person;
RETURN my_cursor;
END;
Invoking it from Hibernate requires mapping the Stored Procedure in the Person class.
- <sql-query name="SP_agenda" callable="true">
- <return alias="ev" >
- <return-property name="id" column="id"/>
- <return-property name="name" column="person_name"/>
- <return-property name="surname" column="person_surname"/>
- <return-property name="address" column="person_address"/>
- </return>
- { ? = call agenda() }
- </sql-query>
- Query query = session.getNamedQuery("SP_agenda");
- List results = query.list();
Supposing you have to fetch a large resultset and update the single objects. By using the standard Query Object you would retrieve the whole set of Objects in Memory:
- Query q = session.createQuery("from ABC");
- List l = q.list();
If you need to operate on an online cursor, then you can use the ScrollableResults:
- Session session = sessionFactory.openSession();
- Transaction tx = session.beginTransaction();
- ScrollableResults itemCursor =
- session.createQuery("from Account").scroll();
- int count=0;
- while ( itemCursor.next() ) {
- Account a = (Account) itemCursor.get(0);
- modifyObject(a);
- if ( ++count % 100 == 0 ) {
- session.flush();
- session.clear();
- }
- }
- tx.commit();
- session.close();
Notice the counter which flushes the objects every 100 items to free memory.
HOW DO YOU BIND THE ID OF AN ENTITY EJB 3.0 TO A SEQUENCE ?
You can define a SequenceGenerator which points to the DB Sequence. Then you link your Id to the SequenceGenerator through the @GeneratedValue annotation. Example:
- @Entity
- @Table(name="EJB_TASK_VIEWS")
- public class View implements Serializable {
- @Id()
- @GeneratedValue( strategy=GenerationType.SEQUENCE, generator="viewSequence" ) // name of the generator
- @SequenceGenerator( name="viewSequence", sequenceName="VIEW_SEQUENCE")
- public Integer getId() {
- return id;
- }
- public void setId(Integer id) {
- this.id = id;
- }
- .....
- }
Retrieving a large amount of data and returning them to the client can be quite paniful....however with EJB 3 it's quite easy to paginate a large resultset: for example supposing you want to retrieve only the first "page" of 100 Users:
- List <Users> tasklist = em.createNamedQuery("findUsersByRole")
- .setParameter("role", role)
- .setMaxResults(100)
- .setFirstResult(0)
- .getResultList();
You could further optimize the query with "setFetchSize" which sets a fetch size for the underlying JDBC query.
I have tested with a (rather complex) resultset of 100.000 records on JBoss AS 5.0 + Oracle 10.1. Retrieving the full Resultset took about 12 seconds (not too bad, with plain SQL it took about 7.5 seconds). Retrieving the single page of 100 records took just 0.5 seconds.
HOW DO I LOOKUP FROM A WEB APPLICATION AN EJB DEPLOYED STANDALONE ?
Supposing you have deployed an Enterprise Java Bean as stand alone application and you want to access it from your Servlet / Jsp layer. What you need to do is adding the appropriate references to your web.xml and jboss-web.xml.
So if you have an EJB named "HelloBean" add to your web.xml
- <ejb-ref>
- <ejb-ref-name>HelloBean</ejb-ref-name>
- <ejb-ref-type>session</ejb-ref-type>
- <home>test.HelloBeanHome</home>
- <remote>test.HelloBeanRemote</remote>
- </ejb-ref>
Then modify jboss-web.xml by adding:
- <ejb-ref>
- <ejb-ref-name>HelloBean</ejb-ref-name>
- <jndi-name>HelloBean</jndi-name>
- </ejb-ref>
Now you can safely lookup your EJB from your Servlet:
Context ic = new InitialContext();
Object ejbHome = ic.lookup("java:comp/env/HelloBean");
HOW TO USE NATIVE QUERIES WITH EJB 3.0 ?
You can use the createNativeQuery method of the EntityManager interface to create a
dynamic query using SQL as follows:
- Query q = em.createNativeQuery("SELECT p1.last_name, t1.title_name, t2.title_name
- FROM person p1 INNER JOIN title t1 ON p1.title_1 = t1.title_abbrev,
- person p2 INNER JOIN title t2 ON p2.title_2 = t2.title_abbrev",
- sample.Person.User.class);
- return q.getResultList();
here we pass two parameters to the method createNativeQuery: the first is the SQL and
the second is the Entity which will be populated.
What about if your query returns more than one Entity ? You have to use the @SqlResultSetMapping
which will be passed to the method instead of the Entity:
At first we define the mapping:
@SqlResultSetMapping(name = "MyMapping",
entities = @EntityResult(entityClass = sample.Person.User.class))
then we can specify the mapping in the Query as follows:
- Query q = em.createNativeQuery("SELECT p1.last_name, t1.title_name, t2.title_name
- FROM person p1 INNER JOIN title t1 ON p1.title_1 = t1.title_abbrev,
- person p2 INNER JOIN title t2 ON p2.title_2 = t2.title_abbrev",
- "MyMapping");
Are your SFSB eating too much memory ? if you want, you can specify the maximum number of Stateful Session Beans at Container level. You have to change the default maximun (100000 ) in ejb3-aop-interceptors.xml.
Look for the tag "container-pool-conf". It has an element Maximum Size which is the maximum number of SFSB created by the container.
- <container-pool-conf>
- <MaximumSize>100</MaximumSize>
- </container-pool-conf>
You can specify in your annotations the fetch strategy (fetch = FetchType.LAZY)
- @Entity
- @Table(name = "PET")
- public class Pet implements Serializable {
- private long id;
- private Zoo zoo;
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- @Column(name = "ID")
- public long getId() {
- return id;
- }
- public void setId(long id) {
- this.id = id;
- }
- @ManyToOne(fetch = FetchType.LAZY)
- @JoinColumn(name="ZOO_ID")
- public Zoo getZoo() {
- return zoo;
- }
- public void setZoo(Zoo zoo) {
- this.zoo = zoo;
- }
- }
- @Entity
- @Table(name = "ZOO")
- public class Zoo implements Serializable {
- private long id;
- @Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
- @Column(name = "ID")
- public long getId() {
- return id;
- }
- public void setId(long id) {
- this.id = id;
- }
- }
HOW TO CREATE A MDB 3.0 SINGLETON ?
EJB3 uses the resource adapter. When using the resource adapter, you need to constrain the number of Sessions: so you set the minimum for the sessions. This will essentially give you a singleton.
You can set the maxSession in your bean with an annotation by adding :
@ActivationConfigProperty(propertyName = "maxSession", propertyValue = "1")
You can add this by default in the server/$/deploy/ejb3-interceptors-aop.xml file
- <annotation expr="!class(@org.jboss.annotation.ejb.DefaultActivationSpecs)">
- @org.jboss.annotation.ejb.DefaultActivationSpecs (value={@~ActivationConfigProperty(propertyName = "maxSession", propertyValue = "1")})
- </annotation>
This will set the default for all message driven beans.
Will it work in a cluster too ?
No , if you want a clustered singleton MDB you need to deploy your mdb in
deploy-hasingleton
or create your own clustered singleton deployment.
HOW DO YOU LIMIT THE NUMBER OF RECORDS IN A QUERY WITH EJB 3.0 ?
Use the setMaxResults method from the Java persistence API Query
Example:
@PersistenceContext(unitName="myPersistenceUnit")
private EntityManager em;
private int maxRecords = 100;
public void getNextItems() {
Query q = em.createQuery("select object(o) from Item as o");
q.setMaxResults(maxRecords);
items= q.getResultList();
}
HOW TO SET EJB TIMEOUT PERIOD ?
Use Container managed transactions.
Open jboss-service.xml ( in the conf directory)
- <mbean code="com.arjuna.ats.jbossatx.jta.TransactionManagerService"
- name="jboss:service=TransactionManager">
- <attribute name="TransactionTimeout">300</attribute>
- <attribute name="ObjectStoreDir">${jboss.server.data.dir}/tx-object-store</attribute>
- </mbean>
Modify the TransactionTimeout attribute as you need.
Note: The timeout attribute is in seconds not in milliseconds ! HOW DO YOU KEEP YOUR EJB CALLBACKS SEPARATED FROM BIZ. METHODS?
If you have need to use callback methods in your EJB Entity Beans then it's likely that your code is a mess! With EJB 3.0 you can add the @EntityListeners annotation to indicate that the callback methods are located in another class.
Example: recall the Note class in the EJB 3.0 tutorial:
- import java.io.Serializable;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.Id;
- import javax.persistence.Table;
- @Entity
- @Table(name = "NOTE")
- @EntityListeners(NoteCallbackListener.class)
- public class Note implements Serializable {
- long noteId;
- String text;
- String actor;
- String attachment;
- @Id
- @GeneratedValue
- public long getNoteId() {
- return noteId;
- }
- public void setNoteId(long noteId) {
- this.noteId = noteId;
- }
- public String getActor() {
- return actor;
- }
- public void setActor(String actor) {
- this.actor = actor;
- }
- public String getAttachment() {
- return attachment;
- }
- public void setAttachment(String attachment) {
- this.attachment = attachment;
- }
- public String getText() {
- return text;
- }
- public void setText(String text) {
- this.text = text;
- }
- }
and this is the Class holding the listener:
- import javax.persistence.PreRemove;
- import javax.persistence.PostRemove;
- import javax.persistence.PreUpdate;
- import javax.persistence.PostUpdate;
- import javax.persistence.PostLoad;
- import javax.persistence.PrePersist;
- import javax.persistence.PostPersist;
- public class NoteCallbackListener
- {
- @PrePersist
- public void doPrePersist(Note note)
- {
- System.out.println("doPrePersist: About to create Note: " + Note.getId());
- }
- @PostPersist
- public void doPostPersist(Object Note)
- {
- System.out.println("doPostPersist: Created Note: " + ((Note)Note).getId()));
- }
- @PreRemove
- public void doPreRemove(Note note)
- {
- System.out.println("doPreRemove: About to delete Note: " + Note.getId());
- }
- @PostRemove
- public void doPostRemove(Note note)
- {
- System.out.println("doPostRemove: Deleted Note: " + Note.getId());
- }
- @PreUpdate
- public void doPreUpdate(Note note)
- {
- System.out.println("doPreUpdate: About to update Note: " + Note.getId());
- }
- @PostUpdate
- public void doPostUpdate(Note note)
- {
- System.out.println("doPostUpdate: Updated Note: " + Note.getId());
- }
- @PostLoad
- public void doPostLoad(Note note)
- {
- System.out.println("doPostLoad: Loaded Note: " + Note.getId());
- }
· First you have to remove the default Web application that ships with JBoss (ROOT.war).
· Then deploy your web application taking care to add in your application the file WEB-INF\jboss-web.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <jboss-web>
- <context-root>/</context-root>
- </jboss-web>
HOW TO USE JPA FROM A JBOSS WEB APPLICATION ?
The @PersistenceUnit and <persistence-unit-ref> elements can be used within Servlets and JSPs to access EntityManagerFactory only.
You cannot inject EntityManagers directly into web components. Unfortunately, again, Tomcat doesn't support them, so you have to lookup the EntityManagerFactory in JNDI.
To be able to do that you need to set the jboss.entity.manager.factory.jndi.name property in yourpersistence.xml file:
- <persistence
- <persistence-unit name="unit1">
- <provider>org.hibernate.ejb.HibernatePersistence</provider>
- <jta-data-source>java:/MySqlDS</jta-data-source>
- <properties>
- <property name="hibernate.dialect"
- value="org.hibernate.dialect.MySQLDialect"/>
- <property name="jboss.entity.manager.factory.jndi.name" value="java:/MyEntityManagerFactory"/>
- </properties>
- </persistence-unit>
- </persistence>
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- InitialContext ctx;
- try {
- ctx = new InitialContext();
- EntityManagerFactory factory = (EntityManagerFactory)ctx.lookup("java:/MyEntityManagerFactory");
- System.out.println("Factory is "+factory);
- } catch (NamingException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
WHAT IS A WEB SERVICE ONE WAY INVOCATION?
@Oneway indicates that the given web method has only an input message and no output. Typically, a oneway method returns the thread of control to the calling application prior to executing the actual business method.
@WebMethod
@Oneway
public void ping()
{
log.info("ping");
feedback = "ok";
}
This Web service expose the method ping as web service and returns the thread of execution before executing the method.
HOW DO I RELOAD DYNAMICALLY MY JSP FROM AN EAR ?
Deploy your Jsp as part of an application deployed in exploded format. (That is create a folder named yourapplication.ear and inside it create a folder yourwebapplication.war).
This is the suggested deployment strategy when you're developing your applications because changes to the jsps take effect immediately and you dont need to redeploy the application nor restart the server
HOW TO AVOID HARDCODING CONNECTION DETAILS IN THE DATASOURCE FILE?
If you don't want to hardcode the Connection details of your Datasource in the -ds.xml file, then you can just specify the Connection as a property:
<connection-url>${database.url}</connection-url>
then you can start-up JBoss passing the parameter database-url with the -D flag. Example:
run.sh -Ddatabase.url=jdbc:mysql://localhost:3306/myschema
You can even set up an additional Connection URL which will be used in case the first one (parameterized) will fail:
<connection-url>${database.url:jdbc:mysql://localhost:3306/myschema}</connection-url>
HOW TO USE CLOB AND BLOB WITH EJB 3 ?
You can use @javax.persistence.Lob annotation to fetch Clob and Blob elements from the Database. Example:
view plaincopy to clipboardprint?
- @Entity
- public class SampleEntity implements Serializable
- {
- private Long id;
- private Blob blob;
- private Clob clob;
- @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
- public Long getId()
- {
- return id;
- }
- public void setId(Long id)
- {
- this.id = id;
- }
- @Lob @Basic(fetch = FetchType.EAGER)
- public Blob getBlob()
- {
- return blob;
- }
- public void setBlob(Blob blob)
- {
- this.blob = blob;
- }
- @Lob @Basic(fetch = FetchType.EAGER)
- public Clob getClob()
- {
- return clob;
- }
- public void setClob(Clob clob)
- {
- this.clob = clob;
- }
- }
Blob:
org.hibernate.Hibernate.createBlob(byte[] bytes)
org.hibernate.Hibernate.createBlob(InputStream stream, int length)
org.hibernate.Hibernate.createBlob(InputStream stream)
Clob:
org.hibernate.Hibernate.createClob(String string)
org.hibernate.Hibernate.createClob(Reader reader, int length)
HOW TO DEPLOY THE PERSISTENCE UNIT IN THE GLOBAL JNDI ?
By default the persistence unit are available in the java: Context. If you wish to make them available also in theglobal naming Context you have to add two properties to your persistence.xml configuration file:
view plaincopy to clipboardprint?
- <persistence>
- <persistence-unit name="manager1">
- <jta-data-source>java:/MySQLDS</jta-data-source>
- <properties>
- <property name="jboss.entity.manager.jndi.name" value="java:/Manager1"/>
- <property name="jboss.entity.manager.factory.jndi.name" value="java:/Manager1Factory"/>
- </properties>
- </persistence-unit>
- </persistence>
HOW DO YOU CONNECT A DATASOURCE TO A CLUSTER ?
We'll examine two popular Database: Oracle and MySQL
Oracle cluster (RAC)
Oracle RAC allows multiple computers to run the Oracle RDBMS software simultaneously while accessing a single database thus providing a clustered database.
In order to benefit from Oracle RAC features like fault tolerance and load balancing all you have to do is configuring the connection url with the list of Oracle hosts which belongs to the cluster.
In this example we are configuring our datasource to connect to a RAC made up of host1 and host2:
<connection-url>
jdbc:oracle:thin:@(description=(address_list=(load_balance=on)(failover=on) (address=(protocol=tcp)(host=host1)(port=1521))(address=(protocol=tcp)(host=host2)(port=1521)))(connect_data=(service_name=xxxxsid)(failover_mode=()(method=basic))))
</connection-url>
My SQL cluster
MySQL Cluster is a real-time open source transactional database designed for fast, always-on access to data under high throughput conditions.
In order to achieve load-balancing and failover across MySQL cluster you need to modify your jdbc Connection string adding the "loadbalance" keyword
to do load-balancing across the SQL nodes in MySQL Cluster, you would use a different JDBC connection string with the "loadbalance" keyword added
<connection-url>
jdbc:mysql:loadbalance://host-1,host-2,...host-n/database?loadBalanceBlacklistTimeout=5000
</connection-url>
Notice the "loadBalanceBlacklistTimeout" adds the needed feature that failed connections in a connection pool are put aside for the specified time, and only working connections are utilized. This parameter is essential for proper failover.
HOW TO CHOOSE WHICH COLUMN TO UPDATE WITH EJB CMP ?
If you need to select which columns need update when executing a CMP statement you might use the "updatable" attribute on the @Column annotation.
Setting "updatable" = false will assume that the column is not always included in the SQL update statement.
@Column(name="colname" updatable="false")
At the moment this feature is available only with TopLink JPA.
HOW TO CREATE VIEW OF OBJECTS WITH EJB QL ?
One nice feature of EJB QL is the ability to create new Type safe instances of an Object simply using the new construct. Here is an example:
select new Family(mother, mate, offspr)
from DomesticCat as mother
join mother.mate as mate
left join mother.kittens as offspr
Here we are returning an Object type of Family provided that we have a Constructor Family(mother, mate, offspr) in the class.
This option is useful to create View of Object structures, similarly like RDBMS create view of tables
HOW DO YOU HANDLE A DEADLOCK WITH JBOSS ?
When your application is trying to access the same entity bean within 2 different transaction in a different order a DeadLock can happen. When jBoss detects this situation will issue aorg.jboss.util.deadlock.ApplicationDeadlockException.So you should write your application so that it can retry a transaction if the invocation fails because of theApplicationDeadlockException. Unfortunately, this exception can be deeply embedded within aRemoteException, so you have to search for it in your catch block. For example:
- try {
- // ...
- } catch (RemoteException ex) {
- Throwable cause = null;
- RemoteException rex = ex;
- while (rex.detail != null) {
- cause = rex.detail;
- if (cause instanceof ApplicationDeadlockException) {
- // ... We have deadlock, force a retry of the transaction.
- break;
- }
- if (cause instanceof RemoteException) {
- rex = (RemoteException)cause;
- }
- }
- }
HOW TO ADD CONNECTION PROPERTIES TO YOUR JBOSS DATASOURCE ?
You can include connection properties in your DataSource configuration that will get passed in the DriverManager.getConnection(props) call. Here's how to do it:
Local Datasource
<local-tx-datasource>
...
<connection-property name="char.encoding">UTF-8</connection-property>
<!-- Tells an Oracle 10g driver to properly implement clobs. -->
<connection-property name="SetBigStringTryClob">true</connection-property>
..
</local-tx-datasource>
XA Datasource
<xa-datasource-property name="ConnectionProperties">SetBigStringTryClob=true</xa-datasource-property>
HOW DO I ACCESS THE SPECIFIC DRIVER CONNECTION WITH JBOSS ?
If you need to access to the specific driver connection (for example the OracleConnection instead of the java.sql.Connection) then you need to use the WrappedConnection object and get its underlying connection:
- Connection c = dataSource.getConnection();
- org.jboss.resource.adapter.jdbc.WrappedConnection wc = (WrappedConnection) c;
- OracleConnection ajc = (OracleConnection ) wc.getUnderlyingConnection();
Or another way, using reflection:
- public static OracleConnection getOracleConnection(Connection conFromPool)
- throws SQLException {
- try {
- Class[] parms = null;
- Method method =
- (conFromPool.getClass()).getMethod("getUnderlyingConnection",
- parms);
- return (OracleConnection) method.invoke(conFromPool, parms);
- } catch (InvocationTargetException ite) {
- throw new SQLException(ite.getMessage());
- } catch (Exception e) {
- throw new SQLException(e.getMessage());
- }
- }
HOW TO CHANGE JBOSS CONNECTION POOL SIZE DYNAMICALLY ?
Supposing you need to change at runtime the size of your datasource named "CatalogDB", then you can use twiddle command (or modify it manually from the JMX-Console)
$ twiddle.sh set jboss.jca:name=CatalogDB,service=ManagedConnectionPool MaxSize 300
This sets the Max ConnectionPool size to 300
HOW TO DEPLOY A HAR FILE INSIDE AN EAR ?
Hibernate archives can be deployed as top level packages or can be deployed as a component of an EAR file. Since Hibernate archives are not a standard J2EE deployment type, we need to declare them in the jboss-app.xml file of an EAR file to use them that context.
This is done with a module/har element as shown in the following example.
- <!DOCTYPE jboss-app PUBLIC "-//JBoss//DTD J2EE Application 1.4//EN"
- "http://www.jboss.org/j2ee/dtd/jboss-app_4_0.dtd">
- <jboss-app>
- <module>
- <har>sample.har</har>
- </module>
- </jboss-app>
With this, a Hibernate archive can be deployed along side a WAR or EAR file in any EAR file.
HOW CAN I RETRIEVE THE ID OF A TRANSACTION STARTED BY JBOSS ?
Sometimes it an be useful for debugging purpose to retrieve the id of a transaction; one typical scenario could be a transaction started by an EJB deployed as CMT.
Most application server provide some methods to obtain this information : with JBoss you can use the methodcom.arjuna.ats.jta.TransactionManager.transactionManager().getTransaction()It's not portable, however should you need it......
HOW TO USE MULTIPLE DATABASE IN PERSISTENCE.XML?
The Java Persistence API allows you to define multiple persistence units, each of which can map to a separate database. If you look at the persistence.xml file :
- <persistence>
- <persistence-unit name="sample-db1">
- <provider>org.hibernate.ejb.HibernatePersistence</provider>
- <jta-data-source>jdbc/SamplesDB</jta-data-source>
- </persistence-unit>
- <persistence-unit name="sample-db2">
- <provider>
- oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider
- </provider>
- <jta-data-source>jdbc/SamplesDB2</jta-data-source>
- </persistence-unit>
- </persistence>
@PersistenceContext(unitName="sample-db1",
.TRANSACTION)
private EntityManager em1;
@PersistenceContext(unitName="sample-db2",
.TRANSACTION)
private EntityManager em2;
HOW TO USE AN ENV VARIABLE IN YOUR PERSISTENCE.XML ?
Simply wrap your env variable in into ${variable}
Example:
- <persistence>
- <persistence-unit name="CustomEJB3Persistence">
- <jta-data-source>${myds}</jta-data-source>
- </persistence-unit>
- </persistence>
then pass the variable to the runs.h script
run.sh -Dmyds=$myds
HOW TO CREATE AN INDEX ON YOUR ENTITY BEANS?
You can use the @Index annotation with EJB3 in Hibernate 3.2.X to create indexes automatically when an entity is deployed.
This annotation can be put either on the Table annotation or directly on the entity property.
Examples:
@javax.persistence.Table(name = "items")
@org.hibernate.annotations.Table(appliesTo = "items", indexes = { @Index(name = "INDX", columnNames = { "idItem" }) })
@Index(name = "IDX", columnNames = { "idItem" })
public String getIdItem() {
return timestamp;
}
HOW TO CONNECT TO A DATASOURCE FROM A REMOTE CLIENT?
If you want to connect to your JBoss Connection Pool from a remote client ( that is a client that is not deployed on JBoss) you need to tell JBoss NOT to bind the Datasource under the "java:/"
namespace.
As a matter of fact this restricts the lookup to the same VM as the JBoss server.
Simply use tag <use-java-context>false</use-java-context> in your -ds.xml file
This is a sample Datasource file for mysql configured to accept remote client access
- <datasources>
- <local-tx-datasource>
- <jndi-name>MySqlDS</jndi-name>
- <use-java-context>false</use-java-context>
- <connection-url>jdbc:mysql://mysql-hostname:3306/jbossdb
- </connection-url>
- <driver-class>com.mysql.jdbc.Driver</driver-class>
- <user-name>x</user-name>
- <password>y</password>
- <metadata>
- <type-mapping>mySQL</type-mapping>
- </metadata>
- </local-tx-datasource>
- </datasources>
HOW TO DEPLOY A DATASOURCE IN JBOSS AT APPLICATION LEVEL ?
Do you need to deploy your DataSource along with your Enterprise Application ? (that is without having to install it in the "deploy" dir )
So, In your EAR file, create a jboss-app.xml file containing the following:
Code:
<jboss-app>
<module>
<service>myapp-ds.xml</service>
</module>
</jboss-app>
Place this jboss-app.xml in the META-INF folder of your EAR. And place the -ds.xml at the root of the EAR.
HOW TO DEPLOY AN APPLICATION REMOTELY WITH JBOSS AS ?
If you are running a JBoss AS release 5.1.0, there's a web application named admin-console which is going to replace the jmx-console for monitoring the application server.
You can launch it this way:
http://xx.xx.xx.xx/admin-console(Replace the xx.xx.xx.xx with your IP Address)
Now, in order to deploy an application select in the left tree view the type of Application you wish to deploy (Web, EJB or other) and click on the folder node
In the central frame just select "Add a new resource" and upload your application.
HOW TO FORCE JBOSS TO DEPLOY THE EJB FIRST IN AN EAR ?
Sometimes the order of deployed units, in an Enterprise application matters. For example, if you are deploying an EAR which is made up of a WEB application an EJB, it can be necessary that the EJB application is deployed at first.
A typical scenario is a Web application uses ServletContextListeners. If the ServletContextListener tries to access the EJB, as soon as the Web component is deployed, a NamingException might be the outcome of it, because the EJB hasn't been still bound in the JNDI.
The quick fix to it is adding a ContextComparator in conf\bootstrap\deployers.xml file:
- <bean name="topContextComparator">
- <constructor factory factoryMethod="getInstance"/>
- <property name="suffixOrder" >
- <map key value>
- <entry>
- <key>.war</key>
- <value>700</value>
- </entry>
- </map>
- </property>
- </bean>
HOW TO ADD A CUSTOM JBOSS ARCHIVE IN AN EAR ?
JBoss custom archives (like .sar or .har) are not recognized by the application.xml descriptors, so in order to deploy them in an EAR you have to declare them in jboss-app.xml. This file is located in the META-INF folder of your EAR.
For example, if you want to include an Hibernate Archive (HAR), you have to provide the following jboss-appl.xml configuration:
- <jboss-app>
- <module>
- <har>sample.har</har>
- </module>
- </jboss-app>
- <jboss-app>
- <module>
- <service>sample.sar</service>
- </module>
- </jboss-app>
- <module>
- <web>
- <web-uri>myapp.war</web-uri>
- <context-root>/myapp</context-root>
- </web>
- </module>
HOW TO RESTRICT ACCESS TO JBOSS WEB APPLICATION BY IP OR HOST?
You can create easily Access control list based on the IP address/Host name using Tomcat Valves. A Valveelement represents a component that will be inserted into the request processing pipeline for the associated Catalina container.
The Remote Address Filter allows you to compare the IP address of the client that submitted this request against one or more regular expressions, and either allow the request to continue or refuse to process the request from this client.
For example, to block all requests coming in except those from the local host:
<Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127.0.0.1" />
The Remote Host filter is much like the Remote Address Valve, except it allows you to compare the remote host address of the client that submitted this request instead of the fixed IP address. A Remote Host filter can be associated with a Tomcat Engine , Host, or Context container. An example entry using the org.apache.catalina.valves.RemoteHostValve can be found in the following code snippet.
<Valve className="org.apache.catalina.valves.RemoteHostValve" deny="badhost*"/>
This valve entry denies access to the assigned container for the host whose name starts with badhost. If I assign this valve entry to the host container localhost, then all clients beginning with badhost will see a 403 - Forbidden page.
THE JNDI.PROPERTY PITFALL
A piftall which is sometimes reported in JBoss forum is that JBoss refuses to start up correclty after an ear deployment unit has been added.
javax.naming.CommunicationException: Failed to connect to server localhost:1099 [Root exception is javax.naming.ServiceUnavailableException: Failed to connect to server localhost:1099 [Root exception is java.net.ConnectException: Connection refused]
If the problem disappear when you undeploy the ear deployment unit it is likely that you have added a jndi.properties file in the ear package.
The file jndi.properties is generally used when you connect to jBoss environment from remote resources.
#jboss JNDI properties
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://localhost:1099
java.naming.factory.url.pkgs=org.jnp.interfaces
Adding to the Ear deployment interfers with JBoss binding process, so JBoss refuses to start-up. Get rid of it and the problem will disappear!
HOW TO DEPLOY AN APPLICATION TEMPORARLY WITH JBOSS ?
One way to do it, is using the jboss.system:service=MainDeployer Mbean.
In practice, if you deploy an application using this MBean your application will be temporarlydeployed on the application server. Why temporarly ? because it's not copied into the "deploy" directory but simply deployed where it is.
The location of the application is not persisted, JBoss keeps in memory the location of the application, so at server shutdown the application will exit from JBoss.
One way to reach this MBean is via the twiddle utility:
twiddle invoke "jboss.system:service=MainDeployer" deploy C:\TempApp.war
Here the web application TempApp.war is deployed from C:\ . Until JBoss is running.
HOW TO DEPLOY AN EXPLODED APPLICATION ON JBOSS SAFELY ?
Have you ever tried to deploy a large application as exploded directory ? one common issue arises from the fact that if JBoss reads the deployment descriptors before the whole application is deployed. JBoss usually complains that the application was deployed as incomplete application.
This can happen for example if you are transferring the files on a slow network, or if the application is quite big.
One workaround is not to copy files but rather moving
mv mylargeapp.ear $JBOSS_HOME/server/default/deploy
why this should work ? because on most OS mv is treated as an atomic operation, that is, files are made available only when the transfer is completed (like for example when we issue a commit to the database).
I cannot guarantee that this will work on all situations (for example on the HP docs I have read that mv is atomic only within the same filesystem. Across filesystems mv is not atomic.)...however it's worth a try, isn't it ??
HOW TO INJECT SYSTEM PROPERTIES INTO JBOSS ?
One cool way to add a list of System properties to JBoss is the Properties MBean Service.
In the deployment folder look for "properties-service.xml". (if you don't have it in your release you can create it at any time) :
Now add your properties either in the URLList Attribute or in the Properties Attribute:
view plaincopy to clipboardprint?
- <server>
- <mbean code="org.jboss.varia.property.SystemPropertiesService"
- name="jboss:,name=SystemProperties">
- <attribute name="URLList">
- http://somehost/some-location.properties,
- ./conf/somelocal.properties
- </attribute>
- <attribute name="Properties">
- property1=This is the value of my property
- property2=This is the value of my other property
- </attribute>
- </server>
As you can see the The "URLList" is a comma-separated list of URL strings from which to load properties file-formatted content while the "Properties" is a specification of multiple property name=value pairs
Now you can access your properties with standard:
System.getProperty("property1");
HOW TO RUN 2 JBOSS ON THE SAME COMPUTER ?
Running 2 JBoss instances on the same computer requires changing default ports in order to avoid conflicts.
· Open /deploy/jbossweb-tomcat55.sar/server.xml and change port 8080
· Open conf/jboss-service.xml and change ports 8083,1099,1098,4444,4445
· Open deploy/jms/uil2-service.xml and change port 8093
Hint: An easier solution would be to add a virtual address to your pc and simply bind each jboss to a different address with the -b option
HOW DO I CHANGE MULTICAST ADDRESS OF JBOSS CLUSTER ?
Since JBoss AS 4.0.3, the jboss.partition.udpGroup property can be used to change the multicast address of JBoss cluster. A command line option can be used also:
$ run.sh -c all --udp 233.3.4.5
HOW TO CREATE A CUSTOM JBOSS CONFIGURATION ?
JBoss ships with 3 configurations:
· default: the standard jBoss standalone configuration
· all: same as standard but with Clustering enabled
· minimal: barebones JMX services
However you re not limited to the existing configurations: you can create a custom server configuration that suits your needs best.
The easiest way to do it is starting from one existing configuration and adjust for your needs.
for example if you need a standard JBoss configuration but without JMS support, simply copy the "default" configuration and remove the "deploy/jms" folder which contains all the JMS related services.
The name of the new directory you created is the name of the server configuration. You will need to pass the server configuration name to instruct JBoss to use the new configuration. For example, if your new configuration directory is named "myconfig" then you would need to start JBoss using "run -c myconfig".
HOW TO CONFIGURE LOG4J IN YOUR EAR ?
Have you got exceptions when tried to configure log4j at application level ? this is due to the fact that JBoss ships already with log4j classes: you need to isolate the classes from other deployments. Without isolation, you can see common errors like ClassCastException, IllegalAccessErrors, VerifyErrors and in general, strange behavior.
Here's how to do it:
Create a log4j.properties file and package it with your application and make it visible to JBoss classpath (see image at the bottom). The log4j.properties has just a minimal content:
log4j.logger.com.sample=TRACE
Within your application you need to add the appropriate version of log4j jar (this is important because you will have to ensure that log4j initializes separately for your application and picks up the log4j.properties file). Place this log4j jar file in the lib folder of your EAR (as depicted in the picture).
Finally you need to enable classloader isolation for your application. In order to achieve classloader isolation you need to add an entry in jboss-app.xml file and place it in the META-INF folder of the EAR. The jboss-app.xml looks like:
- <jboss-app>
- <loader-repository>
- org.myapp:loader=MyClassLoader
- <loader-repository-config>
- java2ParentDelegation=false
- </loader-repository-config>
- </loader-repository>
- </jboss-app>
This is how your application EAR should look like:
HOW DO I CHANGE THE DEFAULT LIB DIRECTORY IN AN EAR FILE?
Supposing you have an Enterprise application which has been packaged in an ear and its libraries are placed in another folder like Weblogic's APP-INF/lib. How can I deploy this application to JBoss ?
You might resort to the "library-directory" parameter of jboss-app.xml
Here's an example:
<application>
<display-name>My Application</display-name>
<module>
<web>
<web-uri>myapp.war</web-uri>
<context-root>/myapp</context-root>
</web>
</module>
<module>
<ejb>myapp.jar</ejb>
</module>
<library-directory>APP-INF/lib</library-directory>
</application>
HOW TO CONFIGURE JBOSS TO DISABLE HOT DEPLOYMENT ?
For performance reason you might want to disable JBoss hot deployment's feature.
Simply open the conf/jboss-service.xml file and find the line:
<!-- A flag to disable the scans -->
<attribute name="ScanEnabled">true</attribute>
Simply change to false and hot deployment will be disabled.
If on the other hand you simply want to reduce scan polling time, look for a few lines before:
<!-- Frequency in milliseconds to rescan the URLs for changes -->
<attribute name="ScanPeriod">5000</attribute>
This will set the scan time (in milliseconds)
MBean
Monitoring your Connection Pool
Each datasource translates into several MBeans that you can interact with in the JMX Console. All the datasource-related objects are in the jboss.jca domain. You can find them by searching through the JMX Console page, or by using jboss.jca:* as the query filter.
Supposing you want to monitor your OracleDS datasource from the previous example: you could use a more specific filter, such as jboss.jca:name=OracleDS,*, to see only the OracleDS entries. In either case, four MBeans will be related to the OracleDS datasource:
• name=OracleDS ,service=DataSourceBinding
• name=OracleDS ,service=LocalTxCM
• name=OracleDS ,service=ManagedConnectionFactory
• name=OracleDS ,service=ManagedConnectionPool
While each plays a critical role in providing the datasource functionality in JBoss, you are most likely to need to interact with the connection pool. Click the connection pool MBean to expose the management attributes and operations.
In our datasource file we've been using specified a minimum connection pool size of 2 and a maximum pool size of 10. You'll see those values reflected in the MinSize and MaxSize attributes. You can change the values in the running server by adjusting the values and clicking Apply Changes.
Setting the values here affects the connection pool only in memory. To change the configuration permanently, update the datasource file. Try setting the pool sizes there. When you save the file, JBoss will redeploy the datasource and the new pool sizes will be displayed when you reload the page.
You might occasionally want to adjust the pool size to account for usage; you are more likely to be curious how much of the connection pool is being used. The ConnectionCount attribute shows how many connections are currently open to the database. However, open connections are not necessarily in use by application code. The InUseConnectionCount attribute shows how many of the open connections are in use. Viewing the statistic from the other direction, AvailableConnectionCount shows how much room is left in the pool.
Finally, the MBean has several statistics that track connection pool usage over the pool's lifetime. ConnectionCreatedCount and Connection-DestroyedCount keep running totals of the number of connections created and destroyed by the pool. If IdleTimeout is greater than 0, connections will eventually timeout, be destroyed, and be replaced by fresh connections. This will cause the created and destroyed counts to rise constantly. The MaxConnectionsInUseCount attribute keeps track of the highest number of connections in use at a time.
If you notice anything awkward in the connection pool, or you just want to reset the statistics, you can flush the connection pool using the flush operation on the MBean. This will cause a new connection pool to be created, abandoning the previous connection pool.
A Graph is worth 100 words
or so ! if you read our recent Recipes (and we really appreciate that you are a faithful visitor !) then you know that JBoss Web Console is able to show you graphically the value of many MBeans attribute (those who have a numeric value).
So look for the MBean "name=OracleDS ,service=ManagedConnectionPool", there you can choose to add a graph to any of the attributes: in this picture you can see a sample graph of the JMX Attribute Connection Count
How do I configure a Queue/Topic to work in a cluster?
Just set the Clustered attribute to "true" in your Queue/Topic definition. Here's a Queue example:
1. <mbean code="org.jboss.jms.server.destination.QueueService"
2. name="jboss.messaging.destination:service=Queue,name=SampleQueue"
3. xmbean-dd="xmdesc/Queue-xmbean.xml">
4. <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
5. <depends>jboss.messaging:service=PostOffice</depends>
6. <attribute name="Clustered">true</attribute>
7.
8. </mbean>
How to configure a queue in jboss ?
Simply drop a file ending in -service.xml in the deploy folder, containing the Queue definition.
<server>
<mbean code="org.jboss.mq.server.jmx.Queue"
name="jboss.mq.destination:service=Queue,name=MyQueue">
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>
</server>
Verify in the Jmx-console under the jboss.mq.destination tab that the Queue is correctly deployed.
How to a dump of jndi tree with jmx console ?
Quite easy. Open your JMX console:
http://localhost:8080/jmx-console
and look for the Service "JNDIView" (it's under the object name jboss)
Now simply find the method "list", click it et voilà !
without writing a line of code but simply using the JMX Console
JMX Basics
JMX Management Beans are POJOs that live in a JMX Container. The JMX container provides standardized ways of accessing these POJOs so that various tools can be used to access the objects, get their status, etc. These POJOs are used to start, stop and configure various important application services such as JDBC connection pools, JMX services, and EJB deployers. In fact, all services in JBoss AS are initialized and configured using JMX management beans that are loaded in to the JMX container when JBoss starts.
Why make a custom JMX MBean?
• Java Enterprise application developers often need services that run when the application starts up.
• Database migration - It's usually difficult to modify the database schema while the application is running, so it's often done using shell scripts or standalone Java programs. It also doesn't work if the code needs to run before the application is deployed.
• Timer service - While EJB3 timeouts will take care of the vast majority of applications, sometimes there is a need for very precise timing.
• Protocol services - Application servers such as JBoss handle HTTP and RMI, but occasionally another protocol is needed for example FTP or FIX.
• Some technologies that developers often use to implement these kinds of features are:
• Startup Servlets - This is actually a very effective approach, but there can be problems in clustered deployments. For example, a database migration program should be launched only once when the cluster starts.
• Daemon JVMs - These are JVMs started outside the application server that perform some functions that the application server cannot handle. Often these JVMs are remote EJB clients that retrieve information from the application and process it asynchronously. In these cases a Message Driven EJB might be a simpler, and better choice. However if there are network protocols that must be implemented, this is a popular choice. The problems with this kind of architecture are:
o The JVM process needs to be managed separately, started and stopped along with the application server processes.
o Building in high availability - restarting the deamon on another machine if it fails is not built in.
o Remote communication with the app server is required.
Ideas about invoking EJBs, etc. from JMX
A simple solution to this would be to have a singleton in the outer class loader that forms a bridge between some objects instantiated by the application class loader and JMX MBeans. This singleton can contain proxy objects that forward simple JMX lifecycle methods to the implementation if it is registered.
• Singleton class, loaded into an outer class loader that both the JMX service and the EAR have in common. In JBoss, this is simply a jar in the server lib directory.
• The singleton contains a map of proxies, keyed by 'implementation name'. The key can serve as a way to instantiate the delegate implementation class.
• JMX Services can retrieve the proxy object from the singleton and pass on any lifecycle messages. If the implementation is not there yet, the resulting state will need to be remembered for later.
• A startup servlet in the application can invoke an initialization method on the singleton. The singleton can then instantiate all the implementation class names because the correct class loader is there.
• Each proxy will instantiate the implementation at this time, invoking JMX lifecycle methods to put the object in the state it would have been in had it been directly called by the JMX MBean in the first place.
Each datasource translates into several MBeans that you can interact with in the JMX Console. All the datasource-related objects are in the jboss.jca domain. You can find them by searching through the JMX Console page, or by using jboss.jca:* as the query filter.
Supposing you want to monitor your OracleDS datasource from the previous example: you could use a more specific filter, such as jboss.jca:name=OracleDS,*, to see only the OracleDS entries. In either case, four MBeans will be related to the OracleDS datasource:
• name=OracleDS ,service=DataSourceBinding
• name=OracleDS ,service=LocalTxCM
• name=OracleDS ,service=ManagedConnectionFactory
• name=OracleDS ,service=ManagedConnectionPool
While each plays a critical role in providing the datasource functionality in JBoss, you are most likely to need to interact with the connection pool. Click the connection pool MBean to expose the management attributes and operations.
In our datasource file we've been using specified a minimum connection pool size of 2 and a maximum pool size of 10. You'll see those values reflected in the MinSize and MaxSize attributes. You can change the values in the running server by adjusting the values and clicking Apply Changes.
Setting the values here affects the connection pool only in memory. To change the configuration permanently, update the datasource file. Try setting the pool sizes there. When you save the file, JBoss will redeploy the datasource and the new pool sizes will be displayed when you reload the page.
You might occasionally want to adjust the pool size to account for usage; you are more likely to be curious how much of the connection pool is being used. The ConnectionCount attribute shows how many connections are currently open to the database. However, open connections are not necessarily in use by application code. The InUseConnectionCount attribute shows how many of the open connections are in use. Viewing the statistic from the other direction, AvailableConnectionCount shows how much room is left in the pool.
Finally, the MBean has several statistics that track connection pool usage over the pool's lifetime. ConnectionCreatedCount and Connection-DestroyedCount keep running totals of the number of connections created and destroyed by the pool. If IdleTimeout is greater than 0, connections will eventually timeout, be destroyed, and be replaced by fresh connections. This will cause the created and destroyed counts to rise constantly. The MaxConnectionsInUseCount attribute keeps track of the highest number of connections in use at a time.
If you notice anything awkward in the connection pool, or you just want to reset the statistics, you can flush the connection pool using the flush operation on the MBean. This will cause a new connection pool to be created, abandoning the previous connection pool.
A Graph is worth 100 words
or so ! if you read our recent Recipes (and we really appreciate that you are a faithful visitor !) then you know that JBoss Web Console is able to show you graphically the value of many MBeans attribute (those who have a numeric value).
So look for the MBean "name=OracleDS ,service=ManagedConnectionPool", there you can choose to add a graph to any of the attributes: in this picture you can see a sample graph of the JMX Attribute Connection Count
How do I configure a Queue/Topic to work in a cluster?
Just set the Clustered attribute to "true" in your Queue/Topic definition. Here's a Queue example:
1. <mbean code="org.jboss.jms.server.destination.QueueService"
2. name="jboss.messaging.destination:service=Queue,name=SampleQueue"
3. xmbean-dd="xmdesc/Queue-xmbean.xml">
4. <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
5. <depends>jboss.messaging:service=PostOffice</depends>
6. <attribute name="Clustered">true</attribute>
7.
8. </mbean>
How to configure a queue in jboss ?
Simply drop a file ending in -service.xml in the deploy folder, containing the Queue definition.
<server>
<mbean code="org.jboss.mq.server.jmx.Queue"
name="jboss.mq.destination:service=Queue,name=MyQueue">
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>
</server>
Verify in the Jmx-console under the jboss.mq.destination tab that the Queue is correctly deployed.
How to a dump of jndi tree with jmx console ?
Quite easy. Open your JMX console:
http://localhost:8080/jmx-console
and look for the Service "JNDIView" (it's under the object name jboss)
Now simply find the method "list", click it et voilà !
without writing a line of code but simply using the JMX Console
JMX Basics
JMX Management Beans are POJOs that live in a JMX Container. The JMX container provides standardized ways of accessing these POJOs so that various tools can be used to access the objects, get their status, etc. These POJOs are used to start, stop and configure various important application services such as JDBC connection pools, JMX services, and EJB deployers. In fact, all services in JBoss AS are initialized and configured using JMX management beans that are loaded in to the JMX container when JBoss starts.
Why make a custom JMX MBean?
• Java Enterprise application developers often need services that run when the application starts up.
• Database migration - It's usually difficult to modify the database schema while the application is running, so it's often done using shell scripts or standalone Java programs. It also doesn't work if the code needs to run before the application is deployed.
• Timer service - While EJB3 timeouts will take care of the vast majority of applications, sometimes there is a need for very precise timing.
• Protocol services - Application servers such as JBoss handle HTTP and RMI, but occasionally another protocol is needed for example FTP or FIX.
• Some technologies that developers often use to implement these kinds of features are:
• Startup Servlets - This is actually a very effective approach, but there can be problems in clustered deployments. For example, a database migration program should be launched only once when the cluster starts.
• Daemon JVMs - These are JVMs started outside the application server that perform some functions that the application server cannot handle. Often these JVMs are remote EJB clients that retrieve information from the application and process it asynchronously. In these cases a Message Driven EJB might be a simpler, and better choice. However if there are network protocols that must be implemented, this is a popular choice. The problems with this kind of architecture are:
o The JVM process needs to be managed separately, started and stopped along with the application server processes.
o Building in high availability - restarting the deamon on another machine if it fails is not built in.
o Remote communication with the app server is required.
Ideas about invoking EJBs, etc. from JMX
A simple solution to this would be to have a singleton in the outer class loader that forms a bridge between some objects instantiated by the application class loader and JMX MBeans. This singleton can contain proxy objects that forward simple JMX lifecycle methods to the implementation if it is registered.
• Singleton class, loaded into an outer class loader that both the JMX service and the EAR have in common. In JBoss, this is simply a jar in the server lib directory.
• The singleton contains a map of proxies, keyed by 'implementation name'. The key can serve as a way to instantiate the delegate implementation class.
• JMX Services can retrieve the proxy object from the singleton and pass on any lifecycle messages. If the implementation is not there yet, the resulting state will need to be remembered for later.
• A startup servlet in the application can invoke an initialization method on the singleton. The singleton can then instantiate all the implementation class names because the correct class loader is there.
• Each proxy will instantiate the implementation at this time, invoking JMX lifecycle methods to put the object in the state it would have been in had it been directly called by the JMX MBean in the first place.