• Subscribe  |  
  • Register  |  
  • Issue Tracking  |  
  • Login   |  
  • Search:

View feed: My Wiki

  • Subscribe to this feed:
  • ATOM

How do i use my own log4j properties or xml file in JBoss

Posted on 2008-04-19 06:50:00.0 by Jaikiran [ View original post ]

This article is mainly for those who had a hard time configuring "their own" log4j.properties or log4j.xml within their application on JBoss. For a brief background on this, please read through this JBoss wiki. As explained in that wiki, JBoss uses its own version of log4j.xml and log4j jar, making it difficult to use your own version of the log4j properties/xml files. The wiki also lists down the steps required to configure your application to use its own log4j config file. However, i have seen people complain in the forums that those steps either dont work for them or the steps are too involved and not worth a try.

People at JBoss had taken note of these issues (see the related JIRA) and starting JBoss-4.2.x, the steps involved to configure your own log4j config file in JBoss are pretty simple and straight-forward. In this example, i will try to explain these steps for a EAR file as well as a WAR file. The version that i am using here is JBoss-4.2.2GA (which is the latest stable version at this point). In the examples here, i use a log4j.properties file. The steps are the same even for a log4j.xml.

So here's what is required to get it working in a EAR file:

1) Create a log4j.properties and package it with your application and make it available in the classpath (i placed the log4j.properties file at the root of the EAR file).

2) Also package the appropriate version of log4j jar with your application (this step and the next step are 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 application package so that it is made available in the classpath (i placed it in a folder named lib of the EAR file - remember that any jars in the lib folder of the EAR are by default added to the classpath and made available to the entire application, starting JBoss-4.2.x version).

3) Enable classloader isolation for your application. This is necessary as explained in step#2. You will have to create a 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 the EAR file would look like:



myApp.ear
|
|--- log4j.properties
|
|--- META-INF
| |
| |--- application.xml
| |
| |--- jboss-app.xml
|
|--- lib
| |
| |--- log4jxxx.jar






That's it! Your application now will use it own version of log4j config file as well log4j jar.

Steps involved for a WAR file are similar (If the WAR file is part of an EAR file, then you don't have to follow the steps below. The steps mentioned above for an EAR file are sufficient for a WAR inside an EAR):

1) Create a log4j.properties and package it with your application and make it available in the classpath (i placed the log4j.properties file in the WEB-INF/classes folder of the WAR).

2) Also package the appropriate version of log4j jar with your application (this step and the next step are 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 application package so that it is made available in the classpath (i placed it in a WEB-INF/lib of the WAR file).

3) Enable classloader isolation for your application. This is necessary as explained in step#2. You will have to create a jboss-web.xml file and place it in the WEB-INF folder of the WAR. The jboss-web.xml looks like:



<jboss-web>
<class-loading java2ClassLoadingCompliance="false">
<loader-repository>
org.myapp:loader=MyClassLoader
<loader-repository-config>java2ParentDelegation=false</loader-repository-config>
</loader-repository>
</class-loading>
</jboss-web>





This is how the WAR file would look like:


myApp.war
|
|--- WEB-INF
| |
| |--- web.xml
| |
| |--- jboss-web.xml
| |
| |--- classes
| | |
| | |--- log4j.properties
|
|
|--- lib
| |
| |--- log4jxxx.jar






Why do i get NameNotFoundException while doing a JNDI lookup?

Posted on 2007-10-06 04:07:00.0 by Jaikiran [ View original post ]

Many a times when you are doing a lookup in the JNDI tree, you see javax.naming.NameNotFoundException. A simple code that does the lookup will look something like:


Context ctx = new InitialContext();
Object obj = ctx.lookup("somepath/somename");


This code just looks up the JNDI tree to get an object bound by the name "somepath/somename". Looks simple. However, chances are that you might even see this exception:


