Thứ Hai, 25 tháng 2, 2008

Flex 3 Released Today

Adobe announced today the official release of Flex 3. Users of FlexBuilder will probably really like a new version of FlexBuilder, but the now open source nature of Flex is also going to appeal to many. I was a little surprised that as of this writing, the evening of this announcement, there is no press release on this available on the page with press releases. The most recent press release currently listed there for Flex is the 13 December 2007 announcement regarding the release of BlazeDS.

One impact the timing of this release of Flex 3 has on me is that I now need to update my slides for Collaborate08 regarding Flex 2 and Flex 3.

Thứ Bảy, 23 tháng 2, 2008

Windows PowerShell and Java

In my previous blog entry, I briefly wrote about Windows PowerShell. In this blog entry, I intend to cover some uses of Java with Windows PowerShell.

Many Java applications require the environment variable JAVA_HOME to be set appropriately to work correctly. In PowerShell, you can check the setting of a particular environment variable with the command echo $env:JAVA_HOME. An example of this is shown in the next screen snapshot (click on image to see larger version).



Another environment variable that is often useful to note when using Java is any CLASSPATH setting. This can be checked with the echo $env:CLASSPATH command. If the CLASSPATH environment variable is set, it will be displayed. What if you wanted to set your classpath for use in Java applications rather than passing the classpath to the application with the Java launcher? In that case, you could set CLASSPATH with the command $env:CLASSPATH = "<<someClassPath>>".

The quotation marks are significant in setting the classpath because the semicolon (;) is still used to separate class path entries. Because the semicolon also tells PowerShell that a command is being terminated and another started, this must be in quotation marks to avoid the classpath being treated as two separate statements.

The classpath can also be set on the command-line in conjunction with the Java launcher with a command like: java -cp "<<someClassPathEntry>>;<<anotherClassPathEntry>>" <<package>>.<<classToRun>> (again, as with setting the CLASSPATH environment variable, quotations should be used around the entire classpath entry so that the semicolon is not treated as a statement terminator). A concrete example of this is shown next:

java -cp "C:\NetBeansProjects\SpringJmxExample\build\classes;C:\spring-framework-2.5.1\dist\spring.jar;C:\spring-framework-2.5.1\lib\jakarta-commons\commons-logging.jar" marx.SpringJmxMain


The take-aways from all of this include the following:

  • Although many Unix-isms can be used in PowerShell, one should still use the semicolon for classpath separators as described in the Windows Setting the Class Path document rather than with colons for Unix as documented in the Solaris Setting the Class Path document.

  • PowerShell does recognize semicolons as statement terminators for placing multiple statements on the same line. This very Unix-like feature means that class path values must be surrounded in quotes so that multiple entries can be separated with semicolons without making PowerShell think there are multiple statements on the line.

  • Although PowerShell "feels" much more like Unix than DOS, it still supports DOS operations and the semicolon and backwards slashes in the examples above shown that this is the same as in DOS as well. That being said, I can also use more Unix-like syntax and have it work as well. The command shown above could also be run as follows:

    java -cp "/NetBeansProjects/SpringJmxExample/build/classes;/spring-framework-2.5.1/dist/spring.jar;/spring-framework-2.5.1/lib/jakarta-commons/commons-logging.jar"
    marx.SpringJmxMain

    The above command will behave exactly as the one shown above, but without the DOS-obvious C:\ drive syntax and the backwards slashes.

  • It is not shown above, but you can find out more about using PowerShell environment variables by running the command man env (or help env) in the PowerShell terminal window.



When specifying Java system properties on the command line in PowerShell, you need to put quotation marks around the these specifications so that the -D is not interpreted prematurely. The next screen snapshot shows running Java with the -D system properties options without quotes and the error that follows. The same screen snapshot then shows how it runs successfully if double quotes are used around the -D system properties.



You can run the java -version command in PowerShell just as you would in DOS or Unix/Linux. The next screen snapshot demonstrates this.



Similarly, you can run other Java executable tools in the same way you'd run them in DOS or in Unix/Linux. The next screen snapshot shows the command-line view of running these in PowerShell.



PowerShell brings each of us a more "natural" Java development command-line experience if we've developed Java primarily in a Unix/Linux environment in the past.

It is not as easy as I would have expected to find good blogs and articles on using Java with PowerShell. This may be due somewhat to the chasm that often seems to exist between the Windows community and Java or other non-.NET communities. Here are some interesting links related to using Java with PowerShell:

Hello Windows PowerShell

I have been frustrated for some time with DOS scripting. Fortunately, a colleague pointed me to Microsoft PowerShell (formerly known as Project Monad) for Windows XP and Windows Vista. PowerShell can be downloaded here and there are several scripts for use with PowerShell provided here. You can also download the Windows PowerShell Owner's Manual.

One of the things that is nice about PowerShell is that is supports many of the commands that we like to use in Unix/Linux. There are far too many useful things to demonstrate about PowerShell in one place, but the next two screenshots (click on them to see larger versions) demonstrate some Unix-like commands supported in Windows PowerShell.

The first screen snapshot demonstrates the very handy history command along with the ability to run a man (equivalent to help) command for a particular command.



The next screen snapshot shows the ls command along with the mv command. Having Unix equivalents makes it less frustrating to switch between Unix/Linux and Windows. Also, the ls and mkdir commands demonstrate the displaying of file modes.



