Maxence Button's Blog
Maxence Button's Homepage
Hi, I'm French and I've been working for over seven years with Java EE. I describe myself as something between an experimented developer, a junior architect and a BEA evangelist :) I have decided to share my knowledge, built from my experience and the issues I face while working for my clients. Feel free to drop me a line, in French or English!
Reminder on how to use EJB3 with Weblogic 10
Posted by mbutton on April 3, 2008 at 2:18 AM | Permalink
| Comments (18)
First of all, I'd like to point out the excellent tutorial by Greg Mally on using EJB3 within Workshop : http://dev2dev.bea.com/blog/gmally/archive/2007/11/using_workshop.html How to define an EJB3 ? Well, it's quite easy. According to the specification, you only have to use annotations to define your EJB. For instance, let's take the following EJB : @Stateless(
name = "PdfRetriever",
mappedName = "ejb/stateless/PdfRetriever",
description = "Gets a PDF file from the server")
@Local ({PdfRetriever.class})
@Remote ({PdfRetrieverRemote.class})
public class PdfRetrieverBean implements
PdfRetriever, PdfRetrieverRemote {
[...]
}
For specifying the interfaces (local or remote), you can choose to use only the annotations or the implementation declarations.
The use of annotations is maybe a bit quicker to read, but the implement declaration prevents you from missing an interface method. I wrote both so that you can make your choice.
As for the deployment descriptor, the ejb-jar.xml must have the correct declaration, that is to say :
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
version="3.0">
How to call it with remote interface ?
Here's the code to call the EJB :
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
props.put(Context.PROVIDER_URL,
"t3://localhost:8001");
InitialContext ctx = new InitialContext(props);
PdfRetrieverRemote ejb = (PdfRetrieverRemote)
ctx.lookup("ejb.stateless.PdfRetriever#sample.ejb.PdfRetrieverRemote");
ejb.getPdfFileFromServer("myFile.pdf");
Be aware that the JNDI name is not exactly the same as entered in the EJB definition ("ejb/stateless/PdfRetriever").
It has been postfixed with a # and the full-qualified name of the Remote interface.
How to call it with local interface ?
Note : "Local" doesn't refer to the same JVM but the same EAR.
The easiest way to call your EJB is through a Servlet thanks to an annotation.
As explained above, your servlet must reside in the same EAR than the EJB3 module.

