Saturday, December 13, 2008

JavaFX missing the boat

I was looking at all of the effort that went into JavaFX. Sun has really done a good job with it. It does some really cool things: effects, animations, simple declarative style, etc.

It is missing something... Usefulness.

I think that it is really neat. Don't get me wrong. I am wondering based on Sun's history and recent pull-back from projects it has called "the next big thing", that this will fall into the heap of ideas that fail to get momentum (sustainable momentum).

I have waited for two years (JavaOne 2007) for this to come out. In that two years, we have had plenty of hype, but no substance. Sun's chance at getting into the RIA space has been diminishing during this time. The folks that are/were most interested in this type of technology have adopted Adobe Flash, Flex, and Air, or have moved to Microsoft Silverlight.

Who is this technology designed for?

A few years ago, Sun had a product called Sun Studio Creator. It had this vision of making it easier for web developers to develop sophisticated JSF and EJB technology based sites. The idea was to make the tool easy enough for non-programmers to use these powerful technologies. It never gained critical mass. That technology was transferred over to NetBeans as Visual Web Pack in its first editions. Later this became Visual JSF in NetBeans (Project Woodstock). Sun has since abandoned the project.

Now Sun has another framework based on the same idea that we can get visual designers to work with Java developers to do the same thing again, but with a twist. Visual designers won't do ANY development, just provide their creative work to Java developers to implement.

Interesting.

I am an enterprise developer. I create applications for business users to use. These are primarily web based, but I also do a lot of Swing development. When I want to create an application for end users to access SAP, I don't need drop shadows, 3D animations, or transitions. I need a simple elegant interface to enter data. I have never seen a visual designer, nor do I need one. I need a technology that just works.

I shouldn't need a visual designer to create "pretty" pictures for my applications.

The majority of the companies I am familiar with are in the same boat. We don't need fancy JavaFX... we need Swing to work.

I would rather have had some folks at Sun work on JSR-295 Beans Binding and JSR-296 Swing Application Framework. These were Sun's next big things at JavaOne 2005 and JavaOne 2006.

Where do we go from here?

JavaFX is really cool. I suggest you go check out the demos if you have a Windows, or Mac based machine. Linux users will need to wait. It has not been released for Linux.

It is also quite apparent that someone in marketing who does not get it, came up with some of the current name changes: Stage and Scene. Really??? So I need to learn new names for something that should be transparent. That is a permanent mistake!

Tooling needs to be improved. In its initial release, the tools in NetBeans 6.5 are mediocre at best. I have been waiting for the technology and tools for two years. The initial tooling release is disappointing at its best, and better left undiscussed in polite company at its worst.

Swing tooling with Matisse, and Visual JSF are much more mature and better.

I will probably try some experiments with JavaFX, but it is not ready for the prime time of critical business application development and deployment.

In the December issue of eWeek magazine, Spencer Katt has an article on the last page which has a cartoon with the tag line "Adobe Releases 64-bit Version of Flash For Linux". In the cartoon, the Linux penguin asks Spencer what his favorite feature in Flash is. He replies "The skip-intro button". Let's hope that is not the fate of JavaFX.

Tuesday, November 25, 2008

JSF 1.2 : Project Woodstock Add/Remove Component Example

There have been a number of people who have asked me for example code on how to use Woodstock (Visual JSF) add/remove component examples. I have decided to post a proof-of-concept piece for people to use. It is using Woodstock 4.3 Build 7, but should work on 4.2 if you change the theme library to use 4.2 in the code.

Here is the code example: WoodstockAddRemoveComponentExample.

Sunday, November 02, 2008

DZone™ GlassFish Application Server Refcardz™

Just finished examining the GlassFish Application Server Refcardz by Masoud Kalali. The reference card is very well done, but is targeted primarily at new administrators. The information contained on the card is in digestible well defined topics. It provides the Cliff Notes™ version of the installation and administration guides. It is perfect for new administrators who may need a quick reference on how to set up and administer GlassFish.

If you are a developer, or administrator who is using GlassFish for the first time; I would recommend it with 4/5 stars.

If you are a seasoned Glassfish developer, or administrator, I would give it 2/5 stars, only because of its limited usefulness.

Effective Tools and Techniques for the Java Developer - InformIT white paper

I just finished reading a white paper from InformIT. It is essentially excerpts from a number of books from well know authors like Joshua Bloch, and Kent Beck. The sections they included were good, but like all good things...they must come to an end.

The sections did not cover the topics in their entirety, and in most cases ended in the middle of a topic. It is a taste teaser. I will note that although you really can't accomplish much from the excerpts, it does give you a good feel for the books and authors.

Saturday, November 01, 2008

ICEFaces 1.7.2 and NetBeans 6.1

I downloaded and installed ICEFaces 1.7.2 and its modules for NetBeans 6.1. My conclusion is that is not ready for primetime on NetBeans.

I would recommend that you read the release notes very carefully. The newest version of ICEFaces is not JSF 1.2 compliant. It needs to run in compatibility mode. This requires you to modify the faces-config.xml and web.xml files. This is a major pain point.

