Who’s On Phirst

Official blog of Phurnace Software.

Category >> Java

Posted by: Daniel Nelson on

Phurnace's VP of Products and Co-Founder, Daniel Nelson, wrote a blog posting for one our partners, Electric Cloud, earlier this week. Here is a link to their blog and here is his post.

In the software development lifecycle the results need to ultimately get out into production. The application must make it onto the server, the server needs to be configured and all of the properties, paths and settings need to be correct to get the value of the application. Those in the data center often refer this to the last mile. And it is often a real bear. Seems more like 10 miles at times. Sophisticated and robust tools like ElectricCommander have automated almost all of the steps in the process, but rely on home-grown scripts to lay the applications down on app servers. Why? It is actually a logical approach if you have no alternative. Every environment is different. Every app has different settings for WebSphere (or WebLogic or JBoss) and there is no way to anticipate those differences. Therefore – the last mile is unique to each customer and each app –the IT or dev teams write scripts. It takes skilled resources and the scripts are always in need of attention. Not anymore. STOP. That is no longer necessary. What if ElectricCommander could hand off the EAR file to a software tool that has already pre-built a model of the environment and has made all of the JDBC, JMS, and application bindings for you? What if it required NO scripting? What if the “last mile” was now automated and under the control of your build and release system? Ta Da ! It is now. Phurnace Software is an auto deployment and configuration tool that will eliminate custom scripting. And you can drive it all from within ElectricCommander. The last mile is now just a step away.

In java
Comment (0) Read More...


Posted by: Wesley Willard on

One of the hottest technologies right now in server-side development right now is OSGi (formerly known as the Open Services Gateway initiative). As the underlying framework on which the Eclipse Project's runtime is based (since 3.0), this technology is starting to garner a lot of attention for its abilities to allow the development of "bundles" (or, "plugins"). This has enabled the popularity of Eclipse to grow by leaps and bounds, as plugins can be quickly added or updated.

OSGi has moved beyond being "just" a very powerful piece of the Eclipse Project, and is rapidly gaining traction amongst enterprise application servers. It offers a mechanism for resolving complex classloading issues, which often cause problems for the developers of services for the application servers. It also provides the ability to control the visibility of the implementation details, which serves to prevent unintended coupling between bundles. By default, all packages in a bundle is private, and can only be visible outside of the bundle by explicit exporting. By enforcing these visibility rules, unnecessary dependencies in the software are avoided, allowing for independent development, and versioning of bundles. OSGi manages the life cycle of a bundle, from start to stop, and enforces security concerns at each step of the way. Also, OSGi is capable of functioning as a standalone container, which allows bundles to be tested without the need for a full-blown application server environment.

With the release of the SpringSource Application Platform, SpringSource has embraced OSGi in a big way, building its application server on top of the Eclipse Project's Equinox OSGi runtime environment. From the release announcement, these quotes from SpringSource CEO Rod Johnson stand out with regard to SpringSource's commitment to OSGi:

"It is the first product that built on a modern technology basis. Java EE compliance is no longer the be all and end all. We've got a competitive advantage because we have a clean new code base. We have designed and delivered to meet the requirements of today and not those from the last 10 years."

"The OSGi technology used is a fundamental next generation technology."

JBoss Application Server 5 is nearing its long-awaited release. In contrast to SpringSource's approach, JBoss is definitely hedging its bets, that while OSGi is definitely a major technology force, it might be prudent to be a little cautious in adopting it wholesale. By abstracting its interface to the component model, the JBoss Microcontainer will allow native support of POJO's, legacy MBeans, as well as OSGi. Its pluggable architecture model will also allow the flexibility to work with other component models that will be developed in the future.

In this article, Open Source analyst firm Redmonk's Michael Cote is quoted as saying:

"Rather than build their core on OSGi, they're building the core on their own stuff, and supporting OSGi as a sort of way of using that JBoss-specific core," he said. "The hedge there being that they can add on support for whatever comes into fashion if OSGi becomes tomorrow's bell-bottoms. If you have the time to build an architecture that lets you hedge like that, it's usually a good thing."

So, while both Spring and JBoss are definitely adding OSGi to the mix, their approaches reflect very different approaches. It will be interesting to see if one approach is better than the other.

In Spring FrameworkOSGiJBoss
Comment (0) Read More...