javax.naming.NameNotFoundException: somepath not bound
at org.jnp.server.NamingServer.getBinding(NamingServer.java:529)
at org.jnp.server.NamingServer.getBinding(NamingServer.java:537)
at org.jnp.server.NamingServer.getObject(NamingServer.java:543)
at org.jnp.server.NamingServer.lookup(NamingServer.java:267)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:294)
at sun.rmi.transport.Transport$1.run(Transport.java:153)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:149)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:460)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:701)
at java.lang.Thread.run(Thread.java:595)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:247)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:223)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:126)
at org.jnp.server.NamingServer_Stub.lookup(Unknown Source)
at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:625)
at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:587)
at javax.naming.InitialContext.lookup(InitialContext.java:351)


Look closely at the stacktrace. It shows that while looking up the JNDI tree it could not find the jndi name "somepath" (this name may vary). The reason is simple, the JNDI tree does not have any object bound by this name.

To quote the javadocs of this exception "This exception is thrown when a component of the name cannot be resolved because it is not bound."

So how do i know, what's the name to which my object is bound? Each application server, usually provides a JNDI view which can be used to see the contents of the JNDI tree. If you know what object you are looking for (ex: the name of the bean), then you can traverse this JNDI tree to see what name it is bound to. The JNDI view is specific to every application server.

To give an example, JBoss provides its JDNI tree view, through the JMX console. Here are the steps, one has to follow to check the JNDI tree contents on JBoss:

- Go to http://< server>:< port>/jmx-console (Ex: http://localhost:8080/jmx-console)
- Search for service=JNDIView on the jmx-console page
- Click on that link
- On the page that comes up click on the Invoke button beside the list() method
- The page that comes up will show the contents of the JNDI tree.

Here's an sample of how the output looks like(just a small part of the entire output):


java: Namespace

+- XAConnectionFactory (class: org.jboss.mq.SpyXAConnectionFactory)
+- DefaultDS (class: org.jboss.resource.adapter.jdbc.WrapperDataSource)
+- SecurityProxyFactory (class: org.jboss.security.SubjectSecurityProxyFactory)
+- DefaultJMSProvider (class: org.jboss.jms.jndi.JNDIProviderAdapter)
+- comp (class: javax.naming.Context)
+- JmsXA (class: org.jboss.resource.adapter.jms.JmsConnectionFactoryImpl)
+- ConnectionFactory (class: org.jboss.mq.SpyConnectionFactory)
+- jaas (class: javax.naming.Context)
| +- dukesbank (class: org.jboss.security.plugins.SecurityDomainContext)
| +- HsqlDbRealm (class: org.jboss.security.plugins.SecurityDomainContext)
| +- jbossmq (class: org.jboss.security.plugins.SecurityDomainContext)
| +- JmsXARealm (class: org.jboss.security.plugins.SecurityDomainContext)


Global JNDI Namespace

+- ebankTxController (proxy: $Proxy79 implements interface com.sun.ebank.ejb.tx.TxControllerHome,interface javax.ejb.Handle)
+- ebankAccountController (proxy: $Proxy75 implements interface com.sun.ebank.ejb.account.AccountControllerHome,interface javax.ejb.Handle)
+- TopicConnectionFactory (class: org.jboss.naming.LinkRefPair)
+- jmx (class: org.jnp.interfaces.NamingContext)
| +- invoker (class: org.jnp.interfaces.NamingContext)
| | +- RMIAdaptor (proxy: $Proxy48 implements interface org.jboss.jmx.adaptor.rmi.RMIAdaptor,interface org.jboss.jmx.adaptor.rmi.RMIAdaptorExt)
| +- rmi (class: org.jnp.interfaces.NamingContext)
| | +- RMIAdaptor[link -> jmx/invoker/RMIAdaptor] (class: javax.naming.LinkRef)
+- HTTPXAConnectionFactory (class: org.jboss.mq.SpyXAConnectionFactory)
+- ConnectionFactory (class: org.jboss.mq.SpyConnectionFactory)
+- ebankCustomer (proxy: $Proxy67 implements interface com.sun.ebank.ejb.customer.LocalCustomerHome)
+- UserTransactionSessionFactory (proxy: $Proxy14 implements interface org.jboss.tm.usertx.interfaces.UserTransactionSessionFactory)
+- ebankCustomerController (proxy: $Proxy77 implements interface com.sun.ebank.ejb.customer.CustomerControllerHome,interface javax.ejb.Handle)
+- HTTPConnectionFactory (class: org.jboss.mq.SpyConnectionFactory)
+- XAConnectionFactory (class: org.jboss.mq.SpyXAConnectionFactory)
+- TransactionSynchronizationRegistry (class: com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionSynchronizationRegistryImple)
+- ebankAccount (proxy: $Proxy68 implements interface com.sun.ebank.ejb.account.LocalAccountHome)
+- UserTransaction (class: org.jboss.tm.usertx.client.ClientUserTransaction)
+- UILXAConnectionFactory[link -> XAConnectionFactory] (class: javax.naming.LinkRef)
+- UIL2XAConnectionFactory[link -> XAConnectionFactory] (class: javax.naming.LinkRef)
+- queue (class: org.jnp.interfaces.NamingContext)
| +- A (class: org.jboss.mq.SpyQueue)
| +- testQueue (class: org.jboss.mq.SpyQueue)
| +- ex (class: org.jboss.mq.SpyQueue)
| +- DLQ (class: org.jboss.mq.SpyQueue)
| +- D (class: org.jboss.mq.SpyQueue)
| +- C (class: org.jboss.mq.SpyQueue)
| +- B (class: org.jboss.mq.SpyQueue)