The next thing I noticed is that the design-time implementations are not complete. The ability to visually manipulate the components needs some serious work.

I attempted to do one of the tutorials to create a CRUD application using Netbeans. It was very flaky and did not cover the details adequately. In the end I got the application to deploy, and I could click on the table rows, but it did not work as it did in the tutorial.

I have used ICEFaces in the past and I do like their product in general, but it needs to come up to speed with the rest of the world on JSF 1.2 .Its support for NetBeans needs to have more than token capabilities, and it should account for its compatibility issues without intervention from the end user.

The Java Developer's Guide to Web Development

I just read a white paper from Sun called the The Java Developer's Guide to Web Development It is published on Internet.com. I was totally unimpressed. It is a collection of short articles on web frameworks including Wicket, Struts, Stripes, Tapestry, MyFaces, and Spring MVC.

The articles are too short to give you a good feel for the frameworks. At the end of the white paper I felt that I had just wasted a good couple of hours going over it. If you get an email from SDN on it, don't waste your time. I did it for you.

Monday, October 20, 2008

Happy 10th Birthday NetBeans

It is hard to believe that NetBeans is 10 years old. It seems like it was just yesterday that I switched from Sun Forte, Sun Studio Enterprise, and Sun Studio Creator to NetBeans. Don't get me wrong some of these IDEs were more polished at the time, and based on NetBeans in some cases. NetBeans just kept growing and the other IDEs fell by the wayside.

Why have multiple code bases? Sun made a good decision to focus on the community tool instead of wasting time on multiple code bases. It took time to get to this point though, but I think we can all agree it was a good decision.

I am participating in the NetBeans Decathalon. They wanted to know how I use NetBeans. Well as you can see from my blog... I use it on everything! On a serious note, I use NetBeans to develop enterprise class applications for my employer. It is a complete package from head to toe to accomplish this task. Most of my applications are JSF based interacting with JMS, EJBs, and Web Services. All of this on top of Project GlassFish.

My biggest project with NetBeans was using Visual JSF a.k.a Visual Web Pack (VWP) (Project Woodstock) to develop a timesheet tracking system which linked to our field force automation system and SAP.

This is also my favorite NetBeans story...

I decided to use VWP in NetBeans 5.0 to start the development. As more features were added to VWP, I kept upgrading. Eventually I was using 5.5 nightly builds along with Glassfish nightly builds. This became our production environment. NetBeans 6.0 nightly builds and GlassFish V1 Build 48. I just took Glassfish B48 out of production last week and replaced it with V2 UR2. This is a testament to how solid Glassfish is, and how useful NetBeans was in accomplishing my task.

I have been tasked to update this application by years end. I am waiting for NetBeans 6.5 to be released before I start. I am also waiting for some definitive word on Project Woodstock.

Happy Birthday NetBeans...

Saturday, September 27, 2008

OpenDS LDAP and GlassFish Configuration

Introduction

A question was posted to our JUG mailing list on how to lock a directory which contained an Adobe™ PDF file. In this example I want to cover a couple of really cool technologies, and how to implement them.

OpenDS is a project hosted on Java.net. It is an open source directory server which is based on the Sun™ SunOne™ Directory server and its predecessors (Netscape™ iPlanet™). It has a binary, or a Java™ Webstart deployment mechanism. It has a simple quick start setup including SSL based LDAP, and directory replication.

This is a simple to install, easy to use and configure, no-nosense LDAP server. It is a great server for prototyping.

Project Glassfish is an open source Java EE application server. It is simple to install and configure, and easy to use. The chances are pretty good that if you are reading this blog, you are familiar with its enormous benefits.

Case

The developer has a pdf file that is located inside a web project on the web server. The file can be bookmarked by users, but the developer wants to make sure that the user authenticates with the server before the file is displayed.


Software and Files Required


Setup

1. Download and install Glassfish

Note: When Glassfish is installed it creates its own self-signed SSL certificates. We will use this certificate later.
2. Start the installation of OpenDS



3. Create a new instance.

4. Accept the default installation directory. Set the password for the cn=Directory Manager to test.



5. Press the Configure button to configure the secure LDAP connection.
  • Set the Key Store Type to Java Key Store (JKS).
  • Set the key store path to point to the keystore.jks file located in the GLASSFISH_HOME/domains/domain1/config directory.
  • Set the Key Store Pin to changeit.


Note: "changeit" is the default password to the keystore. You will need to "change it" for a production system.




6. Select the default for topology options and continue to Directory Data Next.



  • Directory Data should have the default Directory Base DN: dc=example,dc=com
  • Select Import Data from LDIF file and use this example.ldif file. Next.

Note: I have created a pre-generated list of users previously. In this example, I have created a group and assigned it members. So to simplify the example, please use the example.ldif file.




7. Review the selections and Finish.



8. Authenticate with the server using cn=Directory Manager and password "test".






Note: A message will pop-up asking if you want to accept the certificate for the LDAP server. Use the this session only option.




Congrats. You now have a running LDAP server.

If you want to explore the contents of the directory use a tool like JXplorer, or Apache Directory Studio.