Posted by: Pete Pickerill on

Anyone who’s worked with J2EE application servers has more than a passing familiarity with XML. It’s the weapon of choice for configuration in the 3 platforms I’ve spent most of my time working with; JBoss, WebLogic, and WebSphere. When I first started working at Phurnace, I would verify these files by hand using a diff tool that could handle single documents or a directory tree. I would compare a ‘known good’ configuration to the configuration produced by Phurnace Deliver. This worked great while I was getting my feet wet and finding my way around each platform’s configuration peculiarities.


For obvious reasons, this method sucked a lot after I got a handle on the different configuration conventions used by each platform. The process was incredibly monotonous and error prone. My mind would start to wander as I robotically clicked through the differences in dozens of XML files. Most of the time the differences were expected due to system generated unique IDs or environmental differences. I decided I needed to automate this process simply because I dreaded doing it manually. Because we were dealing with XML, XPath seemed to be the obvious choice for programmatic validation. So I just needed to whip up some XPath expressions and a simple Java class to resolve them and I was done. No bubbles, no troubles. Right?


Well I was forgetting that a WebSphere profile with one node and one server contains more than 100 individual XML files ranging in size from <1K to 600K+. If I thought using the diff tools was tedious, it was nothing compared to generating thousands of XPath expressions by hand. Plus, every time the product expanded into new areas of configuration, I was looking at hours of updating the automation data to keep it current. I needed a tool that would generate these XPath expressions for me. I had some specific needs that weren’t addressed by the sample classes and open source solutions I was finding on the web so I decided to write my own. Keep in mind:

 

  • Coding isn’t my forte. You may find bone-headed logic or hacky work-arounds. But for my purposes it works and it’s quick. Consider it your chance to test the tester and file a bug by leaving a comment. I’d love to get feedback and improve it!
  • This is a simplified version of the class I use and it works fine on simple XML. This sample class has some limitations. It doesn’t handle namespace designations and I haven’t added handling for special characters. I encourage you to play around with it and add methods that suit your purposes.

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.apache.commons.lang.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class XPathGenerator {

/*
* fileList - a list of files to generate XPath expressions from xpath - an
* xpath instance used to verify generated xpaths
*/
private static List fileList = new ArrayList();
private static XPath xpath = XPathFactory.newInstance().newXPath();

/*
* Simple utility method that checks for whitespace at the beginning a text
* node
*/
private static boolean isWhiteSpace(String nodeText) {
if (nodeText.startsWith("\r") || nodeText.startsWith("\t")
|| nodeText.startsWith("\n") || nodeText.startsWith(" "))
return true;
else
return false;
}

/*
* Simple utility method to verify brutishly assembled xpath expressions
*/
private static void checkXPath(String xpathExpression, Node node) {
Object xpathCheck;
try {
xpathCheck = xpath.evaluate(xpathExpression, node
.getOwnerDocument(), XPathConstants.BOOLEAN);
if (xpathCheck.toString() == "true") {
/*
* print the file/xpath combo to use for future verification For
* Example:
* file:/C:/tmp/sample.xml=/rootNode/firstChild/firstGrandChild
* [@attrib="value"][text()="some text"]
*/
System.out.println(node.getOwnerDocument().getDocumentURI()
+ "=" + xpathExpression);
}
} catch (XPathExpressionException xpe) {
System.out.println("\n\n" + xpathExpression);
xpe.printStackTrace();
}
}

/*
* Simple utility method to check for a text node on the currenrt XML
* element
*/
private static boolean hasValidText(Node node) {
String textValue = node.getTextContent();

return (textValue != null && textValue != ""
&& isWhiteSpace(textValue) == false
&& !StringUtils.isWhitespace(textValue) && node.hasChildNodes());
}

/*
* Simple utility to check for attributes on the current element
*/
private static boolean hasValidAttributes(Node node) {
return (node.getAttributes().getLength() > 0);

}

/*
* Build XPath attribute list for individual XML Element Nodes Iterate
* through all attribute nodes and build a string that can be included in an
* XPath expression to validate an XML document. Resulting string will look
* like: [@attrib1="value1" and @attrib2="value2"] Skip this if the
* attribute list is empty.
*/

private static String buildAttribString(Node node, String pathExpr) {
NamedNodeMap nnlist = node.getAttributes();
pathExpr = pathExpr + "[";

int attribCount = 0;
// iterate over attributes
for (int i = 0; i < nnlist.getLength(); i++) {
// grab attribute name and value
String attribName = nnlist.item(i).getNodeName();
String attribValue = nnlist.item(i).getNodeValue();

// if we've already added attributes to the path expression append
// the current one
if (attribCount > 0) {
pathExpr = pathExpr + " and ";
}

pathExpr = pathExpr + "@" + attribName + "=\"" + attribValue + "\"";
attribCount++;
}

pathExpr = pathExpr + "]";

return pathExpr;
}

/*
* processNode checks for attributes and text nodes on an xml node and
* process them accordingly
*/
public static NodeList processNode(Node node) {

if (hasValidAttributes(node) || hasValidText(node)) {
String pathExpr = "/" + node.getNodeName();

// check for attributes
if (hasValidAttributes(node)) {
pathExpr = buildAttribString(node, pathExpr);
}

// Make a copy of node to preserve it's state
Node tmpNode = node;

// Build pathExpr for XPath Expression by working backward through
// the XML until we hit the document node.
while (tmpNode.getParentNode() != null
&& tmpNode.getParentNode().getNodeType() != Node.DOCUMENT_NODE) {

tmpNode = tmpNode.getParentNode();
String nodeName = tmpNode.getNodeName();

if (hasValidAttributes(tmpNode)) {
String attribString = buildAttribString(tmpNode, nodeName);
pathExpr = "/" + attribString + pathExpr;
} else {
pathExpr = "/" + nodeName + pathExpr;
}
}

if (hasValidText(node)) {

/*
* Build XPath text value expression to verify text values for
* node. This is a little tricky because linebreaks, tabs and
* spaces included in the XML document are considered text
* nodes.
*/

// Copy original node to a textNode to preserve state of
// original node for future operations
Node textNode = node;

/*
* This check iterates through child nodes of the original node
* until it reaches the next element node. As long as the node
* is not null, starts with white space and is not an element
* node, move on to the next node
*/
while (textNode != null
&& isWhiteSpace(textNode.getTextContent()) == true
&& StringUtils.isWhitespace(textNode.getTextContent())
&& textNode.getNodeType() != Node.ELEMENT_NODE) {
textNode = textNode.getFirstChild();
}

/*
* If the text content of the current node is not null, doesn't
* start with whitespace and has child nodes, we grab the text
* and frame it into an XPath text argument. A sample element
* and it's resulting text argument:
*
* some text here YIELDS
* element1[text()="some text here"]
*
* NOTE: The check for child nodes prevents us from creating a
* blank text argument for self contained elements (example:
* )
*/
pathExpr = pathExpr + "[text()=\""
+ StringUtils.strip(textNode.getTextContent()) + "\"]";

}

checkXPath(pathExpr, node);
}
// gather children and return
return node.getChildNodes();
}

// This function takes a group of nodes and generates XPath expressions for
// them until it runs out of nodes
public static void processNodeList(NodeList nodelist) {
for (int i = 0; i < nodelist.getLength(); i++) {
if (nodelist.item(i).getNodeType() == Node.ELEMENT_NODE
&& (hasValidAttributes(nodelist.item(i)) || hasValidText(nodelist
.item(i)))) {
processNode(nodelist.item(i));
}
processNodeList(nodelist.item(i).getChildNodes());
}
}

// This function takes the cmd line argument and adds to fileList all files
// in the directory and it's subdirectory
private static void processDir(File dir) {
File[] fileArray = dir.listFiles();

for (int i = 0; i < fileArray.length; i++) {
if (fileArray[i].isFile()) {
if (fileArray[i].toString().endsWith(".xml")) {
fileList.add(fileArray[i]);
}
} else if (fileArray[i].isDirectory()) {
processDir(fileArray[i]);
}
}
}

// This starts the process of an individual XML file
private static void processXML(File xmlFile) throws SAXException,
IOException, ParserConfigurationException, XPathExpressionException {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
factory.setIgnoringComments(true);

DocumentBuilder parser = factory.newDocumentBuilder();
Document doc = parser.parse(xmlFile);

NodeList startlist = doc.getChildNodes();

processNodeList(startlist);
} catch (Exception e) {

}
}

