WeBLOGic
Saturday, November 22, 2003
 

Easy Ears and Split Dir



Ok from the top here are the manual steps that should show how it fits all
together (assuming you have a shell or cmd with your wls env set) (there is
an env script in your domain dir (you can use the Config Wizard or type java
weblogic.Server from an empty directoy to bootstrap your domain) or the base
env is in $WL_HOME/weblogic81/common/bin/commonEnv.sh)

1) create a top level directory of your application (i.e. the root of your
ear)
$cd /temp
$mkdir myEar

2) create top level directories herein that map to your J2EE components
$mkdir myWebApp
$mkdir myEJB

3) "write your code" for those modules. I am lazy though so I am going to
copy it from the helloWorldEar example.

$cp
$WL_HOME/weblogic81/samples/server/examples/src/examples/splitdir/helloWorld
Ear/helloWebApp/hello.jsp myWebApp
$cp -r
c:/bea/wls81/weblogic81/samples/server/examples/src/examples/splitdir/helloW
orldEar/helloEJB/examples/ myEJB/

Then I am going to remove all the depenencies from the EJB, so I whack it
down to:

package simple.hello;

import weblogic.ejb.GenericSessionBean;

/**
* @ejbgen:session
* ejb-name = HelloEJB
* @ejbgen:jndi-name
* local = simple.hello.HelloEJB
*/
public class HelloEJB extends GenericSessionBean {

/**
* @ejbgen:local-method
*/
public String sayHello(){
return "Hello from an ejb";
}
}

Then I whack the hello.jsp to simplify and remove dependencies as well:

<html>

<
body>

<p><b>You request URI </b><%= request.getRequestURI() %></p>

<p><b>Date</b> <%= new Date()%></p>

<
/body>

<
/html>


So now I have the following:
$ pwd
c:/temp/myEar
$ find . -name "*.*" -print
.
./myWebApp/hello.jsp
./myEJB/examples/splitdir/hello/HelloEJB.ejb

4) bootstrap your build.xml
java weblogic.BuildXMLGen -user myuser -password mypass -d . .
Generated .\build.xml
You can run this tool with no args for the help.

5) lets see what ant tasks we have
$ ant

help:
[java] Buildfile: build.xml
Main targets:

appc Runs weblogic.appc on your application
build Compiles myEar application and runs appc
build.myEJB Builds just the myEJB module of the application
build.myWebApp Builds just the myWebApp module of the application
clean Deletes the build and distribution directories
compile Only compiles myEar application, no appc
deploy Deploys (and redeploys) the entire myEar application
descriptors Generates application and module descriptors
ear Package a standard J2EE EAR for distribution
redeploy.myEJB Redeploys just the myEJB module of the application
redeploy.myWebApp Redeploys just the myWebApp module of the application
undeploy UnDeploys the entire myEar application


6) we still can't build though because we don't have descriptors, but we can
bootstrap that as well.

There is a bug currently where we don't recognize webapps, so you'll have to
run this one by hand.


$ cd myWebApp
$ java weblogic.marathon.ddinit.WebInit .
$ find . -name "*.*" -print
./hello.jsp
./WEB-INF/web.xml
./WEB-INF/weblogic.xml
$ cd ..
$ pwd
C:/temp/myEar


THEN run:

$ ant descriptors
This produces:


$ find . -name "*.*" -print
./build.xml
./myWebApp/hello.jsp
./myWebApp/WEB-INF/web.xml
./myWebApp/WEB-INF/weblogic.xml
./myEJB/examples/splitdir/hello/HelloEJB.ejb
./META-INF/application.xml
./META-INF/weblogic-application.xml


(if you don't run the webinit first, the application.xml generated by "ant
descriptors" won't include your webap)


7) now we can build and deploy. NOTE.
>>>>>>>build = Compiles myEar application and runs appc
appc is an EAR compiler. It is the equivilant of ejbc for an EAR. So it
runs ejbc on ejb's and webapp descriptor vlaidation and jspc. You may NOT
want to run build as part of your normal iterative development cycle,
because as you already pointed out, it takes some time to run jspc on every
jsp and precompile them. So you may want to run this after each descriptor
tweak to validate them, or you can just do the alternative.