Now we need to configure our LDAP Security Realm in Glassfish. You may have multiple realms in Glassfish to accommodate application requirements.

1. Start Glassfish and login on http://localhost:4848. The default user is admin and password is adminadmin.

2. Go to Configuration --> Security --> Realms. Create a new Realm

  • Name: OpenDS
  • Class: com.sun.enterprise.security.auth.realm.LDAPRealm
  • JAAS context: ldapRealm
  • Directory: ldaps://localhost:1636
  • Base DN: dc=example, dc=com
  • Assign Group: ou=Groups,dc=example,dc=com
3. Add a property called group-target.
  • group-search-filter: member=%d





Note: The group-search-filter defines the attribute to look at when determining members of the groups. It may be member, memberurl, etc. depending on how you define your groups. In the example.ldif file, I have define the group as a groupOfNames which contains member [0...] attributes. The %d format expands to match the Relative Distinguished Name (RDN).


4. Save and you are done.

You have now configured Glassfish to use OpenDS.

Note: Since we configured it to use secure LDAP, remember to configure your server to use SSL to authenticate users. Otherwise the secure LDAP portion is a waste if the users are transmitting their usernames and passwords in cleartext over the network
I have created a sample Netbeans project which takes advantage of the new LDAP authentication. The project creates a page with a link to a PDF file located in a secured directory. The directory requires the user to authenticate using basic authentication implemented in the browser. If you fail to authenticate, it will produce a 403 error. The project is located here.

Once you successfully authenticate, you will see a list of popular software that runs on Glassfish.

Tuesday, September 02, 2008

Netbeans License Templates

I have created a couple of license templates for use in Netbeans.

1. You will need to go to Tools -->Templates -->User Configuration Properties -->User.properties and Open in Editor

2. Update the user property to your name. Add another line called company and provide the company name.


#
# Here, or in other properties files in this directory, you can define
# various properties that you want to make available to the template
# processor while creating various templates.
#

# uncomment the next line and specify your user name to be used
# in new templates
user=John Yeary
company=Blue Lotus Software, LLC

3. Next download the licenses you are interested in from below.

4. Go to Tools -->Templates -->Licenses and click on the Add button.

5. Select the license file you downloaded.

6. To use the license, edit the project.properties file and add project.license= to match the license, i.e., bsd, mit, etc.

7. The license name is based on the format license-XXXX.txt

Sunday, August 31, 2008

Sun™ Certified Java™ Programmer Boot Camp

The Greenville Java Users Group (GreenJUG) is conducting an ten (10) week boot camp to prepare its members for the CX-310-065 exam. It is a great opportunity to get a better understanding of Java™ and a obtain a valuable industry certification.

The code examples, books, and notes can be found on the Blue Lotus Software Sun™ Certified Java™ Programmer (SCJP) Boot Camp site. All of the code is Open Source Apache 2 licensed. The schedule for classes and final exam preparation are on the GreenJUG site.

Friday, August 29, 2008

Making a System Call in Java

This is an example on how to make a system call to the local operating system to execute external programs. This example was written to work on Mac OS X, but will work on other UNIX type operating systems likely without issue. It will not work as written on Windows unless Cygwin is installed and in the PATH.


1 /*
2 * $Id: SystemCallExample.java 106 2008-08-30 00:58:59Z jyeary $
3 *
4 * Software License Agreement (BSD License)
5 *
6 * Copyright (c) 2008, Blue Lotus Software, LLC
7 * All rights reserved.
8 *
9 * Redistribution and use of this software in source and binary forms, with or
10 * without modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * Redistributions of source code must retain the above
14 * copyright notice, this list of conditions and the
15 * following disclaimer.
16 *
17 * Redistributions in binary form must reproduce the above
18 * copyright notice, this list of conditions and the
19 * following disclaimer in the documentation and/or other
20 * materials provided with the distribution.
21 *
22 * Neither the name of Blue Lotus Software, LLC nor the names of its
23 * contributors may be used to endorse or promote products
24 * derived from this software without specific prior
25 * written permission of Blue Lotus Software, LLC
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
28 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
29 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
30 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
33 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
34 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36 package com.bluelotussoftware.examples;
37
38 import java.io.BufferedInputStream;
39 import java.io.BufferedReader;
40 import java.io.IOException;
41 import java.io.InputStream;
42 import java.io.InputStreamReader;
43
44 /**
45 * This is a demo application on how to use Java to make system calls.
46 * The use of system calls is platform specific. This code may not be
47 * transportable accross platforms,i.e. UNIX, Mac OS X, and Windows.
48 * @author John Yeary
49 * @version 1.0
50 */
51 public class SystemCallExample {
52
53 /**
54 * Creates a new instance of SystemCallExample
55 */
56 public SystemCallExample() {
57 }
58
59 /**
60 * Main program method
61 * @param args the command line arguments
62 */
63 public static void main(String[] args) {
64 Runtime r = Runtime.getRuntime();
65
66 try {
67 /*
68 * Here we are executing the UNIX command ls for directory listing.
69 * The format returned is the long format which includes file
70 * information and permissions.
71 */
72 Process p = r.exec("ls -l");
73 InputStream in = p.getInputStream();
74 BufferedInputStream buf = new BufferedInputStream(in);
75 InputStreamReader inread = new InputStreamReader(buf);
76 BufferedReader bufferedreader = new BufferedReader(inread);
77
78 // Read the ls output
79 String line;
80 while ((line = bufferedreader.readLine()) != null) {
81 System.out.println(line);
82 }
83 // Check for ls failure
84 try {
85 if (p.waitFor() != 0) {
86 System.err.println("exit value = " + p.exitValue());
87 }
88 } catch (InterruptedException e) {
89 System.err.println(e);
90 } finally {
91 // Close the InputStream
92 bufferedreader.close();
93 inread.close();
94 buf.close();
95 in.close();
96 }
97 } catch (IOException e) {
98 System.err.println(e.getMessage());
99 }
100 }
101 }
102