Besides the Unix/Linux commands shown in the screen snapshots above, other goodies that are now available in PowerShell include pwd, ps, and cat. It is amazing how nice it is to have these little "extras" in the DOS scripting world.

Windows PowerShell requires .NET framework 2.0, so you'll need to get this if you don't already have it. There is much, much more to Windows PowerShell than what I've shown here so far. I think it is likely that I'll post future blog entries on other great features of PowerShell. It is even more likely that I'll start using PowerShell more frequently in my blog entries that show me running scripts, Java commands, the Flex compiler, etc. from the command line rather than using the old-style DOS terminal.

In related resources, Vaibhav discusses running PowerShell from Java. An interesting related article is A Return to Command-Line Control with Windows PowerShell. A free Windows PowerShell eBook is available as well. Finally, two other introductory references for using PowerShell are What is Windows PowerShell? and Top Ten Tips for Using Windows PowerShell Finally, a gentle introduction to Windows PowerShell is available in Discover PowerShell.

Thứ Hai, 18 tháng 2, 2008

Use Trang to Generate XML Schema

Trang has been around for a while and is a useful utility for converting between types of XML Schema. In fact, the most recent version for download at the Trang site is version 20030619 (note the date embedded in the version name).

Besides being useful for converting between XML schema definitions, Trang is also useful for generating a new XML schema definition from one or more source XML files. In fact, this use of Trang is the focus of this blog entry. In this blog entry, I will demonstrate how simple it is to apply Trang to generation of W3C XML Schema and DTD definitions from a source XML file.

Oracle provides the highly useful Java OracleXMLQuery class for querying the relational database and provide the query results in XML format. The OracleXMLQuery class provides the setRowsetTag(String) method to specify the Java String to be used as the root tag of the generated XML file containing the query results. Likewise, the OracleXMLQuery.setRowTag(String) method allows one to specify the String label provided for each row element tag in the generated XML file.

The XML below was generated using OracleXMLQuery with the rowset tag specified as "Employees" and the row tag specified as "Employee." The query used to generate this XML was run against the HR schema and is shown next.
SELECT employee_id, first_name, last_name, department_name
FROM employees, departments
WHERE employees.department_id = departments.department_id


The XML generated by OracleXMLQuery is shown next.