/*
* Entry point. Pass in the xml file or top level directory of a group of
* files to generate XPath expressions for them.
*/

public static void main(String[] args) {
File startDir = new File(args[0]);
try {
if (startDir.isFile()) {
processXML(startDir);
} else if (startDir.isDirectory()) {
processDir(startDir);
for (int i = 0; i < fileList.size(); i++) {
processXML(fileList.get(i));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

In Xpath ExpressionsXML
Comment (3) Read More...


Posted by: Wesley Willard on

The Spring Framework has become the most popular open source application framework in the Java space in recent years. One of its most powerful features is its ability to allow developers to create Spring Beans, which can be configured together to create an application's object graph, or data structure. The framework provides a consistent interface to accessing these beans which avoids unnecessary dependencies between components.

JMX (Java Management Extensions) is a technology that enables the configuration, instrumentation, and monitoring of Java applications of all sorts, both J2SE and J2EE. It has gained wide-spread acceptance in the Java community as the standard API for these tasks. JMX provides access to MBeans (JMX's version of Spring's Beans), which compose its management interface. This is handled through a software layer known as the MBeanServer.

One useful piece of the Spring Framework is its direct support for JMX. Spring provides the ability to register its Beans in an MBeanServer, which can then be interrogated and modified by management applications by Spring Bean interface methods. The interface to Spring Beans is more intuitive and easier to use than the MBean interface, and abstracts many complicated details.

The follow example shows how Spring JMX can be used to provide remote management capability of its Beans. It will illustrate both server and client configuration and code. It will assume some Spring and JMX knowledge.

First, I create the Spring server-side application context configuration:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
 "http://www.springframework.org/dtd/spring-beans.dtd"> 
 
<beans>
    <bean id="registry" class=
"org.springframework.remoting.rmi.RmiRegistryFactoryBean">
        <property name="port" value="1090"/>
    </bean>
    
    <bean id="exporter" 
class="org.springframework.jmx.export.MBeanExporter" 
lazy-init="false"
         <property name="beans">
             <map>
                 <entry key="spring:name=jmxBean">
                     <ref local="jmxBean"/>
                 </entry>
             </map>
         </property>
         <property name="assembler" ref="assembler" />
         <property name="server">
             <ref local="mbeanServer"/>
         </property>
    </bean>
 
    <bean id="mbeanServer" 
        class="org.springframework.jmx.support.
MBeanServerFactoryBean"/> <bean id="jmxBean" class="com.phurnace.JmxBeanImpl"> <property name="name"> <value>Daffy Duck</value> </property> <property name="rating"> <value>5</value> </property> </bean> <bean id="jmxAttributeSource" class="org.springframework.jmx.export.annotation.
AnnotationJmxAttributeSource"/> <bean id="assembler" class="org.springframework.jmx.
export.assembler.MetadataMBeanInfoAssembler"> <property name="attributeSource" ref="jmxAttributeSource"/> </bean> <bean id="serverConnector" class="org.springframework.jmx.support.
ConnectorServerFactoryBean"> <property name="objectName" value="connector:name=rmi"/> <property name="serviceUrl" value="service:jmx:rmi://localhost/jndi/rmi://localhost:
1090/myconnector"/> </bean> </beans>

The MBeanExporter class is used to specify the Spring Beans that are to be exposed via JMX by the MBeanServer. The MBeanServer is implemented by the Spring MBeanServerFactoryBean class. In this example, it will expose the specifed Beans via RMI. If there is an existing MBeanServer, such as in a web container like Tomcat or JBoss, Spring JMX will use that one. Spring also allows for the specification of an RMI registry for the MBeanServer. It will be started when the application context file is loaded.

The AnnotationJmxAttributeSource and MetadataMBeanInfoAssembler classes are used allow Java 5 Annotations to indicate which classes and methods which will be exposed in the MBeanServer.

The final bean in the configuration file configures a ConnectorServerFactoryBean to provide remote access to the Spring Beans. This connector will be running over RMI, on port 1090.

Now, I configure the Spring Bean (jmxBean), which looks a whole lot like a standard Java Bean:


//
// Interface class
//
package com.phurnace;

public interface JmxBean {
    public String getName();
    public void setName(String name);
    public int getRating();
    public void setRating(int rating);
}



//
// Implementation of JmxBean interface
//
package com.phurnace;

import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedResource;

@ManagedResource(objectName=
"spring:name=jmxBean", description="Managed Bean")
public class JmxBeanImpl implements JmxBean {
    private String name;
    private int rating;

	
    @ManagedAttribute(defaultValue="animal")
	public String getName() {
		return name;
	}
     
    @ManagedAttribute
       (description="Name Attribute",
        defaultValue="animal")
	public void setName(String name) {
		this.name = name;
		System.out.println("Setting name to " + this.name);
	}

	@ManagedAttribute
	    (description="Rating Attribute")
	public int getRating() {
		return rating;
	}

	public void setRating(int rating) {
		this.rating = rating;
	}
}

As I indicated before, Spring allows usage of Java 5 Annotations to specify which classes and methods will be loaded into the MBeanServer, as well as metadata about them. Annotations are straight-forward to use, and provide great visibility to the developer as to which methods are exposed.

Finally, here is an example server, which loads up the Spring application context file.


package com.phurnace;

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.
ClassPathXmlApplicationContext; public class SpringJmxServer { private static Logger logger =
Logger.getLogger(SpringJmxServer.class); /** * @param args */ public static void main(String[] args) { org.apache.log4j.BasicConfigurator.configure(); ApplicationContext ctx = new
ClassPathXmlApplicationContext("/com/phurnace/server-jsr160.xml"); if (ctx != null) { logger.info
("Successfully loaded ApplicationContext"); } JmxBean jmxBean = (JmxBean) ctx.getBean("jmxBean"); String name = jmxBean.getName(); logger.info("Name is " + name); while ( !name.toUpperCase().equals("EXIT") ) { try { Thread.sleep(5000); name = jmxBean.getName(); } catch (Exception e) { logger.error("Trapped error " +
e.getMessage()); System.exit(1); } } System.exit(0); } }

Now, on to the client-side of things. First, I will show how to access the Spring Bean as a standard JMX client:


package com.phurnace;

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import org.apache.log4j.Logger;

public class TestJmxClient {
	private static Logger logger = Logger.getLogger(
TestJmxClient.class); private final String objectNameStr = "spring:name=jmxBean"; private final String jmxRmiStr = "service:jmx:rmi://localhost/jndi/rmi://localhost:1090/
myconnector"; private ObjectName objectName; private JMXServiceURL jmxUrl; private JMXConnector jmxConnector; private MBeanServerConnection mbsc; /** * @param args */ public static void main(String[] args) { org.apache.log4j.BasicConfigurator.configure(); if (args.length == 0) { logger.info("Usage: java com.phurnace.
TestJmxClient "); System.exit(0); } TestJmxClient jmxClient = new TestJmxClient(); jmxClient.init(); jmxClient.accessBean(args[0]); System.exit(0); } public void init() { try { objectName = new ObjectName(objectNameStr); jmxUrl = new JMXServiceURL(jmxRmiStr); jmxConnector = JMXConnectorFactory.connect
(jmxUrl); mbsc = jmxConnector.getMBeanServerConnection(); } catch (Exception e) { logger.error("Error initializing
connection"); } } public void accessBean(String newName) { String name = getName(); if (name == null) { return; } logger.info("Original name is " + name); logger.info("Setting new name to " + newName); setName(newName); // // Access the name again to check it's value // name = getName(); if (name == null) { return; } logger.info("New name is " + name); } private void setName(final String name) { final String operationName = "setName"; try { Object[] params = new Object[1]; params[0] = name; String[] signature = new String[1]; signature[0] = new String("java.lang.String"); mbsc.invoke(objectName, operationName, params, // no parameter signature ); } catch (Exception e) { logger.info( "Error setting name value in bean "
+ e.getMessage()); } } private String getName() { final String operationName = "getName"; try { final String status = (String) mbsc.invoke(objectName, operationName, null, // no parameter null ); return status; } catch (Exception e) { logger.info("Error getting name value from
bean " + e.getMessage()); } return null; } }

This example does not need any Spring classes to access the MBean, even though it is created on the server as a Spring Bean. The test client accesses the MBeanServer via the RMI protocol.

You may notice that in order to make a connection to the MBeanServer, several intermediate objects must be created, such as a JMXServiceURL, a JMXConnector, and a MBeanServerConnection. In the process of creating these objects, checked exceptions must be handled.

This leads me to my final piece of code, which illustrates the same functionality, but is implemented using Spring.

First, here is a client-side Spring configuration file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
 "http://www.springframework.org/dtd/spring-beans.dtd">
 
<beans>
 
<bean id="clientConnector" class=
"org.springframework.jmx.support.MBeanServerConnectionFactoryBean">
  <property name="serviceUrl" value=
"service:jmx:rmi://localhost/jndi/rmi://localhost:1090/myconnector"/>
</bean>
 
<bean id="proxy" class=  
"org.springframework.jmx.access.MBeanProxyFactoryBean">
  <property name="objectName" value="spring:name=jmxBean"/>
  <property name="proxyInterface" value="com.phurnace.JmxBean"/>
  <property name="server" ref="clientConnector"/>
</bean>
 
</beans>
This configuration file configures an MBeanServerConnectionFactoryBean to provide the client with a connection to the server, via the RMI protocol. Then, an MBeanProxyFactoryBean is configured to create a proxy for the MBean registered under the specified ObjectName. Finally, the client connection bean is referenced, to allow remote access. Finally, here is the the Spring client:

package com.phurnace;

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.
ClassPathXmlApplicationContext; public class TestSpringJmxClient { private static Logger logger = Logger.getLogger
(TestSpringJmxClient.class); private ApplicationContext ctx; private JmxBean jmxBean = null; /** * @param args */ public static void main(String[] args) { org.apache.log4j.BasicConfigurator.configure(); if (args.length == 0) { logger.info("Usage: java com.phurnace.
TestSpringJmxClient "); System.exit(0); } TestSpringJmxClient jmxClient = new TestSpringJmxClient(); jmxClient.init(); jmxClient.accessBean(args[0]); System.exit(0); } public void init() { ctx = new ClassPathXmlApplicationContext
("/com/phurnace/client-jsr160.xml"); if (ctx != null) { logger.info("Successfully loaded
ApplicationContext"); } jmxBean = (JmxBean)ctx.getBean("proxy"); } public void accessBean(String newName) { String name = getName(); if (name == null) { return; } logger.info("Original name is " + name); setName(newName); name = getName(); if (name == null) { return; } logger.info("New name is " + name); logger.info("Rating is " + jmxBean.getRating()); try { jmxBean.setRating(10); } catch (Exception e) { logger.warn("Unable to set rating -
attribute is read-only"); } logger.info("Rating is still " +
jmxBean.getRating()); } private String getName() { return jmxBean.getName(); } private void setName(String name) { jmxBean.setName(name); } }

You might notice that the code is much more concise and clean. Except for the loading of the application context file, and the Bean access, there are no references to Spring code needed.

A try-catch block wraps the call JmxBean.setRating(10), as this method was specifically not exported by the server-side. This essentially makes this property read-only.

Hopefully, this code might encourage you to investigate Spring JMX as a technology worth incorporating in your next application. Providing external access to applications can pay off in valuable, unforseen ways after the it has been deployed.

In Untagged 
Comment (4) Read More...


Posted by: Alexander Bibighaus on

Switching IDE's has always been something I feel is important to keep an open mind about. I learned this early on when I was an emacs fanatic. I started software development in a Unix/C environment where emacs and vi were the two editors of choice (or debate). Despite all of the vi/emacs wars , my experience was that both came in handy, but at different times.

I recently feel this way about Netbeans vs Eclipse in the Java IDE world. Both IDE's contribute different tools to a Java developer that are extremely useful.

Let's take Eclipse for example. I like Eclipse's efficiency. Everything takes less clicks! In addition, the SWT toolkit still feels and performs better than any Java application out there. Netbeans continues to have small quirks about it that cause discomfort for the user because the application does not behave as a normal native application. Something as simple as managing the cursor in the code does not feel natural to me. So, the “Everyday IDE” still goes to Eclipse.

On the flip side, Netbeans has far more integrated tools and wizards than Eclipse. Netbeans has a rich set of wizards and tools for mobility, J2EE, Web development etc. Moreover, the Java Profiler is excellent! The best part about Netbeans is that it is one coherent tool from a single vendor. The “Most Complete IDE” goes to NetBeans.

Netbeans Visual Development tools are the first visual tools for Java I can say I enjoyed. The best part is the ability to integrate manually written code with the visual designer and vice-versa. In addition, the visual designer generates simple code. The generated code is straightforward Java that anyone unfamiliar with the visual tools would understand. The “Most Innovative IDE” goes to NetBeans for finally giving Java a set of useful visual tools.

Eclipse has a one big leg up on Netbeans. Eclipse RCP is a fantastic development framework. It is rich in features and has a unifying effect on product development. Anyone thinking about developing a desktop application should seriously consider Eclipse RCP. The “Best Application Development IDE” goes to Eclipse because you should be developing RCP applications in that case.

In conclusion, just as vi and emacs both brought different ideas as an editor, it is worth the effort to learn both. You will find that rather wasting your time arguing for one or the other, you just have more tools in you tool chest since you tried them both!

In NetbeansIDEEclipse
Comment (0) Read More...


Posted by: Robert Reeves on

In the first part of this two part post, I discussed how scripts are terrible at eliminating errors. In fact, scripts simply replace typos with system errors. A rather poor trade-off, I think.

The second problem with scripts is the burden they place on employees to maintain them and the decrease in productivity they can cause. This maintenance burden and productivity sinkhole are the two areas scripts were supposed to fix!

Frankly, I hold the tools architecture responsible. Scripts conflate the Data with the Mechanism because of the enforced procedural nature of the tools (think wsadmin). Please note that I don't mean to pick on WebSphere, but I just have a *ton* of experience with that application server. I could have just easily singled out WebLogic, OAS, JBoss or Glassfish. The architecture problem is common to them all.

To see an example of conflation, navigate to your WAS 6.1 directory and look at samples\bin\PlantsByWebSphere\install.jacl. You will see the following:

  createJ2CResourceAdapter $nodeName $serverName

That's a good start as both resources are provided at the command line when executing the script. However, the script immediately falls apart on the next directive:

  #--------------------------------------------------------------------

  # Setup security cell

  #--------------------------------------------------------------------

  set secAuthAlias "$cellName/samples"

  set secDescript  "JAAS Alias for WebSphere Samples"

  set secUserID    "samples"

  set secPassword  "$samplepwName"

  createJAASAuthenticationAlias $cellName $secAuthAlias $secDescript $secUserID $secPassword

Don't see it the problem? I don't blame you. The problem is a hardcoded secUserId. This will fail if there is another JAASAuthData that uses the same secUserId as "samples". Now, that's a simple mistake; but it's one that will require a very specific use case to find it. So, we have actually created a maintenance headache for ourselves. This script may save me time in my Dev or QA environments. But, once it gets to Production where they use entirely different usernames for the database, I will have an error I simply cannot afford to have.

But, finding the specific JAASAuthData configuration problem is just the first headache. In my Production environment, imagine that this script fails on the duplicate secUserId value. Well, that's easy to fix, right. Let's just add another argument to pass in when the script is run.

So, I'm only into the second call of my script, and already I'm required to make the script more complicated. Furthermore, since my script is not wrapped in a transaction, I'll have to manually delete the J2CResourceAdapter to completely roll back. Or, at least, I *think* that's all I need to roll back my script's changes. After all, the best thing that can happen when I run a wsadmin script is nothing. Because if I see anything on STDOUT, that's normally a bad thing.

Ideally, I would have my Data described in a simple format that defines the System Resource (or MBean) I am trying to create and its associated attributes. Then, my script would read that data structure and create the MBeans necessary. Finally, at the end, it would generate a report that details what was changed in my environment. And, of course, if any failure's occur, all changes up to the failure are automatically rolled back.

Of course, I would love to see you purchase Phurnace Deliver which can do all of that and then some. However, you can create this yourself. The tools to do so are readily available and most Application Servers provide some sort of API to manage those configuration changes. Just remember to separate the Data from the Mechanism, and you should be much better off.

In Scriptsjava
Comment (0) Read More...


Posted by: Alexander Bibighaus on

 Apple's iPhone represents a revolutionary mobile platform that has attracted people of all sorts to download the SDK and take a look.  Today, it seems I search the internet for "iPhone" related information only to find hundreds of rants.  Most rants are either about the lack of Flash and/or Java support for the iPhone. Perhaps this is because the world is full of developers who know Java or Flash, but not Objective C?

After I perused the SDK, frankly, I was impressed.  I believe the iPhone combined with the SDK is a highly versatile  device with a level of programmability that makes you wonder about the limits of what can be achieved.

The multitude of rants did inspire me to ask the question:  "Why does Apple not support Java since most all mobile phones support Java ME?"  Sifting through the diatribes of opinions, I found an interesting older blog that talks about how Apple could, if they wanted, ship a software upgrade to enable Java. Sounds to me that Apple is hedging their bet by choosing a chip processor that supports embedded Java acceleration engine called Jazelle.

Until then, it is an exciting new platform that requires a steep learning curve. Learning is what we developers enjoy doing, right? 

In java
Comment (0) Read More...


Posted by: Robert Reeves on

Up until the release of Phurnace Deliver last year, there were two choices when it came to Java Application Server management: manual data entry or scripts. Typically, a company starts with manually entering configuration data via a web-based admin console. Then, either organically or via a concerted effort, the company will move to using scripts to manage the Application Server configuration and deploying binaries.

Companies begin this migration for two reasons. The first is to automate mistake prone tasks in order to avoid costly errors. Second, the company seeks to boost efficiency and increase employee and system productivity. While both of these motivators are valid, scripts simply fail to deliver on both of these hopes. In this blog entry, I'm going to discuss how scripting fails to deliver on error elimination. In fact, I will contend that scripts will cause the same, if not more, errors than using a manual approach.

When Exceptions Are the Rule...

Imagine that I was tasked with updating the Server heap size on a WebSphere Application Server; specifically, the heap size is currently 512MB and I need to change it to 1024MB. This is a rather simply task using the WAS Admin Console. However, if it turns out that I have 100 Servers to update, the task begins to become a bit more daunting. I'm certain that, around server 60, I'm going to make a mistake and type in "11024" instead of "1024". A Heap Size of 11 GB is not what Server number 60 needs! Thus, a script sounds like a good choice. And, it is.

Unfortunately, you will never run into this specific case. In reality, the Servers' heap size will all be different based on utilization and hardware requirements. In fact, only 78 of the 100 Servers need to be changed. And, of the 78, 42 need to be 1024MB and 24 need to be 768MB, etc. You can see how reality would make this a very complex task, even for scripts.

When exceptions become the rule, you better have good exception handling. Simply put, error handling in the scripting environments provided by AS vendors are terrible. Error handling is almost non-existent and the execution environments provide sparse responses when an error does occur. In fact, when an error occurs, you cannot be sure it is the script or the environment in which the script is run. Moreover, you are unable to distinguish between a network connectivity error or JNDI name conflict error within your script. Thus, you must rely on the user executing your script to determine the root cause of the error and take corrective action.

If that is the case, then there is really no reason to write a script in the first place. That time would have been better spent on educating the user about the AS change process or (shameless plug) purchased Phurnace Deliver.

"Works on my machine."

I have been working on Java Application Servers since Netscape Application Server 4.0. In all those ensuing years, I have yet to come across a company that had an identical environment for dev, test and production. Each stage differed by topology and naming conventions. For example, I would see 2-way clusters in dev and test and 4-way clusters in production. Moreover, you will find different Cell names, JDBC Urls, Usernames and Passwords in each environment.

And, unless all your environments are managed by a single person with OCD and insomnia, you will encounter Configuration Drift across those environments. These drifts will start in Test or Production. From Test, the drift can be started by a Developer making a change to the Test environment without logging a bug or updating the current script. ("Oh, that error? I forgot to add a new Datasource. Let me add that real quick..."). Thus, when the code moves to Production, you will see the same error caused by a missing Datasource. Drifts can start in Production when IT admins make well intentioned changes to their environments without those changes being pushed down to Test and Dev. Thus, Dev and QA are developing and testing against an invalid environment.

The end result is that you begin to have scripts that only work for specific environments and not a specific release. Thus, the results of your script are little better than a crap shoot when it comes time to update Production. And, since most Application Servers do not keep track of configuration changes internally, determining what is different between two environments is near impossible. If you can't determine the delta, then you can't fix the delta.

Thus, hopes for mistake eliminating and increase productivity become pipe dreams. And, the organization is no better off than with manual deployment than with scripts.

Admittedly, errors are a significant cause of productivity loss; especially errors found in production. However, there are other ways that scripts can cause productivity loss . In my next blog entry, I will discuss how scripts simply move tasks from one area to another in order to give the illusion of productivity enhancements.

In Scriptsjava
Comment (1) Read More...