Saturday, August 16, 2008

How to implement EJB 3.0 <env-entry/> in ejb-jar.xml

A topic which is mentioned in the EJB 3.0 Specification (JSR-220) is the ability to add environment entries in ejb-jar.xml file. What I found interesting is that I could not Google for a good example of how to implement it. As a result, I thought I would provide a good simple example.

The first item you should examine is the schema resources for Java EE. Specifically we want to examine the ejb-jar_3_0.xsd. This file contains all of the information we need to create and validate an ejb-jar.xml file.

First we create an ejb-jar.xml file in our EJB project. This file should contain the following information at a minimum:


1 <?xml version="1.0" encoding="UTF-8"?>
2 <ejb-jar
3 xmlns="http://java.sun.com/xml/ns/javaee"
4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
6 http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
7 version="3.0">
8 </ejb-jar>

From here we can add our beans and environment variables. I have created an example project which demonstrates how to use the environment variables. Here is my ejb-jar file:

1 <?xml version="1.0" encoding="UTF-8"?>
2 <ejb-jar
3 xmlns="http://java.sun.com/xml/ns/javaee"
4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
6 http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
7 version="3.0">
8 <enterprise-beans>
9 <session>
10 <ejb-name>EnvironmentalResourceInjectionExampleBean</ejb-name>
11 <env-entry>
12 <env-entry-name>s1</env-entry-name>
13 <env-entry-type>java.lang.String</env-entry-type>
14 <env-entry-value>Hello</env-entry-value>
15 </env-entry>
16 <env-entry>
17 <env-entry-name>s2</env-entry-name>
18 <env-entry-type>java.lang.String</env-entry-type>
19 <env-entry-value>EJB Resource Injection World!</env-entry-value>
20 </env-entry>
21 </session>
22 </enterprise-beans>
23 </ejb-jar>
In my example, I use a stateless session bean with @WebService annotation. This allows me to test it right in GlassFish. I also use the @Resource annotation to inject my environment entries. I have used the name attribute to give it a JNDI lookup value. This works for GlassFish. Other containers may use the mappedName attribute.

Here is my stateless session bean:

1 /*
2 *
3 * Blue Lotus Software, LLC
4 *
5 * $Id: EnvironmentalResourceInjectionExampleBean.java 100 2008-08-16 21:57:19Z jyeary $
6 *
7 * Copyright [2008] [John Yeary]
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 package com.bluelotussoftware.ee.examples;
19
20 import javax.annotation.Resource;
21 import javax.ejb.Stateless;
22 import javax.jws.WebMethod;
23 import javax.jws.WebService;
24
25 /**
26 *
27 * @author John Yeary
28 * @version 1.0
29 */
30 @Stateless
31 @WebService
32 public class EnvironmentalResourceInjectionExampleBean implements
33 EnvironmentalResourceInjectionExampleRemote,
34 EnvironmentalResourceInjectionExampleLocal {
35
36 @Resource(name = "s1")
37 String s1;
38 @Resource(name = "s2")
39 String s2;
40
41 public String printEnv() {
42 return s1 + " " + s2;
43 }
44
45 @WebMethod
46 public String printEnvironment() {
47 return printEnv();
48 }
49 }

When I deploy the application to GlassFish, I can use the Web Service Tester to validate that I get the injected values.




As we can see, the values s1 and s2 are sucessfully injected. The complete Netbeans 6.1 project and source can be found here.

Sunday, June 29, 2008

JSF Custom Validator Example

I found another Sun Java Creator 2 example for using a custom validator. This may have also been an example from Creator, but I updated its project files to work with Netbeans 6.1. I updated the project so that the original visual JSF files can still be manipulated visually.





Here is a link to the Netbeans project: CustomValidatorExample.zip

Saturday, June 28, 2008

JSF Custom Message Example

I came across an old Sun Java Studio Creator 2 custom message example. This may have originally been an example project on the IDE. I am not sure so I can not make claim to doing the original coding. I did however bring it up to speed on Netbeans 6.1. I transferred the code and updated the project so that it will build and it works very nicely. The result is a page which prompts you for a value and should you submit it without one, it will pop up an error message.



NOTE: The application is not a Visual JSF example.

Here is a link to the Netbeans project : CustomMessage.zip

Java RandomAccessFile Example