employees.xml - XML Generated with OracleXMLQuery
<?xml version = '1.0'?>
<Employees>
<Employee num="1">
<EMPLOYEE_ID>200</EMPLOYEE_ID>
<FIRST_NAME>Jennifer</FIRST_NAME>
<LAST_NAME>Whalen</LAST_NAME>
<DEPARTMENT_NAME>Administration</DEPARTMENT_NAME>
</Employee>
<Employee num="2">
<EMPLOYEE_ID>201</EMPLOYEE_ID>
<FIRST_NAME>Michael</FIRST_NAME>
<LAST_NAME>Hartstein</LAST_NAME>
<DEPARTMENT_NAME>Marketing</DEPARTMENT_NAME>
</Employee>
<Employee num="3">
<EMPLOYEE_ID>202</EMPLOYEE_ID>
<FIRST_NAME>Pat</FIRST_NAME>
<LAST_NAME>Fay</LAST_NAME>
<DEPARTMENT_NAME>Marketing</DEPARTMENT_NAME>
</Employee>
<Employee num="4">
<EMPLOYEE_ID>114</EMPLOYEE_ID>
<FIRST_NAME>Den</FIRST_NAME>
<LAST_NAME>Raphaely</LAST_NAME>
<DEPARTMENT_NAME>Purchasing</DEPARTMENT_NAME>
</Employee>
<Employee num="5">
<EMPLOYEE_ID>119</EMPLOYEE_ID>
<FIRST_NAME>Karen</FIRST_NAME>
<LAST_NAME>Colmenares</LAST_NAME>
<DEPARTMENT_NAME>Purchasing</DEPARTMENT_NAME>
</Employee>
<Employee num="6">
<EMPLOYEE_ID>115</EMPLOYEE_ID>
<FIRST_NAME>Alexander</FIRST_NAME>
<LAST_NAME>Khoo</LAST_NAME>
<DEPARTMENT_NAME>Purchasing</DEPARTMENT_NAME>
</Employee>
<Employee num="7">
<EMPLOYEE_ID>116</EMPLOYEE_ID>
<FIRST_NAME>Shelli</FIRST_NAME>
<LAST_NAME>Baida</LAST_NAME>
<DEPARTMENT_NAME>Purchasing</DEPARTMENT_NAME>
</Employee>
<Employee num="8">
<EMPLOYEE_ID>117</EMPLOYEE_ID>
<FIRST_NAME>Sigal</FIRST_NAME>
<LAST_NAME>Tobias</LAST_NAME>
<DEPARTMENT_NAME>Purchasing</DEPARTMENT_NAME>
</Employee>
<Employee num="9">
<EMPLOYEE_ID>118</EMPLOYEE_ID>
<FIRST_NAME>Guy</FIRST_NAME>
<LAST_NAME>Himuro</LAST_NAME>
<DEPARTMENT_NAME>Purchasing</DEPARTMENT_NAME>
</Employee>
<Employee num="10">
<EMPLOYEE_ID>203</EMPLOYEE_ID>
<FIRST_NAME>Susan</FIRST_NAME>
<LAST_NAME>Mavris</LAST_NAME>
<DEPARTMENT_NAME>Human Resources</DEPARTMENT_NAME>
</Employee>
<Employee num="11">
<EMPLOYEE_ID>198</EMPLOYEE_ID>
<FIRST_NAME>Donald</FIRST_NAME>
<LAST_NAME>OConnell</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="12">
<EMPLOYEE_ID>199</EMPLOYEE_ID>
<FIRST_NAME>Douglas</FIRST_NAME>
<LAST_NAME>Grant</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="13">
<EMPLOYEE_ID>120</EMPLOYEE_ID>
<FIRST_NAME>Matthew</FIRST_NAME>
<LAST_NAME>Weiss</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="14">
<EMPLOYEE_ID>121</EMPLOYEE_ID>
<FIRST_NAME>Adam</FIRST_NAME>
<LAST_NAME>Fripp</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="15">
<EMPLOYEE_ID>122</EMPLOYEE_ID>
<FIRST_NAME>Payam</FIRST_NAME>
<LAST_NAME>Kaufling</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="16">
<EMPLOYEE_ID>123</EMPLOYEE_ID>
<FIRST_NAME>Shanta</FIRST_NAME>
<LAST_NAME>Vollman</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="17">
<EMPLOYEE_ID>124</EMPLOYEE_ID>
<FIRST_NAME>Kevin</FIRST_NAME>
<LAST_NAME>Mourgos</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="18">
<EMPLOYEE_ID>125</EMPLOYEE_ID>
<FIRST_NAME>Julia</FIRST_NAME>
<LAST_NAME>Nayer</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="19">
<EMPLOYEE_ID>126</EMPLOYEE_ID>
<FIRST_NAME>Irene</FIRST_NAME>
<LAST_NAME>Mikkilineni</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="20">
<EMPLOYEE_ID>127</EMPLOYEE_ID>
<FIRST_NAME>James</FIRST_NAME>
<LAST_NAME>Landry</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="21">
<EMPLOYEE_ID>128</EMPLOYEE_ID>
<FIRST_NAME>Steven</FIRST_NAME>
<LAST_NAME>Markle</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="22">
<EMPLOYEE_ID>129</EMPLOYEE_ID>
<FIRST_NAME>Laura</FIRST_NAME>
<LAST_NAME>Bissot</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="23">
<EMPLOYEE_ID>130</EMPLOYEE_ID>
<FIRST_NAME>Mozhe</FIRST_NAME>
<LAST_NAME>Atkinson</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="24">
<EMPLOYEE_ID>131</EMPLOYEE_ID>
<FIRST_NAME>James</FIRST_NAME>
<LAST_NAME>Marlow</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="25">
<EMPLOYEE_ID>132</EMPLOYEE_ID>
<FIRST_NAME>TJ</FIRST_NAME>
<LAST_NAME>Olson</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="26">
<EMPLOYEE_ID>133</EMPLOYEE_ID>
<FIRST_NAME>Jason</FIRST_NAME>
<LAST_NAME>Mallin</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="27">
<EMPLOYEE_ID>134</EMPLOYEE_ID>
<FIRST_NAME>Michael</FIRST_NAME>
<LAST_NAME>Rogers</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="28">
<EMPLOYEE_ID>135</EMPLOYEE_ID>
<FIRST_NAME>Ki</FIRST_NAME>
<LAST_NAME>Gee</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="29">
<EMPLOYEE_ID>136</EMPLOYEE_ID>
<FIRST_NAME>Hazel</FIRST_NAME>
<LAST_NAME>Philtanker</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="30">
<EMPLOYEE_ID>137</EMPLOYEE_ID>
<FIRST_NAME>Renske</FIRST_NAME>
<LAST_NAME>Ladwig</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="31">
<EMPLOYEE_ID>138</EMPLOYEE_ID>
<FIRST_NAME>Stephen</FIRST_NAME>
<LAST_NAME>Stiles</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="32">
<EMPLOYEE_ID>139</EMPLOYEE_ID>
<FIRST_NAME>John</FIRST_NAME>
<LAST_NAME>Seo</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="33">
<EMPLOYEE_ID>140</EMPLOYEE_ID>
<FIRST_NAME>Joshua</FIRST_NAME>
<LAST_NAME>Patel</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="34">
<EMPLOYEE_ID>141</EMPLOYEE_ID>
<FIRST_NAME>Trenna</FIRST_NAME>
<LAST_NAME>Rajs</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="35">
<EMPLOYEE_ID>142</EMPLOYEE_ID>
<FIRST_NAME>Curtis</FIRST_NAME>
<LAST_NAME>Davies</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="36">
<EMPLOYEE_ID>143</EMPLOYEE_ID>
<FIRST_NAME>Randall</FIRST_NAME>
<LAST_NAME>Matos</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="37">
<EMPLOYEE_ID>144</EMPLOYEE_ID>
<FIRST_NAME>Peter</FIRST_NAME>
<LAST_NAME>Vargas</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="38">
<EMPLOYEE_ID>180</EMPLOYEE_ID>
<FIRST_NAME>Winston</FIRST_NAME>
<LAST_NAME>Taylor</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="39">
<EMPLOYEE_ID>181</EMPLOYEE_ID>
<FIRST_NAME>Jean</FIRST_NAME>
<LAST_NAME>Fleaur</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="40">
<EMPLOYEE_ID>182</EMPLOYEE_ID>
<FIRST_NAME>Martha</FIRST_NAME>
<LAST_NAME>Sullivan</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="41">
<EMPLOYEE_ID>183</EMPLOYEE_ID>
<FIRST_NAME>Girard</FIRST_NAME>
<LAST_NAME>Geoni</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="42">
<EMPLOYEE_ID>184</EMPLOYEE_ID>
<FIRST_NAME>Nandita</FIRST_NAME>
<LAST_NAME>Sarchand</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="43">
<EMPLOYEE_ID>185</EMPLOYEE_ID>
<FIRST_NAME>Alexis</FIRST_NAME>
<LAST_NAME>Bull</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="44">
<EMPLOYEE_ID>186</EMPLOYEE_ID>
<FIRST_NAME>Julia</FIRST_NAME>
<LAST_NAME>Dellinger</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="45">
<EMPLOYEE_ID>187</EMPLOYEE_ID>
<FIRST_NAME>Anthony</FIRST_NAME>
<LAST_NAME>Cabrio</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="46">
<EMPLOYEE_ID>188</EMPLOYEE_ID>
<FIRST_NAME>Kelly</FIRST_NAME>
<LAST_NAME>Chung</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="47">
<EMPLOYEE_ID>189</EMPLOYEE_ID>
<FIRST_NAME>Jennifer</FIRST_NAME>
<LAST_NAME>Dilly</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="48">
<EMPLOYEE_ID>190</EMPLOYEE_ID>
<FIRST_NAME>Timothy</FIRST_NAME>
<LAST_NAME>Gates</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="49">
<EMPLOYEE_ID>191</EMPLOYEE_ID>
<FIRST_NAME>Randall</FIRST_NAME>
<LAST_NAME>Perkins</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="50">
<EMPLOYEE_ID>192</EMPLOYEE_ID>
<FIRST_NAME>Sarah</FIRST_NAME>
<LAST_NAME>Bell</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="51">
<EMPLOYEE_ID>193</EMPLOYEE_ID>
<FIRST_NAME>Britney</FIRST_NAME>
<LAST_NAME>Everett</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="52">
<EMPLOYEE_ID>194</EMPLOYEE_ID>
<FIRST_NAME>Samuel</FIRST_NAME>
<LAST_NAME>McCain</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="53">
<EMPLOYEE_ID>195</EMPLOYEE_ID>
<FIRST_NAME>Vance</FIRST_NAME>
<LAST_NAME>Jones</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="54">
<EMPLOYEE_ID>196</EMPLOYEE_ID>
<FIRST_NAME>Alana</FIRST_NAME>
<LAST_NAME>Walsh</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="55">
<EMPLOYEE_ID>197</EMPLOYEE_ID>
<FIRST_NAME>Kevin</FIRST_NAME>
<LAST_NAME>Feeney</LAST_NAME>
<DEPARTMENT_NAME>Shipping</DEPARTMENT_NAME>
</Employee>
<Employee num="56">
<EMPLOYEE_ID>104</EMPLOYEE_ID>
<FIRST_NAME>Bruce</FIRST_NAME>
<LAST_NAME>Ernst</LAST_NAME>
<DEPARTMENT_NAME>IT</DEPARTMENT_NAME>
</Employee>
<Employee num="57">
<EMPLOYEE_ID>103</EMPLOYEE_ID>
<FIRST_NAME>Alexander</FIRST_NAME>
<LAST_NAME>Hunold</LAST_NAME>
<DEPARTMENT_NAME>IT</DEPARTMENT_NAME>
</Employee>
<Employee num="58">
<EMPLOYEE_ID>107</EMPLOYEE_ID>
<FIRST_NAME>Diana</FIRST_NAME>
<LAST_NAME>Lorentz</LAST_NAME>
<DEPARTMENT_NAME>IT</DEPARTMENT_NAME>
</Employee>
<Employee num="59">
<EMPLOYEE_ID>106</EMPLOYEE_ID>
<FIRST_NAME>Valli</FIRST_NAME>
<LAST_NAME>Pataballa</LAST_NAME>
<DEPARTMENT_NAME>IT</DEPARTMENT_NAME>
</Employee>
<Employee num="60">
<EMPLOYEE_ID>105</EMPLOYEE_ID>
<FIRST_NAME>David</FIRST_NAME>
<LAST_NAME>Austin</LAST_NAME>
<DEPARTMENT_NAME>IT</DEPARTMENT_NAME>
</Employee>
<Employee num="61">
<EMPLOYEE_ID>204</EMPLOYEE_ID>
<FIRST_NAME>Hermann</FIRST_NAME>
<LAST_NAME>Baer</LAST_NAME>
<DEPARTMENT_NAME>Public Relations</DEPARTMENT_NAME>
</Employee>
<Employee num="62">
<EMPLOYEE_ID>176</EMPLOYEE_ID>
<FIRST_NAME>Jonathon</FIRST_NAME>
<LAST_NAME>Taylor</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="63">
<EMPLOYEE_ID>177</EMPLOYEE_ID>
<FIRST_NAME>Jack</FIRST_NAME>
<LAST_NAME>Livingston</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="64">
<EMPLOYEE_ID>179</EMPLOYEE_ID>
<FIRST_NAME>Charles</FIRST_NAME>
<LAST_NAME>Johnson</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="65">
<EMPLOYEE_ID>175</EMPLOYEE_ID>
<FIRST_NAME>Alyssa</FIRST_NAME>
<LAST_NAME>Hutton</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="66">
<EMPLOYEE_ID>174</EMPLOYEE_ID>
<FIRST_NAME>Ellen</FIRST_NAME>
<LAST_NAME>Abel</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="67">
<EMPLOYEE_ID>173</EMPLOYEE_ID>
<FIRST_NAME>Sundita</FIRST_NAME>
<LAST_NAME>Kumar</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="68">
<EMPLOYEE_ID>172</EMPLOYEE_ID>
<FIRST_NAME>Elizabeth</FIRST_NAME>
<LAST_NAME>Bates</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="69">
<EMPLOYEE_ID>171</EMPLOYEE_ID>
<FIRST_NAME>William</FIRST_NAME>
<LAST_NAME>Smith</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="70">
<EMPLOYEE_ID>170</EMPLOYEE_ID>
<FIRST_NAME>Tayler</FIRST_NAME>
<LAST_NAME>Fox</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="71">
<EMPLOYEE_ID>169</EMPLOYEE_ID>
<FIRST_NAME>Harrison</FIRST_NAME>
<LAST_NAME>Bloom</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="72">
<EMPLOYEE_ID>168</EMPLOYEE_ID>
<FIRST_NAME>Lisa</FIRST_NAME>
<LAST_NAME>Ozer</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="73">
<EMPLOYEE_ID>145</EMPLOYEE_ID>
<FIRST_NAME>John</FIRST_NAME>
<LAST_NAME>Russell</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="74">
<EMPLOYEE_ID>146</EMPLOYEE_ID>
<FIRST_NAME>Karen</FIRST_NAME>
<LAST_NAME>Partners</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="75">
<EMPLOYEE_ID>147</EMPLOYEE_ID>
<FIRST_NAME>Alberto</FIRST_NAME>
<LAST_NAME>Errazuriz</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="76">
<EMPLOYEE_ID>148</EMPLOYEE_ID>
<FIRST_NAME>Gerald</FIRST_NAME>
<LAST_NAME>Cambrault</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="77">
<EMPLOYEE_ID>149</EMPLOYEE_ID>
<FIRST_NAME>Eleni</FIRST_NAME>
<LAST_NAME>Zlotkey</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="78">
<EMPLOYEE_ID>150</EMPLOYEE_ID>
<FIRST_NAME>Peter</FIRST_NAME>
<LAST_NAME>Tucker</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="79">
<EMPLOYEE_ID>151</EMPLOYEE_ID>
<FIRST_NAME>David</FIRST_NAME>
<LAST_NAME>Bernstein</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="80">
<EMPLOYEE_ID>152</EMPLOYEE_ID>
<FIRST_NAME>Peter</FIRST_NAME>
<LAST_NAME>Hall</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="81">
<EMPLOYEE_ID>153</EMPLOYEE_ID>
<FIRST_NAME>Christopher</FIRST_NAME>
<LAST_NAME>Olsen</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="82">
<EMPLOYEE_ID>154</EMPLOYEE_ID>
<FIRST_NAME>Nanette</FIRST_NAME>
<LAST_NAME>Cambrault</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="83">
<EMPLOYEE_ID>155</EMPLOYEE_ID>
<FIRST_NAME>Oliver</FIRST_NAME>
<LAST_NAME>Tuvault</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="84">
<EMPLOYEE_ID>156</EMPLOYEE_ID>
<FIRST_NAME>Janette</FIRST_NAME>
<LAST_NAME>King</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="85">
<EMPLOYEE_ID>157</EMPLOYEE_ID>
<FIRST_NAME>Patrick</FIRST_NAME>
<LAST_NAME>Sully</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="86">
<EMPLOYEE_ID>158</EMPLOYEE_ID>
<FIRST_NAME>Allan</FIRST_NAME>
<LAST_NAME>McEwen</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="87">
<EMPLOYEE_ID>159</EMPLOYEE_ID>
<FIRST_NAME>Lindsey</FIRST_NAME>
<LAST_NAME>Smith</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="88">
<EMPLOYEE_ID>160</EMPLOYEE_ID>
<FIRST_NAME>Louise</FIRST_NAME>
<LAST_NAME>Doran</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="89">
<EMPLOYEE_ID>161</EMPLOYEE_ID>
<FIRST_NAME>Sarath</FIRST_NAME>
<LAST_NAME>Sewall</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="90">
<EMPLOYEE_ID>162</EMPLOYEE_ID>
<FIRST_NAME>Clara</FIRST_NAME>
<LAST_NAME>Vishney</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="91">
<EMPLOYEE_ID>163</EMPLOYEE_ID>
<FIRST_NAME>Danielle</FIRST_NAME>
<LAST_NAME>Greene</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="92">
<EMPLOYEE_ID>164</EMPLOYEE_ID>
<FIRST_NAME>Mattea</FIRST_NAME>
<LAST_NAME>Marvins</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="93">
<EMPLOYEE_ID>165</EMPLOYEE_ID>
<FIRST_NAME>David</FIRST_NAME>
<LAST_NAME>Lee</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="94">
<EMPLOYEE_ID>166</EMPLOYEE_ID>
<FIRST_NAME>Sundar</FIRST_NAME>
<LAST_NAME>Ande</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="95">
<EMPLOYEE_ID>167</EMPLOYEE_ID>
<FIRST_NAME>Amit</FIRST_NAME>
<LAST_NAME>Banda</LAST_NAME>
<DEPARTMENT_NAME>Sales</DEPARTMENT_NAME>
</Employee>
<Employee num="96">
<EMPLOYEE_ID>101</EMPLOYEE_ID>
<FIRST_NAME>Neena</FIRST_NAME>
<LAST_NAME>Kochhar</LAST_NAME>
<DEPARTMENT_NAME>Executive</DEPARTMENT_NAME>
</Employee>
<Employee num="97">
<EMPLOYEE_ID>100</EMPLOYEE_ID>
<FIRST_NAME>Steven</FIRST_NAME>
<LAST_NAME>King</LAST_NAME>
<DEPARTMENT_NAME>Executive</DEPARTMENT_NAME>
</Employee>
<Employee num="98">
<EMPLOYEE_ID>102</EMPLOYEE_ID>
<FIRST_NAME>Lex</FIRST_NAME>
<LAST_NAME>De Haan</LAST_NAME>
<DEPARTMENT_NAME>Executive</DEPARTMENT_NAME>
</Employee>
<Employee num="99">
<EMPLOYEE_ID>110</EMPLOYEE_ID>
<FIRST_NAME>John</FIRST_NAME>
<LAST_NAME>Chen</LAST_NAME>
<DEPARTMENT_NAME>Finance</DEPARTMENT_NAME>
</Employee>
<Employee num="100">
<EMPLOYEE_ID>108</EMPLOYEE_ID>
<FIRST_NAME>Nancy</FIRST_NAME>
<LAST_NAME>Greenberg</LAST_NAME>
<DEPARTMENT_NAME>Finance</DEPARTMENT_NAME>
</Employee>
<Employee num="101">
<EMPLOYEE_ID>111</EMPLOYEE_ID>
<FIRST_NAME>Ismael</FIRST_NAME>
<LAST_NAME>Sciarra</LAST_NAME>
<DEPARTMENT_NAME>Finance</DEPARTMENT_NAME>
</Employee>
<Employee num="102">
<EMPLOYEE_ID>112</EMPLOYEE_ID>
<FIRST_NAME>Jose Manuel</FIRST_NAME>
<LAST_NAME>Urman</LAST_NAME>
<DEPARTMENT_NAME>Finance</DEPARTMENT_NAME>
</Employee>
<Employee num="103">
<EMPLOYEE_ID>113</EMPLOYEE_ID>
<FIRST_NAME>Luis</FIRST_NAME>
<LAST_NAME>Popp</LAST_NAME>
<DEPARTMENT_NAME>Finance</DEPARTMENT_NAME>
</Employee>
<Employee num="104">
<EMPLOYEE_ID>109</EMPLOYEE_ID>
<FIRST_NAME>Daniel</FIRST_NAME>
<LAST_NAME>Faviet</LAST_NAME>
<DEPARTMENT_NAME>Finance</DEPARTMENT_NAME>
</Employee>
<Employee num="105">
<EMPLOYEE_ID>206</EMPLOYEE_ID>
<FIRST_NAME>William</FIRST_NAME>
<LAST_NAME>Gietz</LAST_NAME>
<DEPARTMENT_NAME>Accounting</DEPARTMENT_NAME>
</Employee>
<Employee num="106">
<EMPLOYEE_ID>205</EMPLOYEE_ID>
<FIRST_NAME>Shelley</FIRST_NAME>
<LAST_NAME>Higgins</LAST_NAME>
<DEPARTMENT_NAME>Accounting</DEPARTMENT_NAME>
</Employee>
</Employees>