You don't have to use JNDI to reach your EJB, just reference it that way :
@EJB
private PdfRetriever pdfRetriever;
public void myMethod () {
byte[] myPdfFile = pdfRetriever.getPdfFileFromServer("myFile.pdf");
}
Note : Due to lots of messages asking me how to call an EJB3 from a pojo, I will write some details about that, but know that this is not the way it is sensed to be used.
According to the specification, an EJB3 is to be called via an annotation in a Servlet or another EJB.
This solution lies on the "java:comp/env" mechanism.
EJB within a web application
First part : declaring the EJB
Taking the example quoted above, you will have to add an annotation to at least one servlet.
Example :
@EJB(beanInterface=sample.ejb.PdfRetriever.class, name = "ejb/PdfRetriever")
public class EjbInvoker extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
This annotation replaces the EJB declaration in the web.xml file. It makes the EJB available for all the War context.
Else you can declare your EJB in the web.xml :
<ejb-local-ref>
<ejb-ref-name>ejb/PdfRetriever</ejb-ref-name>
<local>sample.ejb.PdfRetriever</local>
</ejb-local-ref>
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd
As you can see, the attributes are different :
| Deployment descriptor |
Annotation |
| local |
beanInterface |
| ejb-ref-name |
name |
Note : With the annotation, the beanInterface attribute expects a class.
Second part : calling the EJB from the POJO
Now the EJB has been made visible within the whole web application, the code to call the EJB from the POJO is quite simple :
InitialContext ctx = new InitialContext();
PdfRetriever ejb = (PdfRetriever) ctx.lookup("java:comp/env/ejb/PdfRetriever");
Note : The lookup has been made on the name specified in "name" attribute for the annotation and "ejb-ref-name" for the DD, that is to say "ejb/PdfRetriever"
You can then manipulate your local EJB.
EJB within an EJB module
The scenario is the same than for the web application, except that the element you've got to add the EJB declaration to is now an EJB and the DD to modify is not the web.xml but the ejb-jar.xml
How to read weblogic tlog files ?
Posted by mbutton on March 26, 2008 at 6:30 AM | Permalink
| Comments (3)
What are tlog files ? Tlog files are the files used by weblogic to keep a trace of current transactions. For example, when an instance is restarted, the tlog files are used to perform the second step of a two-phase commit on a transaction that was in progress. Sometimes, when a transaction is corrupted, you've got to delete thes files to get rid of the phantom transaction. There is no need to restart a server to have them recreated. Where are they located ? Tlog files are created for every server. You can thus find some in your server directory. Ex : myDomain / servers / myServer / logs  How to read them ? These files are not human-readable. But BEA provides a tool to decrypt them. This tool is very useful to have a trace of running transactions, and know what's going on on your server. Like every other tool BEA provides, it's part of the package "weblogic". It can be found : - on WLS 8.1 and below, in the weblogic.jar
- on WLS 9 and above, in the module com.bea.core.transaction_2.0.1.0.jar
Usage: java weblogic.transaction.internal.TransactionLoggerImpl <server_tlog_path> <server_tlog_path> - path of server transaction log files e.g. /weblogic/config/mydomain/myserver/myserver To use it, I would advise to go directly where the tlog files are and type the following command : \user_projects\sample\myserver > java weblogic.transaction.internal.TransactionLoggerImpl myserver The result of this command should display something like that : If available, the information will be displayed like shown below : ![clip_image002[7]](http://dev2dev.bea.com/blog/mbutton/WindowsLiveWriter/Howtoreadweblogictlogfiles_75B9/clip_image002%5B7%5D_thumb.jpg)
Building JAX-RPC or JAX-WS webservices with Weblogic 10
Posted by mbutton on March 11, 2008 at 10:07 AM | Permalink
| Comments (2)
On Weblogic
10, you've got the choice to design your webservice following two norms :
Ø JAX-RPC
1.1
Ø JAX-WS
(aka JAX-RPC 2.0)
We are going to study the
way to design a simple webservice using standard annotations, and then to
publish it as JAX-RPC or JAX-WS webservice.
And I will describe what are the main differences between
them.
The webservice is an easy one : it's designed to receive a
file. I like to use that subject because it's a functionality that is often
needed.
import java.io.FileOutputStream;
import java.io.IOException;
import javax.jws.Oneway;
import javax.jws.WebService;
@WebService
public class PdfSaver {
@Oneway
public void savePdf (byte[] pdfFile) {
FileOutputStream fos = null;
try {
// Saving the file in "myDomain/pdf"
fos = new FileOutputStream("pdf/sample.pdf");
fos.write(pdfFile);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Note : the annotation
"@WebMethod" is useful when you have got several methods and you want only some
of them to be published. By default, if you do not write it, all methods are
exposed.
The annotation
"@Oneway" is used when your webservice does not return any value.
In your build.xml file,
you've got to declare the "jwsc" task like this :
<taskdef name="jwsc" classname="weblogic.wsee.tools.anttasks.JwscTask" />
<property name="dest.dir" value="${project}\src" />
Note : This class is in a jar called "wseeclient.jar "
located in the directory
"BEA_HOME /wlsserver_10.0
/ server / lib".
Be sure to have
it referenced in your classpath, as well as the "weblogic.jar" file, located in
the same directory.
Ant task looks like that :
<target name="build-webservice">
<jwsc srcdir="src" destdir="${dest.dir}">
<jws file="com/sample/ws/PdfSaver.java" type="JAXRPC" />
</jwsc>
</target>
Note : the type "JAXRPC" is used by default. I'm only writing it
down to be clearer.
Once published, check your
webservice is of the correct type
:
(Deployments > PdfSaverService > Configuration >
General)
Using
JAX-WSOneway"tation "exposed.ot
you want only some of them to be published.
The Ant task looks alike,
but the type which has now been set to "JAXWS" :
<target name="build-webservice">
<jwsc srcdir="src" destdir="${dest.dir}">
<jws file="com/sample/ws/PdfSaver.java" type="JAXWS" />
</jwsc>
</target>
Once published, check your
webservice is of the correct type
:
(Deployments > PdfSaverService > Configuration >
General)
<property name="dest.package" value="webservice.client.jaxws" />
<property name="dest.dir" value="${project}\src" />
<taskdef name="clientgen" classname="weblogic.wsee.tools.anttasks.ClientGenTask" />
Note : This class is in a jar called "wseeclient.jar "
located in the directory
"BEA_HOME /wlsserver_10.0
/ server / lib".
Be sure to have
it referenced in your classpath, as well as the "weblogic.jar" file, located in
the same directory.
The principle remains the
same as the generation of the webservice
: an ANT script calling a task whose type can ben determined by a simple
attribute.
<target name="build-client">
<mkdir dir="${dest.dir}" />
<clientgen type="JAXRPC"
wsdl="http://localhost:7001/PdfSaver/PdfSaverService?WSDL"
destDir="${dest.dir}" classpath="${java.class.path}"
packageName="${dest.package}" />
</target>
<target name="build-client">
<mkdir dir="${dest.dir}" />
<clientgen type="JAXWS"
wsdl="http://localhost:7001/PdfSaver/PdfSaverService?WSDL"
destDir="${dest.dir}" classpath="${java.class.path}"
packageName="${dest.package}" />
</target>
Generated
classes
The main difference is the
way artifacts are generated
:
Here's the method called
to read the file from the file system and convert it to a byte array.
private byte[] readBinaryFile() throws Exception {
File f = new File("path/to/myPdf.pdf");
FileInputStream fis = new FileInputStream(f);
byte[] tab = new byte[fis.available()];
fis.read(tab);
return tab;
}
Considering the classes
shown above, here is the client code for
calling the JAX-RPC webservice.
public void callMethodWithJaxRpcClient() {
try {
webservice.client.jaxrpc.PdfSaverService service =
new webservice.client.jaxrpc.PdfSaverService_Impl();
byte[] file = readBinaryFile();
service.getPdfSaverSoapPort().savePdf(file);
} catch (Exception e) {
e.printStackTrace();
}
}
Considering the classes
shown above, here is the client code for
calling the JAX-WS webservice.
public void callMethodWithJaxWSClient () {
try {
webservice.client.jaxws.PdfSaverService serviceJaxws =
new webservice.client.jaxws.PdfSaverService();
byte[] file = readBinaryFile();
serviceJaxws.getPdfSaverPort().savePdf(file);
} catch (Exception e) {
e.printStackTrace();
}
}
If everything went well,
you should have your file located in the directory "pdf" located just under the
domain directory.
Main differences
As shown in a previous
section, artifacts are quite differents.
The WAR generated have
different sizes :
Ø 8Kb using JAX-RPC
Ø 3Kb using JAX-WS
And the WSDL generated
quite different as well.
Take a look at them.
 |