Here is another example of how to use a common file handling mechanism in Java. RandomAccessFile is very powerful tool to open a file and find specific items in it. It also allows you to update, delete, or append data to the file. Developers become accustomed to using File for a number of operations, but I contend that using RandomAccessFile is more powerful and flexible.

In the code example and Netbeans project that follow, I create a file and append data to it. I print the data out, and then add the class name to the beginning of the file, append the existing data, and print it back out again.

I originally came across my work on it when I was learning Java many years ago. I re-examined it, tweaked it, and converted it to a Netbeans project.

1 /*
  2  * 
  3  * Blue Lotus Software, LLC
  4  * 
  5  * Copyright 2008. All Rights Reserved.
  6  * 
  7  * $Id$
  8  * 
  9  */
 10 /*
 11  * Copyright (C) 2008 Blue Lotus Software. All Rights Reserved.
 12  *
 13  * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY KIND.
 14  * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
 15  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
 16  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. 
 17  * BLUE LOTUS SOFTWARE, LLC AND ITS LICENSORS SHALL NOT BE LIABLE 
 18  * FOR ANY DAMAGES OR LIABILITIES
 19  * SUFFERED BY LICENSEE AS A RESULT OF  OR RELATING TO USE, MODIFICATION
 20  * OR DISTRIBUTION OF THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
 21  * BLUE LOTUS SOFTWARE, LLC OR ITS LICENSORS BE LIABLE FOR ANY LOST 
 22  * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, 
 23  * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED 
 24  * AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE 
 25  * OF OR INABILITY TO USE SOFTWARE, EVEN IF BLUE LOTUS SOFTWARE, LLC 
 26  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 27  *
 28  * You acknowledge that Software is not designed, licensed or intended
 29  * for use in the design, construction, operation or maintenance of any
 30  * nuclear facility.
 31  */
 32 package com.bluelotussoftware.j2se.examples;
 33
 34 import java.io.FileNotFoundException;
 35 import java.io.IOException;
 36 import java.io.RandomAccessFile;
 37 import java.util.logging.Level;
 38 import java.util.logging.Logger;
 39
 40 /**
 41  *
 42  * @author John Yeary
 43  * @version 1.0
 44  */
 45 public class RandomAccessFileExample {
 46
 47     private static final String CLASSNAME = RandomAccessFileExample.class.getName();
 48     private static Logger logger = Logger.getLogger(CLASSNAME);
 49
 50     /**
 51      * @param args the command line arguments
 52      */
 53     public static void main(String[] args) {
 54
 55         if (args.length < 1) {
 56             System.err.print("You must provide at least a file name with path!");
 57             logger.log(Level.WARNING, "You must provide at least a file name with path");
 58             System.exit(0);
 59         }
 60
 61         RandomAccessFile raf = null;
 62
 63         try {
 64             raf = new RandomAccessFile(args[0], "rw");
 65         } catch (FileNotFoundException e) {
 66             logger.log(Level.SEVERE, null, e);
 67             // Error, set return to 1, and exit 
 68             System.exit(1);
 69         }
 70
 71         for (int i = 1; i < args.length; i++) {
 72             try {
 73                 raf.seek(raf.length());
 74                 raf.writeBytes(args[i] + "\n");
 75             } catch (IOException e) {
 76                 logger.log(Level.SEVERE, null, e);
 77             }
 78         }
 79
 80         try {
 81             raf.close();
 82         } catch (IOException e) {
 83             logger.log(Level.SEVERE, null, e);
 84         }
 85
 86         RandomAccessFileExample.readRAF(args[0]);
 87
 88         try {
 89             raf = new RandomAccessFile(args[0], "rw");
 90
 91             /* If you call seek() before you read, it will not work
 92              * as expected. The read operation will move the cursor
 93              * to the end of the read method.
 94              */
 95             //raf.seek(0); 
 96
 97             byte[] b = new byte[(int) raf.length()];
 98             raf.read(b);
 99
100             /* Here we place the seek() method to append to
101              * start writing at the beginning of the file.
102              */
103             raf.seek(0);
104             raf.writeBytes(CLASSNAME + "\n");
105
106             // Append the original content of the file.
107             raf.write(b);
108             raf.close();
109         } catch (IOException ex) {
110             logger.log(Level.SEVERE, null, ex);
111         }
112         RandomAccessFileExample.readRAF(args[0]);
113     }
114
115     public static void readRAF(String fileName) {
116         try {
117             RandomAccessFile raf = new RandomAccessFile(fileName, "r");
118             String line = null;
119             while ((line = raf.readLine()) != null) {
120                 System.out.println(line);
121                 logger.log(Level.INFO, line);
122             }
123         } catch (FileNotFoundException ex) {
124             logger.log(Level.SEVERE, null, ex);
125         } catch (IOException ex) {
126             logger.log(Level.SEVERE, null, ex);
127         }
128     }
129 }

UPDATED 12/29/2009
The Netbeans project is here: RandomAccessFile.zip

Here is an example of how to delete a String value from the file.