>>>>>>>compile = only compiles the ear, it does not run appc, this is much
much faster. This is nice for say editing a jsp file, plopping it in your
webapp, then hitting reload on your browser.

But lets just do the whole thing. AND I am going to assume your server is
running. So I type:

$ ant build deploy
lots of text screaming by
BUILD SUCCESSFUL

Total time: 11 seconds

If your not sure what context your webapp is deployed under, log into the
console, your app is under the Deployments-->Applications-->MyEar, and for
the webapp there is a testing tab that shows you your context.

Go to your browser:

http://localhost:7001/myWebApp/hello.jsp

There you go, the 7 easy steps to building a EAR with split-dir.

SO lets review a couple of things.

1) your app is in EAR format. The "src" files are in an exploded EAR
format. If you already have descriptors and code that exists, that is fine,
just put them in the right EAR location and you don't have to boostrap
descriptors. We will generate a build.xml for you as show above, and then
if you type ant build, all should work. We do maintain a pointer in the
build dir which tells the server WHERE the src is, AND when you deploy you
deploy the build directory. You can examine the simple build.xml to see how
it all fits together.

Cheers
mbg 
Friday, October 17, 2003
 

Using Resource Refs



One of the problems of J2EE is that it has a high degree of complexity. This is balanced by a set of standard enterprise APIs that have sound architecture foundations and a high degree of flexibility.

One of issues with accessing resources inside an EAR between module types is having to "hard-code" the JNDI names of the resource in the lookup code.

The classic example is a web-application accessing EJB's. In the good old days (J2EE 1.2) EJB's would be bound into JNDI and their namew would be specified in a WLS specific descriptor. You would then need to track this JNDI name either in the web-applications code or in a properties file. If you ever wanted to deploy the same EJB module in two different EAR's then you had to change the JNDI names. One featuer that provided more flexibility was a local jndi name space that allowed the same local-jndi name in two differen applications, since the local jndi naming space was scoped to the application. But you still had the issue of tracking the JNDI names of the EJBs.

Now however you can use resource refs.

1) No longer bind your EJB's into JNDI
2) In your web.xml configure references to the EJB.

So given your /helloEJB/META-INF/ejb-jar.xml entry of:


<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>HelloEJB</ejb-name>
<local-home>com.bea.examples.hello.HelloLocalHome</local-home>
<local>com.bea.examples.hello.HelloLocal</local>
<ejb-class>com.bea.examples.hello.HelloEJB</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>


In your /web/WEB-INF/web.xml you refer to the EJB via:


<ejb-local-ref>
<ejb-ref-name>ejb/helloEJB</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local-home>com.bea.examples.hello.HelloLocalHome</local-home>
<local>com.bea.examples.hello.HelloLocal</local>
<ejb-link>HelloEJB</ejb-link>
</ejb-local-ref>


The ejb-link is either the EJBName (see ejb-jar.xml descriptor snippet above) or you can use the EAR structure to specify the link like EJBjar.jar#MyEJBName.

I used WebLogic Builder to configure the EAR since I never can remember the syntax

Here is a screen shot:



Here is src to build this example with 8.1. Unzip, cd to simpleEar and type ant.

Cheers
mbg
 
 

Load Order of an Application



So I haven't blogged in a while mostly because I have been busy with other stuff. And I don't think I am much of a blogger anyway. This blog is a little different. But nonetheless here goes.