Let's see what this tells us. Let's consider the Global JNDI Namespace first. It contains (among other things) the following:

+- ebankTxController (proxy: $Proxy79 implements interface com.sun.ebank.ejb.tx.TxControllerHome,interface javax.ejb.Handle)


This tells me that an object which implements com.sun.ebank.ejb.tx.TxControllerHome and javax.ejb.Handle interfaces is bound to the JNDI tree by the jndi-name "ebankTxController". So if at all i have to lookup this object, my lookup code would be something like:


Context ctx = new InitialContext();
ctx.lookup("ebankTxController");


Similarly in the same Global JDNI Namespace, we see :


+- queue (class: org.jnp.interfaces.NamingContext)
| +- A (class: org.jboss.mq.SpyQueue)



Make note of the nesting of the names here. This tells me that an object of type org.jboss.mq.SpyQueue is bound by the name "A under the path queue". So your lookup for this object should look like:


Context ctx = new InitialContext();
ctx.lookup("queue/A");


Now let's move on to the java: namespace in the JNDI tree view above. The difference between a Global JNDI namespace and the java: namespace is that, the object bound in the java: namespace can be looked-up ONLY by clients within the SAME JVM. Whereas, in case of Global JNDI namespace, the objects bound in this namespace can be looked-up by clients, even if they are not in the same JVM as the server. One would ask, how does this matter? Consider a standalone java program(client) which tries to lookup some object on the server (running in its own JVM). Whenever a standalone client is started (using the java command), a new JVM is instantiated. As a result, the server (which is started in its own JVM) and the client are running on different JVMs. Effectively, the client will NOT be able to lookup objects bound in the java: namespace of the server. However, the client can lookup the objects present in the Global JNDI namespace of the server.

So, why are we discussing these details, in a topic which was meant to explain the NameNotFoundException? Let's consider the java: namespace output above. There's a


+- DefaultDS (class: org.jboss.resource.adapter.jdbc.WrapperDataSource)


This tells me that there's an object bound to the name DefaultDS in the java: namespace. So my lookup code would be:


Context ctx = new InitialContext();
ctx.lookup("java:/DefaultDS");


As explained above, this code is going to return you the object, if this piece of code runs in the same JVM as the server. However, if this piece of code is run from a client in different JVM (maybe a standalone client), then it's going to run into NameNotFoundException. The reason i explained the java: and the Global JNDI namespace is that, sometimes people are surprised that even though the JNDI view shows that the object is bound in the java: namespace(with the same name as the one they pass to the lookup method), they still run into NameNotFoundException. The probable reason might be, the client is in a different JVM.

Webservice client using dynamic proxy

Posted on 2007-04-18 06:59:00.0 by Jaikiran [ View original post ]

In one of my previous posts, i explained how to create a WebService and access it from a simple client. If you look at the client code which accesses the webservice, you will find that the client is using the stubs that were created at deploy time. Such clients which use "static stubs" for accessing webservices are known as "Static Stub Clients". In such approach, the clients will have to have the stubs in their classpath.