public static void deleteRAF(String value, String fileName) {
        try {
            RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
            long position = 0;
            String line = null;
            while ((line = raf.readLine()) != null) {
                System.out.println("line::line.length()::position::getFilePointer()");
                System.out.println(line + "::" + line.length() + "::" + position + "::" + raf.getFilePointer());
                logger.log(Level.INFO, line);

                if (line.equals(value)) {
                    //Create a byte[] to contain the remainder of the file.
                    byte[] remainingBytes = new byte[(int) (raf.length() - raf.getFilePointer())];
                    System.out.println("Remaining byte information::" + new String(remainingBytes));
                    raf.read(remainingBytes);
                    //Truncate the file to the position of where we deleted the information.
                    raf.getChannel().truncate(position);
                    System.out.println("Moving to beginning of line..." + position);
                    raf.seek(position);
                    raf.write(remainingBytes);
                    return;
                }
                position += raf.getFilePointer();
            }
        } catch (FileNotFoundException ex) {
            logger.log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            logger.log(Level.SEVERE, null, ex);
        }
    }

Friday, June 27, 2008

Putting the Current Directory in the CLASSPATH

Someone from our users group posed a good question. Should you put the current directory in the CLASSPATH? Does it represent any security issues like on UNIX?

Here is the answer...depends, but it is generally a bad idea. Here is an example. I created a class called TestCase. It calls another class called ClassA in a jar file called ExampleJar.jar. I put another class called ClassA in the current directory and set the CLASSPATH as a passed parameter

java -classpath .:./lib/ExampleJar.jar TestCase
Here are the classes:


1 public class TestCase {
2
3 public TestCase() {
4 }
5
6 public static void main(String[] args) {
7 ClassA a = new ClassA();
8 a.print();
9 }
10 }


1 public class ClassA {
2
3 public void print() {
4 System.out.println("I am ClassA in a jar.");
5 }
6 }


1 public class ClassA {
2
3 // Bad apple!!!
4 public void print() {
5 System.out.println("I am ClassA in the wild...");
6 }
7 }


The question becomes which one of the ClassA files gets called? The legitimate one, or the bad apple?

[sundev:Desktop:root]#java -classpath .:lib/ExampleJar.jar TestCase
I am ClassA in the wild...
If I reverse the order to java -classpath lib/ExampleJar.jar:. TestCase

I get the expected result:

[sundev:Desktop:root]#java -classpath lib/ExampleJar.jar:. TestCase
I am ClassA in a jar.
The Classloader finds the first instance of the class which matches the appropriate signature and loads it. Subsequent classes of the same name and signature are not loaded.

Why does it matter?

The inclusion of the current directory into the CLASSPATH represents a potential security risk, also it may produce unexpected results from similarly named classes. The second item may be a bit more contrived in general terms, i.e. com.abc.ClassA and com.cba.ClassA are called ClassA, but are in different packages. This will not represent a problem.

The security issue can be real. A lot of programs that do installs on Windows specifically, add the CLASSPATH variable to the Windows environment and put the . (period) first. I checked my installation and found it to be the case. I would not knowingly put it there myself. Also I checked a couple of tutorials which suggest that you should do it for convenience. That piece is quickly forgotten 200 pages ago.

ADDENDUM:

Java 6 SE (J6SE) has added some additional enhancements around classpath. You can use the * (asterisk) wildcard to include all files in the classpath:

java -cp "*"; TestCase (Windows)
java -cp '*' TestCase (Unix/OS X)

Mark Reinhold has a blog entry entitled Class-Path Wildcards in Mustang which details it.

Tuesday, June 24, 2008

Sample QuartzScheduler Job connecting to HSQLDB

I was cleaning up my system and looking at code samples from over the years. I came across an example Job using the Quartz Scheduler to connect to an HSQLDB database and reading the information about the session. I thought I would update it a little and post it.

Requirements:

You must have an HSQLDB database running in server mode.


package com.bluelotussoftware.quartz.example;

/*
* HSQLJob.java
*
*/

/*
* Copyright (C) 2008 Blue Lotus Software. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY KIND.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* BLUE LOTUS SOFTWARE, LLC AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES OR LIABILITIES
* SUFFERED BY LICENSEE AS A RESULT OF OR RELATING TO USE, MODIFICATION
* OR DISTRIBUTION OF THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* BLUE LOTUS SOFTWARE, LLC OR ITS LICENSORS BE LIABLE FOR ANY LOST
* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
* CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED
* AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE
* OF OR INABILITY TO USE SOFTWARE, EVEN IF BLUE LOTUS SOFTWARE, LLC
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that Software is not designed, licensed or intended
* for use in the design, construction, operation or maintenance of any
* nuclear facility.
*/