Note that this generated XML has the "Employees" root tag and "Employee" row tags just as we specified with OracleXMLQuery. The rest of the XML elements are named based on the names of the columns in the SELECT statement and are all in uppercase. These individual element names correspond with the four columns in the SELECT clause.

It is useful to have the XML shown above generated by OracleXMLQuery, but XML is often much more useful if we have a schema defining it. This is especially true if using technologies such as web services that require an XML schema. When you have example XML files but lack a schema definition for them, Trang comes to the rescue.

The next screen snapshot (click on image to see larger version) displays the Trang help menu when unzipped from its downloadable ZIP file and executed with the Java launcher using the java -jar trang.jar command (trang.jar is an executable JAR) without any options.



To generate a W3C XML Schema that defines the generated XML shown above, run the executable trang.jar command again, but this time specify an input file (the generated XML shown above) and specify an output file after that. In this case, I am running this command as: java -jar trang.jar employees.xml employees.xsd. Trang detects that I want the a W3C XML Schema definition generated for the provided XML file because it recognizes the first listed argument as an XML file based on its extension (.xml) and recognizes the target format based on its extension (.xsd). The Trang manual also explains that you can use explicit options to specify the types of conversions to take place if you don't want to rely solely on file extensions.

When the executable JAR trang.jar is executed as described above, the XSD file is generated that describes the input XML file. That generated XSD file is shown next:

employees.xsd - W3C XML Schema Generated by Trang
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="Employees">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" ref="Employee"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Employee">
<xs:complexType>
<xs:sequence>
<xs:element ref="EMPLOYEE_ID"/>
<xs:element ref="FIRST_NAME"/>
<xs:element ref="LAST_NAME"/>
<xs:element ref="DEPARTMENT_NAME"/>
</xs:sequence>
<xs:attribute name="num" use="required" type="xs:integer"/>
</xs:complexType>
</xs:element>
<xs:element name="EMPLOYEE_ID" type="xs:integer"/>
<xs:element name="FIRST_NAME" type="xs:string"/>
<xs:element name="LAST_NAME" type="xs:string"/>
<xs:element name="DEPARTMENT_NAME" type="xs:string"/>
</xs:schema>


Without much effort on my part, I have a W3C XML Schema file that describes my generated XML. In practical terms, I am likely still going to need to narrow down some of the definitions because it is no surprise that Trang cannot detect more granular datatypes than general types like xs:string. So, I will almost certainly need to create more granular schema types if desired. However, this gives me a compliant starting point to add more specific details as desired.

We are not limited to generating W3C XML Schema with Trang. We can also generate the older, less descriptive Document Type Definition (DTD) with the command: java -jar trang.jar employees.xml employees.dtd. The next listing demonstrates a DTD generated with just such a command.