Another approach of accessing the webservices is through Dynamic Proxies where the proxies are generated at runtime. I will be showing a simple client which uses dynamic proxies to access an webservice. I wont be explaining the steps to deploy the webservice (which i have already done in my other post). This example assumes that the webservice is already deployed on the server.

The client code will be accessing the HelloWorld service and invoking the sayHelloTo method on that service (Refer my other post to see how the service has been deployed onto the server)

Here's the code for the client:


package org.myapp.service.client;

import java.net.MalformedURLException;
import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceException;
import javax.xml.rpc.ServiceFactory;

import org.myapp.service.HelloWorldService;

/**
* Simple webservice client which uses dynamic proxy
*
* @author Jaikiran Pai
*/
public class DynamicProxyClient {

public static void main(String args[]) {

try {

// ServiceFactory instance
ServiceFactory serviceFactory = ServiceFactory.newInstance();
System.out.println("Got the service factory");
String wsdlURLString = "http://localhost:8080/axis/services/HelloWorld?wsdl";
URL wsdlURL = new URL(wsdlURLString);
String serviceName = "HelloWorldServiceService";
String nameSpaceURI = "http://jaikiran.com";
String portName = "HelloWorld";
// get hold of the service by passing the URL of the wsdl and the
// service name
Service service = serviceFactory.createService(wsdlURL, new QName(
nameSpaceURI, serviceName));
System.out.println("Got the service: " + service);
// create the service proxy
HelloWorldService serviceProxy = (HelloWorldService) service
.getPort(new QName(nameSpaceURI, portName),
HelloWorldService.class);
System.out.println("Got the service proxy: " + serviceProxy);
System.out.println("Invoking method on service proxy........");
System.out.println(serviceProxy.sayHelloTo("Dynamic user"));

} catch (ServiceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}



1) Our first step would be to create a ServiceFactory instance, using which we can get access to a deployed service.


ServiceFactory serviceFactory = ServiceFactory.newInstance();


2) Once the ServiceFactory has been created, we will be getting hold of the service which is deployed on the server. To do this, we require
a) The url of the wsdl of the deployed service. In this example it will be http://localhost:8080/axis/services/HelloWorld?wsdl

b) The namespace uri. In this example it will be http://jaikiran.com (You can get this uri from the wsdl file)

c) The name of the service which you want to access. In this example it will be HelloWorldServiceService



String wsdlURLString = "http://localhost:8080/axis/services/HelloWorld?wsdl";
URL wsdlURL = new URL(wsdlURLString);
String serviceName = "HelloWorldServiceService";
String nameSpaceURI = "http://jaikiran.com";

// get hold of the service by passing the URL of the wsdl and the
// service name
Service service = serviceFactory.createService(wsdlURL, new QName(
nameSpaceURI, serviceName));



3) At this point you have got access to the service. But in order to invoke an method on the service, you will have to create a proxy (dynamic proxy) from this service. The Service class, has an API getPort, which creates the proxy. In order to create the proxy, we will have to pass the portName of the service (again, this can be obtained in the wsdl file), the namespace uri and the class type of the service. In this example the service interface is org.myapp.service.HelloWorldService, so we will be passing this as the class as follows:


String portName = "HelloWorld";
// create the service proxy
HelloWorldService serviceProxy = (HelloWorldService) service
.getPort(new QName(nameSpaceURI, portName),
org.myapp.service.HelloWorldService.class);


4) At this point we have got the service proxy which is of type org.myapp.service.HelloWorldService. We can now invoke our sayHelloTo method on this proxy:


System.out.println(serviceProxy.sayHelloTo("Dynamic user"));


Simple, isnt it? You have successfully invoked the webservice through a standalone client using dynamic proxy.

Simple Webservice on JBoss using Axis

Posted on 2006-12-10 05:07:00.0 by Jaikiran [ View original post ]

Download the latest stable version of Axis from Axis Releases

1) Deploying Axis web application on JBoss:

I used Axis 1.4 on JBoss-4.0.4 GCA. Assuming you downloaded Axis to D: , copy the "axis" folder present in D:\Axis-1.4\webapps folder to %JBOSS_HOME%\server\default\deploy folder. The "axis" folder that you copied is nothing but an web application (containing of some servlets and jsps provided by Axis). In JBoss for a web application to be deployed, it has to be named *.war, so rename the "axis" folder in %JBOSS_HOME%\server\default\deploy to axis.war. At this point, the axis web application is ready to be deployed on JBoss. But before starting JBoss, delete the commons-logging-x.x.x.jar and log4j-x.x.x.jar present in %JBOSS_HOME%\server\default\deploy\axis.war\WEB-INF\lib directory, since JBoss maintains its own versions of these jars and packaging these jars in your application will throw exceptions of JBoss startup. After you have deleted these jars, start the JBoss server using the run.bat present in %JBOSS_HOME%\bin folder.


2) Verify Axis web application is deployed and running:

After JBoss has started successfully, go to the following URL to check whether axis is deployed properly:

http://localhost:8080/axis

If Axis was deployed successfully, you will see a welcome page which will have a few links, one of them named "List" which can be used to view the already deployed webservices. Axis by default comes with a few sample webservices which you can see on clicking the "List" link.


3) Writing our own webservice:

3a - The Java classes/interfaces:

Lets create a simple webservice which will echo a message to the user who passes his name. We will have an interface named HelloWorldService:


package org.myapp.service;

public interface HelloWorldService {

public String sayHelloTo(String userName);

}


And here's the implementing class:


package org.myapp.service;

public class HelloWorldServiceImpl implements HelloWorldService {

public String sayHelloTo(String userName) {

//message
String hello = "Hello " + userName + ". You are being watched";

System.out.println(hello);

//return the message
return hello;
}

}



Do you see anything special in this class or the interface? No, you wont. So how do you convert these into webservices? Read on...


3b - Create a wsdl file:

Now that we have the interface and the class ready, lets create a wsdl file out of these java classes. Axis comes with utilities which allow you to create the wsdl file from a java file. I wrote a small ant target which will do this for me:


<!-- Sets classpath for build -->
<path id="classpath">
<pathelement path="${java.class.path}" />
<fileset dir="${lib}">
<include name="**/*.jar" />
</fileset>
<pathelement path="${classes.dir}" />
</path>

<taskdef name="axis-java2wsdl" classname="org.apache.axis.tools.ant.wsdl.Java2WsdlAntTask" >
<classpath refid="classpath"/>
</taskdef>

<target name="generateWSDL" description="Generates wsdl files from the java service interfaces">
<mkdir dir="${wsdl.dir}"/>
<axis-java2wsdl classpathref="classpath"
output="${wsdl.dir}/HelloWorld.wsdl"
location="http://localhost:8080/axis/services/HelloWorld"
namespace="http://jaikiran.com"
classname="org.myapp.service.HelloWorldService">

<mapping namespace="http://jaikiran.com" package="org.myapp.service"/>

</axis-java2wsdl>
</target>


Note: You can find the entire build.xml, that i used, at the end of this article.

You will require the org.apache.axis.tools.ant.wsdl.Java2WsdlAntTask class which is provided by axis to be in the classpath of Ant. This class comes bundled in the axis-ant.jar which i have included in the classpath of this task using the classpathref.

In this target you specify parameters like:
location - this is where the webservice will be deployed.
namespace - the namespace for your webservice
classname - the fully qualified name of the interface which you wrote in step 3a, above.
and also a mapping between the webservice namespace and your application packages.

This target will generate the wsdl file named HelloWorld.wsdl in the directory which you specified in the 'output' parameter of the target.

3c - Create the deploy.wsdd, undeploy.wsdd and the stubs:

Now that you have created a wsdl for your webservice, lets go ahead and create the deploy.wsdd (used for deploying a webservice on the server), undeploy.wsdd (used for undeploying a webservice from the server) and the required stubs for invoking the webservice from a java client.
Again, Axis provides utilities for creating these files. Axis accepts the wsdl file, which we created in step 3b as an input to create these files. Here's the Ant target which does this for us:


<taskdef name="axis-wsdl2java" classname="org.apache.axis.tools.ant.wsdl.Wsdl2javaAntTask" >
<classpath refid="classpath"/>
</taskdef>

<target name="generateWSDD" description="Generates wsdd files from the wsdl files">
<mkdir dir="${wsdd.dir}"/>
<axis-wsdl2java
output="${wsdd.dir}"
deployscope="Application"
serverside="true"
url="${wsdl.dir}\HelloWorld.wsdl">
</axis-wsdl2java>
</target>


This single target creates the deploy.wsdd, undeploy.wsdd and the stubs. As already mentioned, this target takes the wsdl file as an input which we have specified in the 'url' parameter of the axis-wsdl2java target. The files will be created in the directory mentioned in the 'output' parameter of this target. The deploy.wsdd file that gets generated will contain something like:


<!-- Use this file to deploy some handlers/chains and services -->
<!-- Two ways to do this: -->
<!-- java org.apache.axis.client.AdminClient deploy.wsdd -->
<!-- after the axis server is running -->
<!-- or -->
<!-- java org.apache.axis.utils.Admin client|server deploy.wsdd -->
<!-- from the same directory that the Axis engine runs -->

<deployment
xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">

<!-- Services from HelloWorldServiceService WSDL service -->

<service name="HelloWorld" provider="java:RPC" style="rpc" use="encoded">
<parameter name="wsdlTargetNamespace" value="http://jaikiran.com"/>
<parameter name="wsdlServiceElement" value="HelloWorldServiceService"/>
<parameter name="wsdlServicePort" value="HelloWorld"/>
<parameter name="className" value="com.jaikiran.HelloWorldSoapBindingImpl"/>
<parameter name="wsdlPortType" value="HelloWorldService"/>
<parameter name="typeMappingVersion" value="1.2"/>
<operation name="sayHelloTo" qname="operNS:sayHelloTo" xmlns:operNS="http://jaikiran.com" returnQName="sayHelloToReturn" returnType="rtns:string" xmlns:rtns="http://www.w3.org/2001/XMLSchema" soapAction="" >
<parameter qname="in0" type="tns:string" xmlns:tns="http://www.w3.org/2001/XMLSchema"/>
</operation>
<parameter name="allowedMethods" value="sayHelloTo"/>
<parameter name="scope" value="Application"/>

</service>
</deployment>


You might notice that during all these steps we never mentioned our implementing class (HelloWorldServiceImpl) in any of the targets. As you can see above in the deploy.wsdd, Axis has created its own implementing class for the HelloWorldService and provided default implementations in that class. In the deploy.wsdd file, it mentioned the implementation class as follows:

<parameter name="className" value="com.jaikiran.HelloWorldSoapBindingImpl"/>

The reason why Axis created this implementing class is that it never knew that we had created our own implementation. The input that we provided to Axis for generating the wsdd files was a wsdl file through which Axis could never have known that we already have a implementation class.

Our next step would be to modify the deploy.wsdd file to mention our implementation class, in place of Axis'. So let's change the 'className' parameter to:

<parameter name="className" value="org.myapp.service.HelloWorldServiceImpl"/>


3d - Deploy the webservice onto the server:

Now we are almost ready to deploy the webservice onto the server. But before doing that, we will have to make the HelloWorldService.class and HelloWorldServiceImpl.class available in the server's classpath so that when we use this webservice, the server wont throw ClassNotFoundException. So let's compile these 2 classes and place the class files in the %JBOSS_HOME%\server\default\deploy\axis.war\WEB-INF\classes folder. Here's the Ant target that i used to compile these classes:


<target name="compile" description="Compiles java source code">
<mkdir dir="${classes.dir}"/>
<javac destdir="${classes.dir}" classpathref="classpath" fork="true" srcdir="${compile.src}" excludes="org/myapp/service/client/**/*.java"/>
</target>


Once this is done, we are ready to deploy the webservice onto the server. Axis again provides a utility to do this. Here's the target for deploying the service onto the server. This target just invokes the org.apache.axis.client.AdminClient java class passing it the deploy.wsdd file as an argument.