Someone posted on the newsgroups that load ordering didnt seem to be working in WLS 7.0. So I wrote a small isolated reproducible test case (88 times out a 100 this is the quickest way to get your problem solved, but it takes a little bit of work on your part. But if not on your part then on someone elses, more than likely support or a CCE engineer, regardless someone has to do this write a small test. You can't just send us your test cause it probabaly aint small, aint isolated and there fore doesnt help in reproducing the problem). My config.xml looks like this:

    <Application Deployed="true" LoadOrder="1"
Name="simpleEAR701_exploded" Path="C:\tmp\dist\simpleEar1.ear" TwoPhase="true">
<EJBComponent Name="helloEJB" Targets="myserver" URI="helloEJB"/>
<WebAppComponent Name="web" Targets="myserver" URI="web"/>
</Application>
<Application Deployed="true" LoadOrder="2"
Name="simpleEAR702_exploded" Path="C:\tmp\dist\simpleEar2.ear" TwoPhase="true">
<EJBComponent Name="helloEJB" Targets="myserver" URI="helloEJB"/>
<WebAppComponent Name="web" Targets="myserver" URI="web"/>
</Application>


There is a serlvet in each ear that is configured to load on start up and
it logs to the weblogic log "ear init 1" or "ear init 2", so based on this
configuration ear init 1 should come first, but it doesnt. A bug. :(
Here is the src. And ear1 and ear2.
Note I was lazy and if you do build this you will have to change 4 files to make
ear1 and ear2, change the each file the value in bold to 1 or 2.


1) build.xml


<property name="app.name" value="simpleEAR701" />

2) application.xml


/web1



3) weblogic-ejb-jar.xml
com.bea.examples.hello.HelloEJB1



4) HelloWorldServlet.java

log("\n\n****************************\n"
+init ear 1"
+"\n*****************************\n\n");


 
Friday, June 20, 2003
 

How do I share resources in an EAR amongst J2EE modules?


The most common scenario of this is how do I share classes across more than one J2EE module within an EAR. This is a real hole in the J2EE specification.

J2EE 1.3 Specification
J2EE.8.1.1.2 Dependencies

A .jar file can reference another .jar file by naming the referenced .jar file
in a Class-Path header in the referencing .jar file’s Manifest file. The referenced
.jar file is named using a URL relative to the URL of the referencing .jar file.
The Manifest file is named META-INF/MANIFEST.MF in the .jar file. The Class-
Path entry in the Manifest file is of the form
Class-Path: list-of-jar-files-separated-by-spaces


app1.ear:
META-INF/application.xml
ejb1.jar Class-Path: util.jar
ejb2.jar Class-Path: util.jar
util.jar

The problem with this is that you have to use Manifest classpath in every module that would share the EAR level resource. Any resources, such as properties files or user xml configuration files, that needs to be loaded must exist inside the shared jar itself, in the example above util.jar. This is problematic for several reasons.


  1. Maintaining Manifest classpath is tedious. Ant makes it possible [despite a nasty bug in 1.4 that whipes out META-INF directories when you use the manifest attribute], but while the possibility in ant can be abstracted behind a single "bulid" target there is still quite a bit of complexity beneath the covers.

  2. Manifest classpath's only work with an archive. And in the iterative development cycle you don't really want to be archiving everytime. Think about it, you make a change to your properties file, you have to repack the archive of util.jar and then repack the .ear archive, and the first thing that most app servers do with an archive is unpack it to deploy it. What you really want is to develop in an exploded format, edit the properties file in place, and do a simple redeploy. A much faster iterative code/build/test loop.



But J2EE doesn't allow for this. The one thing that would seem to make more sense is an EAR level Manifest classpath, but the spec seems to discourage this, contiuing on in the Dependencies section:

The requirement [regarding Manifest classpath dependencies] here
only applies to JAR format files containing class files or resources to
be loaded directly by a standard ClassLoader; such files are always
named with a .jar extension. It does not cover other JAR format files such as
.ear files that are not typically loaded directly by a ClassLoader, but see the
specifications for such files for details.


This is why in WebLogic 8.1 we introduced a EAR/APP-INF directory that is analogous to the WEB-INF directory for webapps. And it works for the archived as well as for exploded case. Just drop classes/jars/resoruces into this directory and they are accessible to all modules within the ear. 
Wednesday, May 28, 2003
 

How do I install Roller on WebLogic 8.1


The Roller dudes went silent on me, I took more interest in a wiki (even though I know that Roller has a wiki plugin) and I got busy with other stuff, so nothing is really happening right now


So I am interested in getting a J2EE Blogger up and running inside BEA, so I googled my way to Roller. While the instructions are all about Tomcat and or Resin with MSSQL. I of course took the route of installing on WebLogic and chose to use Pointbase as my DBMS.

