Who’s On Phirst

Official blog of Phurnace Software.

Category >> Java

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 (0) 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...