<target name="deployWebservice" description="Deploys the webservice onto the server, using the wsdd file and Axis' AdminClient">
<java classname="org.apache.axis.client.AdminClient" classpathref="classpath" fork="true">
<arg value="${wsdd.dir}/com/jaikiran/deploy.wsdd"/>
</java>
</target>


Now that we have deployed the webservice, lets verify whether its deployed successfully. Let's again go to http://localhost:8080/axis . Here again lets click the "List" link to see all the available webservices. This time you will notice that our HelloWorld service is also listed over here. You can view the wsdl of this webservice, by clicking the wsdl link next to it. Our webservice has been deployed at http://localhost:8080/axis/services/HelloWorld as you can see from the wsdl contents. So let's hit this url. You will see a message like:

HelloWorld

Hi there, this is an AXIS service!
Perhaps there will be a form for invoking the service here...


4) Java client for accessing the webservice that we created:

Let's now create a simple java client which accesses the webservice that we just deployed on the server.
You might remember that in step 3c, we even created the stubs required to access the webservice. We will use these stubs in our java client to access the webservice. Here's the simple java client:


package org.myapp.service.client;

import com.jaikiran.HelloWorldService;
import com.jaikiran.HelloWorldServiceServiceLocator;

public class ServiceClient {

/**
* @param args
*/
public static void main(String[] args) {

try {

//Get hold of the webservice using the locator provided by Axis
HelloWorldService helloWorldService = new HelloWorldServiceServiceLocator().getHelloWorld();

//Invoke the method on the webservice
String message = helloWorldService.sayHelloTo("someUserName");

System.out.println("Client received: " + message);

} catch (Exception e) {
e.printStackTrace();
}
}

}


In this class you will notice that we are using HelloWorldServiceServiceLocator and the HelloWorldService which Axis generated for us. Running this client will invoke the webservice deployed on the server.


5) Ant build file

Here's the complete build.xml that i used as part of this example:


<?xml version="1.0" encoding="UTF-8"?>
<project name="MyApp" basedir=".." default="compile">

<property name="conf.dir" location="${basedir}/conf" />
<property name="build.dir" location="${basedir}/build"/>
<property name="classes.dir" location="${build.dir}/classes" />
<property name="compile.src" location="${basedir}/src" />
<property name="lib" location="${basedir}/lib" />
<property name="wsdl.dir" location="${build.dir}/wsdl" />
<property name="wsdd.dir" location="${build.dir}/wsdd" />


<!-- Sets classpath for build -->
<path id="classpath">
<pathelement path="${java.class.path}" />
<fileset dir="${lib}">
<include name="**/*.jar" />
</fileset>
<pathelement path="${classes.dir}" />
</path>



<taskdef name="axis-java2wsdl" classname="org.apache.axis.tools.ant.wsdl.Java2WsdlAntTask" >
<classpath refid="classpath"/>
</taskdef>

<taskdef name="axis-wsdl2java" classname="org.apache.axis.tools.ant.wsdl.Wsdl2javaAntTask" >
<classpath refid="classpath"/>
</taskdef>

<target name="clean-all" description="Cleans(Deletes) the contents of all output directories">
<delete dir="${classes.dir}"/>
<delete dir="${wsdl.dir}"/>
<delete dir="${wsdd.dir}"/>
</target>

<target name="build-all" description="Builds the entire project" depends="clean-all,compile,generateWSDL,generateWSDD,compileStubs,compile-client">

</target>

<target name="compile" description="Compiles java source code">
<mkdir dir="${classes.dir}"/>
<javac destdir="${classes.dir}" classpathref="classpath" fork="true" srcdir="${compile.src}" excludes="org/myapp/service/client/**/*.java"/>
</target>

<target name="compile-client" description="Compiles the webservice client" depends="compile">
<mkdir dir="${classes.dir}"/>
<javac destdir="${classes.dir}" classpathref="classpath" fork="true" srcdir="${compile.src}" includes="org/myapp/service/client/**/*.java"/>
</target>