I'll keep this upto date as I go and add the finalized supporting docs when I get there.

The steps are pretty much the same as the official Roller installation guide.

So I was able to get the schema created in pointbase but I had a SQL exception executing a sql statement. This ended up being because while my ant script was generating the pointbase DB and schema, I had create=true in my JDBC URL, and when I was starting pointbase it was not picking up the DB files I had created and so it was creating a brand new one. I only figured this out after I got completely frustrated by mysql installation and authentication. Once I figured this out pointbase required other sql tweaks so I went back to mysql. I am not stuck on the usermanager initializing properly.




Prerequisites


You should download and install WebLogic 81.


Download WebLogic RollerProject


Here is v.1 of the rollerProject. Unzip (unjar) it to the place where you want your roller webapp to go.

cd mystuff
jar xvf rollerProject.zip
You can start with
rollerProject2/README.txt

Basically thats it, now you need to go to step 3.

Unpack the downloaded Roller ZIP or TAR file


unzip/tar the roller webapp, which has a root node of "roller", into:

./rollerProject2/src/ roller/build/

so that it looks like:

./rollerProject2/src/roller/build/roller/WEB-INF

Configure DB, Datasource, Server and Security mappings in WebLogic


You can just cd rollerProject2/setup and type ant. It will tell you what to do next.

You will have to make the following tweaks to roller.
1) edit ./rollerProject/src/rollerEar/roller/WEB-INF/tlds/oscache.tld
comment out:

<!--<attribute>
<name>encoding</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
-->

The method encoding doesn't exist in the tag-class com.opensymphony.module.oscache.web.tag.CacheTag

2) if you try to run jspc on the webapp (./rollerProject2/src/rollerEar/build.xml) it will fail because one of the test jsp's is invalid.
Edit ./rollerProject/src/rollerEar/roller/dstest.jsp
modify:
<%@ page import="javax.sql.Connection" %>
to:
<%@ page import="java.sql.Connection" %>

Start WebLogic


In a shell that has the WebLogic environment set cd ./rollerProject2/domain
and execute startRoller.sh/cmd

Pointbase Problem


ERROR [ExecuteThread: '14' for queue: 'weblogic.kernel.Default'] [org.roller.business.hibernate.RefererManagerImpl] RefererManagerImpl.getDaysPopularWebsites(28
1) | Getting popular websites java.sql.SQLException: Invalid table name "ROLLERUSER" specified at position 50.

at com.pointbase.net.netJDBCPrimitives.handleResponse(Unknown Source)
at com.pointbase.net.netJDBCPrimitives.handleJDBCObjectResponse(UnknownSource)
at com.pointbase.net.netJDBCStatement.executeQuery(Unknown Source)
at weblogic.jdbc.wrapper.Statement.executeQuery(Statement.java:316)
at org.roller.business.hibernate.RefererManagerImpl.getDaysPopularWebsites(RefererManagerImpl.java:236)
at org.roller.presentation.MainPageAction$Data.getPopularWebsites(MainPageAction.java:80)
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:324)
at org.apache.commons.beanutils.PropertyUtils.getSimpleProperty(PropertyUtils.java:1185)
at org.apache.commons.beanutils.PropertyUtils.getNestedProperty(PropertyUtils.java:772)
at org.apache.commons.beanutils.PropertyUtils.getProperty(PropertyUtils.java:801)
at org.apache.struts.util.RequestUtils.lookup(RequestUtils.java:851)
at org.apache.struts.taglib.bean.DefineTag.doEndTag(DefineTag.java:266)
at jsp_servlet.__main._jspService(__main.java:354)
at weblogic.servlet.jsp.JspBase.service(JspBase.java:33)
at weblogic.servlet.internal.ServletStubImpl$ServletInvocationAction.run(ServletStubImpl.java:1053)

mysql hell


So I turned to installing mysql. I am currently on my fifth install of mysql and finally got it working. I am pretty appalled by the out of the box expereince and the installation process, particularly around authenticaiton.

First I didn't install it to the default location, I installed it to c:/programs/mysql413/, and with this configuration I was unable to start the DB using either my.cnf in the root of c:/ or my.ini in c:/WINNT (It seems a pretty bald limitation to not allow you to start the DB and point to a configuration file).

