
Configuring JMS in WAS could be quite confusing due to large number of settings and configuration resources (destination, queue/topic, connection factory, activation spec).
One of the most confusing aspects of this configuration is the quality of service (QOS) settings that deal with message reliability.
It is a known fact that an out of the box WAS installation with security enabled is not entirely secure. There is a number of steps that has to be taken in order to "harden" the installation. Most of the steps are documented in the WebSphere hardening guide, which should be closely studied and followed by any WAS administrator or developer. The hardening guide, however, is a little light on the specifics regarding how to secure WAS at the OS level. For example, hardening should normally include changing file and directory permissions to restrict access to sensitive configuration files.
Why bother hardening the installation at the OS level? This helps defend against external threats, i.e., a server hosting the installation is compromised and against internal threats, i.e., an unauthorized access from inside.
Here are some of the things you can do to secure your installation on a Unix/Linux platform:
(more...)
If you're developing applications for WAS and you're new to it, this is what you need to know:
$install_root/profiles/$profile_name/logs/$server_name. The default profile name is AppSrv01 and the default server name is server1. Example:/usr/IBM/WebSphere/AppServer/profiles/AppSrv01/logs/server1. SystemOut.log is the file containing everything that was logged to standard out. Logs can also be viewed from the admin console by navigating to Troubleshooting/Logging and Tracing/server_name/Runtime.Server/Server Types/WebSphere application servers). Otherwise you have to do it from command line. Go to install_root/bin and run ./startServer.sh server_name, e.g., ./startServer.sh server1 (this assumes that your installation has only one profile defined, otherwise you may need to "cd" to the profile_name/bin directory). Make sure that you run all commands using the appropriate system account. To stop the server, run ./stopServer.sh server_name -username user_name -password password. user_name and password is the credentials of an admin account, typically the same one you use to login to the console.Applications/Application Types/WebSphere enterprise applications, click on "Install new application", select "Fast path", accept all the defaults except that on "step 2" make sure that you targeted correct servers (if you have multiple servers/clusters in your environment). Note that you can deploy a WAR file directly, you don't have to build an EAR. In this case, make sure that you set a context root on "step 4" screen of the wizard.Applications/Application Types/WebSphere enterprise applications/application_name/Context Root For Web Modules in the console. Re-start the application after the change.Applications/Application Types/WebSphere enterprise applications/application_name/Manage Modules/module_name and make the appropriate selection in the "Class loader order" drop-down (this assumes you're doing it for a WAR module).Server/Server Types/WebSphere application servers. You'll find the host name in the Host Name column. To find a port, click on your server, and expand Ports. WC_defaulthost is the HTTP port and WC_defaulthost_secure is the HTTPS port.install_root/profiles/profile_name/logs/server_name, and kill the process ID contained in the file server_name.pid. On Unix, you can simply do kill -9 `cat server1.pid` (assuming server1 is your server name). Use task manager of taskkill /PID on Windows.Buses/Your bus name/Destinations/Your destination/Queue points/Your queue point/Runtime/Messages.$install_root/profiles/$profile_name/config/cells/$cell_name.
This post is part of the series on WebSphere Application Server administration. Please subscribe to our blog if you'd like to receive updates.
Note: We offer professional services in the area of WebSphere architecture, implementation and operations. If you're looking for help with any of these tasks, please let us know.
Following are some tips for developing a JMS client for WAS.
-Dcom.ibm.CORBA.Debug=true to your JDK parameters; other debug/tracing parameters are explained here.
Note: We offer professional services in the area of WebSphere architecture, implementation and operations. If you're looking for help with any of these tasks, please let us know.
Application management, including deployment, has remained mostly unchanged since WAS 5.
WAS 7, however, introduced a new concept -- "Business Level Applications" (BLA). It would be more accurate to use the term "composite application" because this is what BLAs are -- it's a composition of Java EE applications (WARs or EARs) or other "assets".
Unfortunately, the term "composite application" is already used in a different context by IBM.
The word "asset" is another confusing and terribly overused term. In WAS7 it's a "catch all" word for any kind of artifact, including jar, zip, and, with the introduction of OSGi support, an OSGi bundle (you need to have a beta OSGI feature pack installed to be able to use OSGi).
BLAs are created by combining applications and assets together either using admin console or scripting. BLA configuration is saved under $profile_root/config/cells/$cell_name/blas. Assets are saved under $profile_root/config/cells/$cell_name/assets.
I can see two use cases for BLAs:
AdminTask.startBLA and AdminTask.startBLA provide an easy way to restart several "regular" applications.AdminTask.importAsset command. You can then reference the jar file using "SharedLibRelationship" option of AdminApp install/update commands. This will automatically create a classloader for this library (note--this might require server restart, at least for me it did). Being able to use regular administration APIs for managing shared libraries is certainly a welcome feature.Unfortunately, BLAs also have limitations:
To summarize, the BLA idea has some promise but its current implementation is too limited to be truly useful. I'm sure IBM will be evolving BLA in future WAS releases.
You can find more information about BLA in this article .
This post is part of the series on WebSphere Application Server administration. Please subscribe to our blog if you'd like to receive updates.
Note: We offer professional services in the area of WebSphere architecture, implementation and operations. If you're looking for help with any of these tasks, please let us know.
If you're a WebSphere administrator or if you're trying to automate some tasks around the IBM WebSphere line of products, you'll inevitably be using WAS scripting (a.k.a. "wsadmin"). For the record, it is also possible to use Java and JMX-based APIs for automation, but it's is more complex and less documented. So "wsadmin" scripting tool is the primary tool of trade for any WebSphere administrator.
There are several things that you need to do in order to be successful with wsadmin:
-javaoption "-Dpython.path=your_path"). Do not forget to put python libraries (the ones that come with jython) on the python path. I prefer using thin administration client as this is more flexible. I also use 2.2.1 version of jython since jython 2.1 that comes with wsadmin is just too old and misses a lot of important language features.
This post is part of the series on WebSphere Application Server administration. Please subscribe to our blog if you'd like to receive updates.
Note: We offer professional services in the area of WebSphere architecture, implementation and operations. If you're looking for help with any of these tasks, please let us know.
Most people assume that in order to run WAS admin scripts, you need to have full WAS installation available on the client machine. This is not correct. Starting with WAS 6.1, it is possible to use the so-called administration thin client instead.
The thin client has many benefits:
You'll need to make sure that you update your client jars whenever the server installation is upgraded.
Oh, and if you're using WebSphere ESB/Process Server and want to utilize some of WESB-specific admin tasks (available from AdminTask object), you're out of luck; the thin client will not support those.
This post is part of the series on WebSphere Application Server administration. Please subscribe to our blog if you'd like to receive updates.
Note: We offer professional services in the area of WebSphere architecture, implementation and operations. If you're looking for help with any of these tasks, please let us know.
You deploy a new version of your application into production environment, hit the application’s URL and get a 500 error with a long error stack and nasty “java.lang.ClassNotFoundException” in bold at the top.
“Class Not Found” exceptions could be quite tricky to troubleshoot because of the complexity of Java Web applications and application servers they run on. An average web application nowadays comes bundled with dozens of jar file (and probably thousands of classes). An average application server’s classpath is many pages long. Not to mention separately deployed libraries containing jar files shared by a group of applications. There should be little surprise that it is quite common for all these different jars and classloaders to clash with each other, get out of sync or become otherwise corrupt and mis-configured.
The list below represents a subset of all the possible causes of “ClassNotFoundException”. Hopefully this list could serve as a starting point for attacking the problem. The list was inspired by A List of Dumb Things to Check.
find . <del>name *.jar -print -exec jar -tvf {} ; | awk '/YOURSEARCHSTRING/ || /jar/ {print} ' (note-it won’t search within EAR and WAR files)jar -xvf? Does the jar indeed contain the package and class in question?versionInfo -long command.Once again, this is by no means a complete list. If anybody wants to contribute, please add a comment below and I’ll update the post.
Any developer wants to see the code changes instantaneously reflected in the application server.
However, when using WebSphere Application Server (WAS), developers usually have to go through the process of deploying an application to the server. Even though the deployment support is integrated into Rational Application Developer (RAD) or Eclipse WTP, it still introduces delays and impedes productivity. Not to mention that Eclipse WTP does not actually support WAS 6.1 runtimes, only 6.0.
This is unfortunate because actually WAS 6.1 has good support for dynamic reloading. With dynamic reloading turned on, WAS monitors changes on the file system and automatically reloads the module (i.e., all classes loaded by the module’s classloader) when it detects a change. The reloading is almost instantaneous for simple modules. For complex modules with a lot of classes or initialization logic the reloading step could take a little bit of time but it is still faster than redeploying an entire application (you should check out Java Rebel if you want a truly instantaneous deployment).
With dynamic reloading all we need to do in order to make our changes available to the server is to update class files in the location where the deployed application resides. This is especially straightforward for web application and classes under WEB-INF/classes since WAS always explodes web application archives during deployment. In case of jar files (say the ones under WEB-INF/lib) the situation is a more complicated.
Unfortunately, the location of the deployed application is usually different from the workspace where a developer makes changes. By default, deployed binaries are located under profile_root/installedApps/cell_name. While this location can be changed, the directory structure will still be somewhat different from how code is organized in the workspace.
We could write a simple Ant script to copy changes, but this again introduces a special “pseudo-deployment” step. It would be nice if we could simply make a change in Eclipse, save it and let dynamic reloading kick in without any extra steps.
Turns out that it is quite possible to make WAS and Eclipse behave this way.
First, let’s configure WAS:
Now let’s configure Eclipse. We will have to create a resource link pointing to the deployed application and configure the project to compile classes to the deployed location.
This techniques takes care of class files only. Dynamic reloading of JSP files is a different story.
Note: This has been tested only with Eclipse 3.4 and WAS 6.1 and on modules with a relatively small code base. I’d be curious to know how effective this approach is for large modules.
This post is part of the series on WebSphere Application Server administration. Please subscribe to our blog if you’d like to receive updates.
Note: We offer professional services in the area of WebSphere architecture, implementation and operations. If you’re looking for help with any of these tasks, please let us know.
Setting maximum heap size and changing other JVM parameters is a fairly common administration task. JVM configuration might be changing quite often during application development, usually as a result of performance testing.
Typically JVM parameters have to be updated for all application servers in a cell or at least for application servers that belong to a particular cluster.
Conveniently, WebSphere Application Server (WAS) supports updating JVM parameters using its administration APIs, specifically, AdminConfig object. This is illustrated by the script below.
import sys
"""
Change JVM heap size for all application servers in a cell
"""
# New heap size is passed as a parameter to the script
max_heap_size=sys.argv[0]
# Get the string with config ids of all serves
server_confids=AdminConfig.list("Server")
# Iterate over all servers - config ids are separated by \n
for server_confid in server_confids.split("\n"):
server_confid=server_confid.strip()
# obtain the type - types are APPLICATION_SERVER, DEPLOYMENT_MANAGER, NODE_AGENT, WEB_SERVER
server_type=AdminConfig.showAttribute(server_confid, "serverType")
# we're changing the heap size for application servers - we want to exclude node agents, etc.
if server_type == "APPLICATION_SERVER":
server_name=AdminConfig.showAttribute(server_confid, "name")
# this is the query to get JavaVirtualMachine configuration object for a particular server
jvm_path="/Server:%s/JavaProcessDef:/JavaVirtualMachine:/" % server_name
jvm_confid=AdminConfig.getid(jvm_path)
# "modify" accepts a list of lists - each list contains name and value (odd choice I must say, why not use tuples?)
AdminConfig.modify(jvm_confid, [["maximumHeapSize", max_heap_size]])
# Commit our changes to the repository
AdminConfig.save()
This post is part of the series on WebSphere Application Server administration. Please subscribe to our blog if you'd like to receive updates.
Note: We offer professional services in the area of WebSphere architecture, implementation and operations. If you're looking for help with any of these tasks, please let us know.
There are many instances when it is necessary to find members (servers) that constitute a cluster. For example, to script starting and stopping an application, we need to know names of servers and nodes where the application is installed. Or we may want to restart all members of a cluster after some configuration change.
As always, this is easy to do when you know what you're doing. A query-like activity in WAS environment usually heavily relies on AdminConfig object. Our example is no exception:
import sys
"""
List application servers that belong to a particular cluster
Cluster name is passed as a parameter to the script
"""
cluster_name=sys.argv[0]
# Get configID of the cluster
cluster_conf_id = AdminConfig.getid("/ServerCluster:"+cluster_name )
if not cluster_conf_id:
raise "Cluster %s does not exist!" % cluster_name
# Get confids of the cluster members
member_conf_ids = AdminConfig.showAttribute(cluster_conf_id, "members")
# AdminConfig returns the list in [], get rid of the brackets
member_conf_ids = member_conf_ids[1:-1]
print "Cluster %s has following members:" % cluster_name
# split by space
for member_conf_id in member_conf_ids.split():
# Obtain server name and node name
member_name=AdminConfig.showAttribute(member_conf_id, "memberName")
node_name=AdminConfig.showAttribute(member_conf_id, "nodeName")
print node_name+"/"+member_name
Now we can do a lot of useful things with node_name and member_name variables; for example, we can try to get an MBean of this server and check its state. Or we can attempt to restart it. I will cover this in one of the future posts.
This post is part of the series on WebSphere Application Server administration. Please subscribe to this blog if you'd like to receive updates.
It is often desirable to "push" configuration changes to nodes in the cell without having to wait for the periodic node sync process to kick in. This becomes a requirement if you want to run some kind of automated testing as part of your configuration/deployment process (which is a very good practice). For example, you may have a build process which runs HTTPUnit tests immediately after the change.
In this case, you really don't want to rely on any artificial "sleeps" and delays in your script, so triggering synchronization programmatically is the best option.
This is actually quite simple to accomplish, as illustrated by the following script:
"""
Sync configuration changes with nodes
"""
# Commit changes to the configuration repository
AdminConfig.save()
# Obtain deployment manager MBean
dm=AdminControl.queryNames("type=DeploymentManager,*")
# "syncActiveNodes" can only be run on the deployment manager's MBean,
# it will fail in standalone environment
if dm:
print "Synchronizing configuration repository with nodes. Please wait..."
# Force sync with all currently active nodes
nodes=AdminControl.invoke(dm, "syncActiveNodes", "true")
print "The following nodes have been synchronized: "+str(nodes)
else:
print "Standalone server, no nodes to sync"
This post is part of the series on WebSphere Application Server administration. Please subscribe to this blog if you'd like to receive updates.
AdminContol and AdminConfig are two key scripting objects that any WAS administrator must know by heart.
The objects are available from wsadmin WAS administration tool.
AdminConfig provides an interface to the WAS configuration repository available under profile_root/config. All AdminConfig services are provided by the Deployment Manager (assuming you're connecting remotely); there is no dependency on node agents.
AdminControl provides an interface to JMX managed beans (MBeans) in your WAS environment. In general, MBeans are only available for the resources that are running. For example, if an application server is down, the corresponding MBean will not be available.
AdminConfig and AdminContol could complement each other nicely, especially when you need to find out the status of "things" in a WAS cell. To illustrate the point, here is a simple script that prints the status of all application servers within a cell:
"""
List all application servers in a cell and print their status (up or down)
"""
# Get the string with config ids of all serves
server_confids=AdminConfig.list("Server")
#Iterate over all servers - config ids are separated by \n
for server_confid in server_confids.split("\n"):
server_confid=server_confid.strip()
# obtain the type - types are APPLICATION_SERVER, DEPLOYMENT_MANAGER, NODE_AGENT, WEB_SERVER
server_type=AdminConfig.showAttribute(server_confid, "serverType")
# we are only interested in application servers
if server_type == "APPLICATION_SERVER":
# obtain the name of the server
server_name=AdminConfig.showAttribute(server_confid, "name")
print "Checking the state of the server %s of type %s" % (server_name, server_type)
#Now we can try to get the mbean of the server. We could've used AdminConfig.getObjectName() as
#a shortcut, but for the sake of the example we'll use AdminControl explicitly
# Query to search for mbeans - note the wildcard at the end to match the rest of mbean parameters
# Note that we're simplifying a little bit since we're ignoring node names -
# server names may not be unique within cell
server_query="type=Server,name=%s,*" % server_name
server_mbean=AdminControl.queryNames( server_query )
# AdminContol returns None if there is no running mbean for this server
if server_mbean:
print "Server is up"
else:
print "Server is down!"
This post is part of the series on WebSphere Application Server administration. Please subscribe to this blog if you'd like to receive updates.
In one of the previous posts I complained that wsadmin tool (which is the main WebSphere Application Server administration tool) still relies on Jython 2.1, which is quite old.
The issue became critical when I realized that jython automatically re-compiles classes compiled with a different jython version. In my case, I was using Jython 2.2 for my Ant scripts and Jython 2.1 for wsadmin scripts. Some of the code was shared. This led to the situation of concurrent builds stepping on each other by dynamically re-compiling classes with different jython versions. The error looked something like that:
File "<string>", line 5, in ?
java.lang.ArrayIndexOutOfBoundsException: -4
at org.python.core.imp.createFromPyClass(Unknown Source)
Bugs like that are always fun to troubleshoot.
Going back to 2.1 was not an option for me since I use closures and “new classes” in quite a few places. So I tried putting jython 2.2.1 on wsadmin classpath and it worked without a hitch with thin wsadmin client. All my of wsadmin scripts work without a problem.
Here is a sample wsadmin.bat file that I use. This file utilizes thin client jars. Note how in line 85 my jython.jar (which is jython 2.2.1) is added to the classpath so it would override jython packages supplied with WAS.
One possible downside of this approach is running into issues with IBM support in case if you need to open a PMR related to wsadmin scripting.
Using AdminTask in wsadmin often results in getting ugly stack traces. In fact, AdminTask always produces a full java stack trace even when the error is fairly innocuous (e.g., a resource name was mistyped). The stack trace in this situation is pretty useless; it could actually confuse operations staff as it might be interpreted as a problem in IBM code.
It is, in fact, quite easy to deal with this situation in Jython and suppress the annoying stack trace:
import sys
from com.ibm.ws.scripting import ScriptingException
...
try:
AdminTask....
except ScriptingException:
# note that we can't use "as" because of python 2.1 version, have to use sys
print "Error:\n"+str(sys.exc_info()[1])