<target name="generateWSDL" description="Generates wsdl files from the java service interfaces">
<mkdir dir="${wsdl.dir}"/>
<axis-java2wsdl classpathref="classpath"
output="${wsdl.dir}/HelloWorld.wsdl"
location="http://localhost:8080/axis/services/HelloWorld"
namespace="http://jaikiran.com"
classname="org.myapp.service.HelloWorldService">
<mapping namespace="http://jaikiran.com" package="org.myapp.service"/>
</axis-java2wsdl>
</target>

<target name="generateWSDD" description="Generates wsdd files from the wsdl files">
<mkdir dir="${wsdd.dir}"/>
<axis-wsdl2java
output="${wsdd.dir}"
deployscope="Application"
serverside="true"
url="${wsdl.dir}\HelloWorld.wsdl">
</axis-wsdl2java>
</target>

<target name="compileStubs" description="Compiles the java classes(stubs) generated by Axis using the wsdl2java task">
<mkdir dir="${classes.dir}"/>
<javac destdir="${classes.dir}" classpathref="classpath" fork="true" srcdir="${wsdd.dir}"/>
</target>

<target name="deployWebservice" description="Deploys the webservice onto the server, using the wsdd file and Axis' AdminClient">
<java classname="org.apache.axis.client.AdminClient" classpathref="classpath" fork="true">
<arg value="${wsdd.dir}/com/jaikiran/deploy.wsdd"/>
</java>
</target>

<target name="undeployWebservice" description="Undeploys webservice using the wsdd file and the Axis' AdminClient">
<java classname="org.apache.axis.client.AdminClient" classpathref="classpath" fork="true">
<arg value="${wsdd.dir}/com/jaikiran/undeploy.wsdd"/>
</java>
</target>

<target name="runWebserviceClient" description="Executes the java client which access the webservice">
<java classname="org.myapp.service.client.ServiceClient" classpathref="classpath" fork="true"/>
</target>

</project>



6) The project directory structure

This is how my project's directory structure looks like (just in case you want to create a similar one):


Sample Webservice
|
|
|------------- src
| |
| |---- org
| |--- myapp
| |---- service
| |------- HelloWorldService.java
| |
| |------- HelloWorldServiceImpl.java
| |
| |----- client
| |-------- ServiceClient.java
|
|
|------------- build
| |----- build.xml
|
|
|------------- lib
|
|----- activation.jar
|----- axis.jar
|----- axis-ant.jar
|----- commons-discovery-0.2.jar
|----- commons-logging-1.0.4.jar
|----- jaxrpc.jar
|----- mailapi_1_3_1.jar
|----- saaj.jar
|----- wsdl4j-1.5.1.jar



How to create a Queue/Topic in JBoss?

Posted on 2006-08-24 06:59:00.0 by Jaikiran [ View original post ]


Queues/Topics are known as administered objects and in jboss they can be deployed through ServiceDotXml files. Let’s name our file, myapp-destination-service.xml. The contents of the file should look like:


<?xml version="1.0" encoding="UTF-8"?>

<server>
<!--My queue, named: myAppQueue -->
<mbean code="org.jboss.mq.server.jmx.Queue"
name="jboss.mq.destination:service=Queue,name=myAppQueue">
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>
<!-- My topic, named: myAppTopic -->
<mbean code="org.jboss.mq.server.jmx.Topic"
name="jboss.mq.destination:service=Topic,name=myAppTopic">
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>

</server>




Place this file in your %JBOSS_HOME%/server/default/deploy directory and start the server.
(Note: If you are using the ‘all’ configuration or the ‘minimal’ configuration then you will have to place this file in the %JBOSS_HOME%/server/all/deploy or %JBOSS_HOME%/server/minimal/deploy directory, as appropriate).

The above queue/topic will be bound to the jndi name: queue/myAppQueue and topic/myAppTopic respectively.

Note:

1) The above file is meant for JBoss-3.2.3. Though there might be slight changes to later versions of JBoss, the basic configuration mechanism remains the same.

2) JBoss also comes with preconfigured queues/topics. These configurations can be found in the jbossmq-destinations-service.xml file which is present in %JBOSS_HOME%/server/default/deploy/jms directory


  • Subscribe to this feed:
  • ATOM