employees.dtd - Generated by Trang
<?xml encoding="UTF-8"?>

<!ELEMENT Employees (Employee)+>
<!ATTLIST Employees
xmlns CDATA #FIXED ''>

<!ELEMENT Employee (EMPLOYEE_ID,FIRST_NAME,LAST_NAME,DEPARTMENT_NAME)>
<!ATTLIST Employee
xmlns CDATA #FIXED ''
num #REQUIRED>

<!ELEMENT EMPLOYEE_ID (#PCDATA)>
<!ATTLIST EMPLOYEE_ID
xmlns CDATA #FIXED ''>

<!ELEMENT FIRST_NAME (#PCDATA)>
<!ATTLIST FIRST_NAME
xmlns CDATA #FIXED ''>

<!ELEMENT LAST_NAME (#PCDATA)>
<!ATTLIST LAST_NAME
xmlns CDATA #FIXED ''>

<!ELEMENT DEPARTMENT_NAME (#PCDATA)>
<!ATTLIST DEPARTMENT_NAME
xmlns CDATA #FIXED ''>


Trang also allows generation of regular RelaxNG and compact RelaxNG schema definition formats as well. The simple changes to the command to get these two formats as well as the output from each are shown next.

employees.rng - Generated with java -jar trang.jar employees.xml employees.rng
<?xml version="1.0" encoding="UTF-8"?>
<grammar ns="" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
<start>
<element name="Employees">
<oneOrMore>
<element name="Employee">
<attribute name="num">
<data type="integer"/>
</attribute>
<element name="EMPLOYEE_ID">
<data type="integer"/>
</element>
<element name="FIRST_NAME">
<text/>
</element>
<element name="LAST_NAME">
<text/>
</element>
<element name="DEPARTMENT_NAME">
<text/>
</element>
</element>
</oneOrMore>
</element>
</start>
</grammar>


employees.rnc - Generated with java -jar trang.jar employees.xml employees.rnc
default namespace = ""

start =
element Employees {
element Employee {
attribute num { xsd:integer },
element EMPLOYEE_ID { xsd:integer },
element FIRST_NAME { text },
element LAST_NAME { text },
element DEPARTMENT_NAME { text }
}+
}


With the two above examples of RELAX NG schema generation covered, the screen in which all four of these commands were run to generate XML Schema, DTD, RELAX NG, and compact RELAX NG are shown in the next screenshot. Note that there is no obvious output of the generated files, but the files will be found in the directory. For organizational purposes, I had my employees.xml file in a subdirectory called "input" and that is specified as part of the input file name.



Trang allows for multiple XML files to be specified as input as long as they are all passed in before the schema file that you want generated. This is useful if you want to generate one of the four schema types for a collection of related but not necessarily exactly the same XML source documents.

Another common use of Trang, especially in years past, was to migrate existing DTDs to W3C XML Schema. DTDs are necessarily less descriptive than W3C XML Schema, but such a conversion could at least get one started on a compliant Schema that could have greater description added.

Finally, in earlier versions of Java SE 6 there was a bug that prevented Trang from working correctly. However, I ran the examples shown here in Java SE 6, confirming that this bug has been fixed and closed.

The following are some links to Trang-related resources. Some of these were cited above as embedded links.

Publishing User Objects in JMX Notifications

In my Publishing JMX Notifications with Spring blog entry, I demonstrated the use of the Spring framework to publish JMX notifications from Spring-exposed MBeans to clients. In that blog entry, I passed a Java String as the optional User Data object in the published Notification. In this blog entry, I'll cover how to pass a custom object rather than a standard Java String.

The code for the main executable is the same as shown in my last blog entry. Likewise, the Spring configuration XML is also the same as shown in that blog entry and so is not shown here. The one piece of code that is different to supply a custom object to a Notification is the class that is Spring-exposed as an MBean. That class's source code is shown here with the new code highlighted.

SomeJavaObject.java

package dustin.server;

import javax.management.Notification;
import org.springframework.jmx.export.notification.NotificationPublisher;
import org.springframework.jmx.export.notification.NotificationPublisherAware;

/**
* Nothing in this class makes it explicitly a JMX MBean. Instead, Spring will
* expose this as an MBean. The Spring-specific NotificationPublisherAware
* interface is implemented by this class, which means that Spring will also
* allow this bean-turned-MBean to easily publish JMX notifications.
*
* @author Dustin
*/
public class SomeJavaObject implements NotificationPublisherAware
{
private int notificationIndex = 0;
private NotificationPublisher notificationPublisher;
private String someValue = "Nada";

public SomeJavaObject()
{
// empty default constructor
}

public String getSomeValue()
{
return this.someValue;
}

public void setSomeValue(final String aSomeValue)
{
notificationPublisher.sendNotification(
buildNotification(this.someValue, aSomeValue) );
this.someValue = aSomeValue;
}

/**
* Generate a Notification that will ultimately be published to interested
* listeners.
*
* @param aOldValue Value prior to setting of new value.
* @param aNewValue Value after setting of new value.
* @return Generated JMX Notification.
*/
private Notification buildNotification(
final String aOldValue,
final String aNewValue )
{
final String notificationType = "dustin.jmx.spring.notification.example";
final String message = "Converting " + aOldValue + " to " + aNewValue;
final Notification notification =
new Notification( notificationType,
this,
notificationIndex++,
System.currentTimeMillis(),
message );
UserDataObject userData =
new UserDataObject("UserData", "Java Management Extensions");
notification.setUserData(userData);

return notification;
}

/**
* This is the only method required to fully implement the
* NotificationPublisherAware interface. This method allows Spring to
* inject a NotificationPublisher into me.
*
* @param aPublisher The NotificationPublisher that Spring injects into me.
*/
public void setNotificationPublisher(NotificationPublisher aPublisher)
{
this.notificationPublisher = aPublisher;
}
}


In my previous blog entry, I provided a simple String to the Notification.setUserData(Object) method and did not need to do anything else, even on the client side, because String is Serializable and JMX clients understand Java Strings without any extra classpath information. However, with my own custom class now, I'll need to specify more on the classpath when running the JMX client.

First, however, let's define the UserDataObject class used in the code above.

UserDataObject.java

import java.io.Serializable;

/**
* A simplistic data object meant to be used in JMX Notifications as a user
* data object.
*
* @author Dustin
*/
public class UserDataObject implements Serializable
{
private String objectName = null;
private String objectType = null;

/**
* Constructor accepting parameters to set all of my necessary parts.
*
* @param aObjectName
* @param aObjectType
*/
public UserDataObject(final String aObjectName, final String aObjectType)
{
this.objectName = aObjectName;
this.objectType = aObjectType;
}

/**
* Provide String representation of this object for use with JMX Notifications.
*
* @return String representation of me.
*/
@Override
public String toString()
{
return "Name of " + this.objectName + " and type of " + this.objectType;
}
}


Because this UserDataObject will need to be used by the JMX Client that listens for the published JMX Notifications, it is important that this class be declared as Serializable . The code to ensure that this class is Serializable was highlighted above.

If the user data object was not serializable, an error similar to that shown in the following snapshot (click on it to see larger version) would appear.



The error message is repeated in text here for search purposes:

WARNING: Failed to deserialize a notification: java.io.NotSerializableException: dustin.server.UserDataObject


Even with the custom user data object declared as Serializable, JConsole will not be able to display the remote JMX Notifications if run locally with no extra options set. When we try to use JConsole to listen to these published JMX Notifications without specifying any extra options, we'll see an error like that shown in the next screen snapshot (click on image to see larger version).



The main text of this error message is:

WARNING: Failed to deserialize a notification: java.lang.ClassNotFoundException: dustin.server.UserDataObject (no security manager: RMI class loader disabled)


The problem here is that the custom user data object we included in the Notification is not available to JConsole in its classpath when run without options. As shown in Using JConsole - Java SE Monitoring and Management Guide, we can use the -J-Djava.class.path syntax to specify to JConsole (-J) that a Java system property (-D) needs to be specified and then specify the java.class.path system property. The jconsole command to provide this custom user data object is shown next:


jconsole -J-Djava.class.path="%JAVA_HOME%\lib\jconsole.jar";"%JAVA_HOME%\lib\tools.jar";C:\userClient.jar


Because this example was run on Windows, the included class path uses double quotes around the %JAVA_HOME% environment variables and semicolons are used to separate classpath entries. Because I was overriding the JConsole classpath, I needed to provide the jconsole.jar and tools.jar JARs on the classpath in addition to my custom user data class (which I encapsulated in userClient.jar).

Here are the contents of userClient.jar:


0 Sun Feb 17 23:00:00 MST 2008 META-INF/
71 Sun Feb 17 23:00:00 MST 2008 META-INF/MANIFEST.MF
805 Sun Feb 17 22:50:34 MST 2008 dustin/server/UserDataObject.class


With the custom user data object specified as Serializable and provided on the classpath to the JMX client (JConsole), we can now see the successful results. The first of the next two screen snapshots shows a snippet of running the main application and entering three strings to be published in the JMX Notification. The second of the next two screen snapshots shows the JMX Notifications received by the JConsole listener when it is executed as shown above and in the first screen snapshot.





In this blog entry, I have attempted to demonstrate how custom user data objects can be associated with JMX Notifications even when they are published to remote clients. The two main things to remember are to make the user data object serializable and to make it available on the client's classpath.


UPDATE:
Two useful forum threads on custom objects on the JMX client side and ways to work with them are jconsole context classloader issue and jconsole no security manager exception (RMI classloader disabled).