/*
* Copyright 2008 John Yeary
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

/**
*
* @author John Yeary
* @version 1.0
*/
public class HSQLJob implements Job {

Connection con;
Statement s;
ResultSet rs;
ResultSetMetaData rsmd;

/** Creates a new instance of HSQLJob */
public HSQLJob() {
}

public void execute(JobExecutionContext context)
throws JobExecutionException {

try {
Class.forName("org.hsqldb.jdbcDriver");
} catch (Exception e) {
System.err.println("ERROR: failed to load HSQLDB JDBC driver.");
e.printStackTrace(System.err);
throw new JobExecutionException("Job Could not continue bacause driver failed to load");
}

System.out.println("Connecting to database...");

try {
// This may need to be changed to match the actual database name
con = DriverManager.getConnection("jdbc:hsqldb:hsql://localhost/glassfish", "sa", "");
} catch (SQLException e) {
throw new JobExecutionException("Failed to connect to HSQLDB Server");
}

try {
String sql = "SELECT * FROM INFORMATION_SCHEMA.SYSTEM_SESSIONINFO";
s = con.createStatement();
rs = s.executeQuery(sql);
rsmd = rs.getMetaData();
for (int i = 1; i <= rsmd.getColumnCount(); i++) {
System.out.print(rsmd.getColumnName(i) + "\t");
}
System.out.println();
while (rs.next()) {
for (int i = 1; i <= rsmd.getColumnCount(); i++) {
System.out.print(rs.getString(i) + "\t");
}
System.out.println();
}

// Clean up the connection
rs.close();
s.close();
con.close();

} catch (SQLException e) {
System.err.println(e.getMessage());
while (e.getNextException() != null) {
System.err.println(e.getMessage());
}
}
}
}




package com.bluelotussoftware.quartz.example;

/*
* QrtzScheduler.java
*
*/

/*
* Copyright (C) 2008 Blue Lotus Software. All Rights Reserved.
*
* THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT A WARRANTY OF ANY KIND.
* ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
* BLUE LOTUS SOFTWARE, LLC AND ITS LICENSORS SHALL NOT BE LIABLE
* FOR ANY DAMAGES OR LIABILITIES
* SUFFERED BY LICENSEE AS A RESULT OF OR RELATING TO USE, MODIFICATION
* OR DISTRIBUTION OF THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL
* BLUE LOTUS SOFTWARE, LLC OR ITS LICENSORS BE LIABLE FOR ANY LOST
* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
* CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED
* AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE
* OF OR INABILITY TO USE SOFTWARE, EVEN IF BLUE LOTUS SOFTWARE, LLC
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that Software is not designed, licensed or intended
* for use in the design, construction, operation or maintenance of any
* nuclear facility.
*/