Then I deleted and installed to the default, c:/mysql, and while I was able to get the mysql DB running, and I thought I followed instructions for step 3 "create roller tables", however when trying to execute "grant all on roller.* to roller identified by 'tiger';" I kept getting the error Access denied for user: '@localhost'. The default user and pass for the mysql installation seems rather vague. So.... I deleted and installed again.

Third installation fo mysql went fine, this time when I ran winmysqladmin I entered in user of scott and password of tiger, but I am still unclear as to if there is a user root and what its password is? This time I followed the step 3 more carefully and successfully created the roller tables. HOWEVER, NOW when I attempt to make a connection to the the DB: Server connection failure during transaction. Attempted reconnect 3 times. Giving up.

My goal now became to see if I could get root authenticating.

shell>mysqladmin -u root password new_password didn't work for me. Setting a password and user when launching winmysqladmin did not work either.

So on my fifth install, I finally noticed in the installer that more docs could be cound on the mysql.org site at http://www.mysql.org/documentation. Before I had gone looking for problems on mysql.org under support, and tried searching for newsgroups. All of this type of stuff is under documentation.

The key doc was this one: http://www.mysql.com/doc/en/Default_privileges.html.

shell> mysql -u root mysql (this says use the mysql db)
mysql> update user set password=PASSWORD('new_password') where User = 'root';

Now I could do:

shell>mysqladmin -u root -p
and authenticate!

Now I followed step 3 again and created the roller tables.

This time (my sql skills were returning), I could see that I had a roller user in the user table.

mysql> select User, password from user;
+--------+------------------+
| User | password |
+--------+------------------+
| root | 67457e226a1a15bd |
| root | |
| | |
| | |
| roller | 3b920bf545feea6d |
+--------+------------------+

(Still have no idea why I have two root users or two blank ones for that matter either.)

Yet and still I was getting Authentication denied for roller@127.0.0.1 Lance on the roller list suggested updating domain on the user table to localhost. There is no domain column its actually the Host column, but updating to localhost for the user roller still failed. Then I decided to try 127.0.0.1.

upatet user set Host='127.0.0.1' where user='roller';

VOILA, I could now finally connect.

And I deleted those extra blank users and root user with no password. 
Monday, May 26, 2003
 

How do I create a new domain?


You can of course always use the Configuration Wizard. However if you want something a little more lightweight. You can do the following:

1) start a shell/cmd and setup your environment
2) create a directory to hold your domain
cd /bea/user_projects
mkdir myserver
cd myserver
3) then just type "java weblogic.Server"
This will start WebLogic, prompt you for user name and password, ask you if you want to create a configuration and your on your way.

This is an easy way to bootsrap your configuration.

Cheers
mbg 
 

How do I write a build.xml for an EJB that will work in WLS 70 and WLS 81



In 8.1 we have introduced a lot of new ant tasks to make your lives easier.

( wlconfig and wlappc and wlcompile and wldeploy )

However someone recently asked how they could build an EJB in 7.0 and 8.1 using the same ant taks.

Here is an example. I took the 8.1 ejb20/basic/statelessSession ejb example and modified.

1) copy it it to a new directory.
2) set up your environment.
3) since I want this to build under 8.1 as well as 7.0 I modified the weblogic-ejb-jar.xml doctype to be:

<!DOCTYPE weblogic-ejb-jar PUBLIC 
'-//BEA Systems, Inc.//DTD WebLogic 7.0.0 EJB//EN' 
'http://www.bea.com/servers/wls700/dtd/weblogic-ejb-jar.dtd'>

4) modify the build to build a temp ejb jar first. (This is another reason that 8.1 is great, with appc no more temp jars it takes care of everything for you).

<target name="jar.ejb" depends="compile_ejb">
<jar jarfile="${temp}/PRE_ejb20_basic_statelessSession.jar"
basedir="${build}"
update="yes">
</jar>
</target>

5) add an entry for ejbc

<taskdef name="ejbc" classname="weblogic.ant.taskdefs.j2ee.Ejbc"/>

and