/*
* Copyright 2008 John Yeary
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.text.ParseException;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;

public class QrtzScheduler {

public static void main(String[] args) {
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler;
try {
scheduler = schedulerFactory.getScheduler();
scheduler.start();

JobDetail job = new JobDetail("hsqldb_example",
scheduler.DEFAULT_GROUP, HSQLJob.class);
CronTrigger cron = new CronTrigger("cron",
scheduler.DEFAULT_GROUP, "0/10 * * * * ?");
scheduler.scheduleJob(job, cron);

} catch (SchedulerException e) {
} catch (ParseException e) {
}
}
}



The Netbeans 6.1 project is located here: HSQLDBQuartzExample.zip

Sunday, June 22, 2008

The Tipping Point : How Little Things Can Make A Big Difference

I just finished reading the book The Tipping Point by Malcolm Gladwell. On the surface this does not seem to be a book on programming, and it is not.

I really liked the book because it assembled a number of political and social theories into a readable and digestible items. The Broken Windows Theory, which makes hypothesized that if a vacant building gets a broken window, you should fix it as soon as possible. The consequences of not-fixing it result in people assuming that no one really cares. The result is the rest of the windows getting broken. If you fix the window, then it is likely that no further damage will be done. This policy was implemented in New York in the 1990s. The result was a dramatic reduction in crime, and vandalism. This is the case of making a small change which results in further downstream effects. The explanation in the book is insightful and makes these theories easy to understand.

How does it relate to software and technology? It covers a methodology for making trends and social behaviors "stick". The ideas covered in the book speak in terms of epidemics. Those who understand viral expansion loops (viral marketing) will be able to understand the book and its underlying premises. If you are looking for some material on viral expansion loops (Viral Marketing), there is a really good one on Fast Company which is very well done. Fast Company had a cover article for May 2008 on CEO Gina Bianchini of Ning. They mention the use of viral expansion to attempt to grow Ning into a social powerhouse.

The book details items on how to make things stick, and how to spread the word about something. My stickiness factor is how to make social networks stick. For example, why is Facebook becoming more popular than MySpace. Why do people use LinkedIn? What benefits are there to blogging. This book can provide a wealth of information into social and environmental factors which make software and technologies popular.

The book is a real quick read, and I would recommend it with 4/5 stars.

Wednesday, June 18, 2008

Apache Derby (JavaDB) INSERT Statement with IDENTITY

If you are trying to insert values into a table which has an identity column, the documentation is not very clear. If I create a table in an Apache Derby (JavaDB) database which has a primary key which is generated always, the syntax for doing a query based insert is a little different.

Here is the table:
CREATE TABLE FAMILY (
ID INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
DESCRIPTION VARCHAR(50) NOT NULL
)
Now if I want to insert values from another table here is the query I used:
INSERT INTO FAMILY (DESCRIPTION) ( SELECT DISTINCT FAMILY FROM EQUIPMENT_GROUP WHERE FAMILY IS NOT NULL)
Please note that I did not put anything into the ID column. If I try to specify a value, it will result in an exception
Exception: Attempt to modify an identity column 'ID'.
Since the column has been marked as GENERATED ALWAYS, it handles incrementing the key and assigning it.

Monday, June 16, 2008

Configuring Apache 2 HTTP Server on Solaris 10

How do you configure Apache 2 HTTP Server to run automatically on Solaris 10 using rc init scripts.

Log into the Solaris box as root, or su root.
Go to the /etc/init.d directory.
Copy the apache startup script to apache2
cp apache apache2

Change the group to sys
chgrp sys apache2
Next change the flags on the file to execute
chmod u+x apache2
Open the apache2 file with your favorite editor and modify the following lines:

APACHE_HOME=/usr/apache
CONF_FILE=/etc/apache/httpd.conf
RUNDIR=/var/run/apache
PIDFILE=${RUNDIR}/httpd.pid

as follows:

APACHE_HOME=/usr/apache2
CONF_FILE=/etc/apache2/httpd.conf
RUNDIR=/var/run/apache2
PIDFILE=${RUNDIR}/httpd.pid

Check to make sure you have a valid httpd.conf file located in /etc/apache2. You can copy the httpd.conf-example file to httpd.conf. This will create a basic httpd.conf file.

Next go to the /etc/init.d directory and try executing the apache2 file. You should see something like this:

[dev1:init.d:root]#./apache2 start
httpd starting.
You can check your configuration by using a browser to check it.

Next you will want to configure it to start/stop at the various runlevels.

Go to /etc/rc0.d and add the following:
ln -s ../init.d/apache2 K17apache2
Go to /etc/rc1.d and add the following:
ln -s ../init.d/apache2 K17apache2
Go to /etc/rc3.d and add the following:
ln -s ../init.d/apache2 S51apache2
Go to /etc/rcS.d and add the following:
ln -s ../init.d/apache2 K17apache2

This will complete the configuration for your server. Next time you change run levels, or reboot, the Apache 2 HTTP Server will restart as you expect.

Addendum:

Zaphod commented on my page about using Solaris SMF. This is truly easier.

1. Check to make sure you have a valid httpd.conf file located in /etc/apache2. You can copy the httpd.conf-example file to httpd.conf. This will create a basic httpd.conf file.

2. Execute svcadm -v enable -rs apache2

3. You are now running on Apache2 on SMF.

Saturday, June 14, 2008

Disabling JavaServer Pages (JSP) Expression Language (EL) and Scripting

I was looking at some JSP pages which contained a bunch of JSP script and JSP Expression Languange (EL) tags. The question was how to disable either both, EL, or scripting. Here is the solution.

You need to add, or change the configuration in your web.xml file. There are two ways configuration parameters which control scripting and EL.

<jsp-config>
<!-- Set to true to disable JSP scriptiing syntax -->
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<scripting-invalid>false</scripting-invalid>
</jsp-property-group>
<!-- Set to true to disable Expression Language (EL) syntax -->
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<el-ignored>false</el-ignored>
</jsp-property-group>
</jsp-config>


The lines above control how the page is translated. They are both currently set to false.

Here is an example of a jsp page with both scripting and EL.


1 <%@page contentType="text/html"%>
2 <%@page pageEncoding="UTF-8"%>
3 <%@ page import="java.util.Date" %>
4
5 <jsp:useBean id="now" scope="request" class="java.util.Date"/>
6
7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
8 "http://www.w3.org/TR/html4/loose.dtd">
9 <html>
10 <head>
11 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
12 <title>JSP Configuration</title>
13 </head>
14 <body>
15 <h1>JSP Configuration</h1>
16 <p>
17 Browser MIME types: ${header.accept}
18 </p>
19 <p>
20 Browser Compression: ${header["accept-encoding"]}
21 </p>
22 <p>
23 The context-path initParam is: ${initParam.customerServiceEmail}
24 </p>
25
26 <p>
27 HTTP Request Method: ${pageContext.request.method}<br>
28 HTTP Response Type: ${pageContext.response.contentType}<br>
29 HTTP Session ID: ${pageContext.session.id}<br>
30 HTTP Context Path: ${pageContext.servletContext.contextPath}
31 </p>
32 <p>
33 Date (script): <%= new Date()%><br>
34 Date(EL): ${now}
35 </p>
36 </body>
37 </html>
38


The resulting output looks like this:



After setting <scripting-invalid>true</scripting-invalid> The page will
throw an exception is there are any JSP scripting elements on the page.



I went back and set the value back to false and set the <el-ignored>false</el-ignored>
This causes the container to treat the EL syntax as literal text.
The result is what you would expect. The only values diaplayed are JSP script.



The question is why would you want to go through the effort... If you were doing work on JSP pages
prior to JSP 2.0, you may have used some syntax similar to EL which you may not want
to have translated.

Turning off scripting forces the developer to use Java Standard Tag Libraries (JSTL)
and Expression Language (EL). This ensures a cleaner separation of code from
presentation in the MVC paradigm.

Popular Posts