<target name="ejbc" depends="jar.ejb">
<ejbc debug="${debug}" keepgenerated="true"
source="${temp}/PRE_ejb20_basic_statelessSession.jar"
target="${dist}/ejb20_basic_statelessSession.jar"
/>
</target>

Now this will build against 7.0 and 8.1, you can download the entire thing and take a look.

Cheers
mbg 
Saturday, May 24, 2003
 

How do I monitor from the command line the number of HttpSessions for my web-app?


I am going to use the examples server that ships with WebLogic 8.1 as the "example".

1) start the Examples Server from the start menu.

2) You can access the Session Servlet in your browser to just check out what we are working with:

http://localhost:7001/examplesWebApp/SessionServlet

3) You can of course use the console to session monitoring. But this is about command line usage. So we are going to first walk through using JMX.

JMX to get Session Monitoring


Before we even start you'll need a cmd or sh will your WebLogic environment set. $BEA_HOME\weblogic81\samples\domains\examples\setExamplesEnv.cmd

Next you may need to read up on JMX, but think of it simply as standard way to lookup and "do" management (get/set/invoke) on objects that are bound into a jmx management server. WLS hosts a JMX server and has an implementation. We expose a bunch of our runtime via JMX interfaces.

http://e-docs.bea.com/wls/docs81/javadocs/weblogic/management/runtime/package-summary.html

Specifically what you want, HttpSession count lives on the WebAppComponentRuntimeMBean:

weblogic.management.runtime.WebAppComponentRuntimeMBean.html#getOpenSessionsCurrentCount()

So how do we get at this?

We ship a command line admin tool.

weblogic.Admin

Which has full documentation at here.

First we need to find the right object name (JMX uses object names as the "primary key" for a managed object) of the WebAppComponentRuntimeMBean.

(While weblogic.Admin requires of course -url,-username,-password I have a mks function aliased to admin in myprofile that defaults all that stuff so just replace admin with weblogic.Admin and all the required args, I am not going to type the full command every time.).

admin get -pretty -type WebAppComponentRuntime -property Name

This will spew out a list "names" that correspond to each of the web apps deployed on the examples server (Name in my command doesn't refer to the jmx object name [even though that also gets printed in the return], it refers to the unique Name in the xml configuration). The one that we want is:

MBeanName: "examples:ApplicationRuntime=examplesServer_examplesWebApp,Location=e
xamplesServer,Name=examplesServer_examplesServer_examplesWebApp_examplesWebApp,S
erverRuntime=examplesServer,Type=WebAppComponentRuntime"
Name: examplesServer_examplesServer_examplesWebApp_examplesWebApp

The MBeanName and everything in quotes is the jmx object name, we'll need this to query the JMX server to get our OpenSessionCurrentCount.

Next we invoke weblogic.Admin again:

admin get -pretty -mbean "examples:ApplicationRuntime=examplesServer_examplesWebApp,Location=e
xamplesServer,Name=examplesServer_examplesServer_examplesWebApp_examplesWebApp,S
erverRuntime=examplesServer,Type=WebAppComponentRuntime" -property OpenSessionsCurrentCount

Which returns:

MBeanName: "examples:ApplicationRuntime=examplesServer_examplesWebApp,Location=e
xamplesServer,Name=examplesServer_examplesServer_examplesWebApp_examplesWebApp,S
erverRuntime=examplesServer,Type=WebAppComponentRuntime"
OpenSessionsCurrentCount: 1372

(I used a simple java class to generate a bunch of load on that particular servlet).

A couple of notes and caveats. Even though the interface name has MBean on the end. ServerMBean and WebAppComponentMBean, you don't use the MBean when you ask for the type using weblogic.Admin. Even though the interface has getOpenSessionsCurrentCount, you omit the get.

You'll also note that using jmx object name syntax is kind of ugly. I'll update this later with a way to do this in ant that is much easier. In the meantime you can read http://edocs.bea.com/wls/docs81/admin_ref/ant_tasks.html#1023006 for more info if you want to figure it out on your own.

Cheers
mbg





 
Answer to questions regarding WebLogic Server.

ARCHIVES


Powered by Blogger