Apress, Java, a Bunch of New Books and What's to Come
by Jessica Sant
How it all began, and how it doubled over night...Apress started
in 1998 during a phone call between Dan Appleman, author of several
top-selling Visual Basic books, and Gary Cornell, co-author of the Core
Java books. They were talking about authoring books when one of them
suggested "we should just publish our own books". They did just that and
Apress, the "Author's Press", was born.
In the spring of 2003,
Wrox Press declared bankruptcy. John Wiley & Sons purchased the Wrox
Press brand, Wrox.com and many of its best-selling titles. At the same
time, Apress more than doubled the number of books they owned by
purchasing the remaining 91% of the Wrox titles.
Sorting through all those books...As Java Editor, it's Craig
Berry's job to develop the Java series of books at Apress. He came to the
company via Wrox Press. Integrating a catalog as large as the one
purchased from Wrox was quite a considerable project. Craig explained that
"with the exception of three or four titles, Apress acquired the rights to
Wrox's entire Java catalog, so what I've been doing recently is finishing
off some of the works-in-progress we had at Wrox. I've also been
evaluating which of the Wrox catalog should be reprinted under an Apress
cover, which should be revised or updated, and which we should just allow
to die gracefully."
Craig said he didn't find there was much
overlap between Apress' preexisting Java books and those that had been
acquired from Wrox. "The Wrox titles had far more significant subject
matter coverage, whereas Apress' titles tended to be more esoteric. There
are a couple of titles I need to work around but for the most part I've
got a reasonably clean slate to create a new strategy.
"That new
strategy includes establishing a strong foundation of titles that gives
Apress good, solid coverage of the core areas of Java and then to branch
out from there, while still making sure that we don't miss out on any
obvious growth areas... The Java book market is quite a tough one; there
are a couple of very big players in the form of O'Reilly and Pearson.
Plus, Java is quite a mature, stable market now; it's not really volatile
like .NET. What I'm looking to do is to carve out a distinctive niche for
Apress because so far I think many of their titles have been under most
people's radar. I want to take the concept of the 'Expert's voice'
(Apress' byline) and help Apress to become recognized as a prestige
publisher."
He then explained that the biggest problem with
publishing Java books based on a new specification is "trying to figure
out when a spec will actually be finalized... Sun is rather vague on
release dates... Normally you can't really start writing based on a new
spec until it's available for public review and is reasonably stable. So
it really comes down to trying to find people who are on the experimental
edge and are interested in playing with the latest technologies and then
pushing them to try and get something written reasonably quickly."
What makes Apress, Apress?That strategy and Apress' high standard
of selecting expert authors is one of the things that makes them unique.
Hollie Fischer, Product Manager at Apress explained, "We publish books
for IT professionals, programmers, and developers that have been
written by expert IT professionals, programmers, and developers.
The Apress editors who are acquiring Apress books are in fact programmers
themselves... so, they know what readers want and need. We ask readers
what they want and need and, we listen. Apress is a really personable
company, too - if a reader or author wants to stop by our office to see
what we're all about, or if they just want to have a chat with us at a
tradeshow or user group meeting, no problem. Our books are of very high
quality - you won't find a lot of fluff in an Apress book."
Wanna write for Apress?Craig talked about how best to go about
getting noticed: "Well, to a certain extent I'm always keeping one eye
open on the lookout for potential authors when I'm trawling the web, etc.,
but if someone wants to take a more active role in becoming an author,
then their best bet is to approach us with an idea for a book. If you were
to just say 'Hello, I'm interested in writing' that's not really going to
get you noticed because we obviously already have lots of writers in our
'family'. What I'd be looking for is an original idea that has a certain
degree of market potential."
Coming soon to an Internet near you...Hollie gave me a little
preview of what's to come at Apress, so I thought it only right to pass it
along.
The new Apress
Forums were opened on August 1st as a place where readers can talk
shop and maybe even talk to some of their favorite authors (sounds a bit
like they're trying to copy the JavaRanch's Bunkhouse
Porch... but we wish them the best of luck *wink*). They will be
having weekly contests and gift awards in the form of American Express
gift cards.
eBooks and ePublishing is a more and more popular
method for publishers to reduce the cost to the reader, or to enhance the
reader's experience with a nice searchable electronic copy to go along
with their printed book. "Sooner than later, no definite date yet, Apress
will be making books available for download. The program will be on a
subscription basis, which will include the email address of the subscriber
in the actual document, customized for the subscriber. That way, if Apress
comes across any illegal copies, we will be able to track the documents
back to the original user and the subscriber will lose their privileges.
Apress is really open to allowing people to post sample chapters of our
books or using our books in tutorials and presentations, so we don't see a
lot of problems with copyright infringements.... Currently, Apress books
are available for readers with disabilities and any Apress book that is
six months old or more is available to Books 24x7 members." If you'd like
more information about the program you can contact Apress through their
website, Apress.com.
And Finally...Hollie and Craig are interested in feedback and
comments about their titles, feel free to contact them at hollie_fischer@apress.com or
craig_berry@apress.com.
|
Return to Top
|
An Interview with Jacquie Barker, author of Beginning Java Objects
by Jessica Sant
JavaRanch: Jacquie, let's start with the
big question first: What was it like to have your publisher, Wrox, drop
out from under you?
Jacquie Barker: Very disturbing, and
the worst of it was that I found out indirectly. Wrox hadn't initially
notified any of their established authors about the bankruptcy; at first,
they only sent email out to those authors with new books under development
at the time.
JavaRanch: Wow, that must have been very
unnerving.
Jacquie Barker: Yes it was. As a matter of fact,
the way that I found out was by receiving an email from none other than
Gary Cornell, the President and founder of Apress; his email basically
said "In light of the demise of Wrox, I wanted to let you know we would be
honored to have you write for us." I said "DEMISE of WROX?" and then
hurriedly sent emails to a couple of other Wrox authors/friends; one knew
about the bankruptcy, one did not.
My immediate concern, of
course, was what the fate of my book was going to be - at that point in
time, Beginning Java Objects had become really well established. It
was typically in the #1 or #2 slot on Amazon's "beginning Java titles"
list, and I was worried that I'd lose ground if another publisher didn't
pick it up quickly enough.
The problem is that when an author
signs a publishing agreement, he/she sells one's soul to that publisher,
and so I had no control in the fate of my book; I had to sit and wait
(along with hundreds of other Wrox authors) to learn of my fate.
JavaRanch: Speaking of your book, how does the Apress
version of Beginning Java Objects differ from the one published by
Wrox?
Jacquie Barker: Actually, it doesn't, and I am glad
you asked, because I want to make sure that folks understand the
situation. John Wiley and Sons purchased the rights to reprint the top 30
selling books by Wrox out of 400+ titles; mine was #35 on Wrox's list, so
Wiley didn't acquire it. As a result of Wiley's purchase of the Wrox
brand, none of the other Wrox titles could continue to be marketed with
their familiar red covers; so, in effect, my book was technically out of
print when Wrox closed their doors! But, it was still in great demand, and
so it was important to get it reprinted ASAP, which I am delighted to say
was a priority on the part of Apress. However, in order for Apress to
reprint my book "as is", they still had to (a) change the cover and (b)
assign it a new ISBN, thus technically making it a new book in, for
example, Amazon.com's eyes.
We've tried hard to get the word out
that it is NOT a new edition, but rather a reprint ... but, I am sure that
there is still some confusion on that subject, because a few of the old
red cover Wrox copies are still floating around in bookstores, etc.
Gary Cornell and I decided that we didn't need to immediately
worry about a new second edition of my book. I wrote my book to be
"timeless" -- it is based on basic object/Java language principles that
are language version independent -- and so we felt it more important to
get the existing book back out on the streets "as is", and to worry about
revisions/potential sequels at a later date. If something isn't broken,
there's no need to fix it!
JavaRanch: So... are there any
new books in the works?
Jacquie Barker: Yes! I am working
on a lighthearted career guide for "techies" at the moment, which I am
going to attempt to self-publish this Fall or Winter. I'm also talking
seriously with Apress about a) a second edition to Beginning Java
Objects (BJO), which will incorporate some of the more significant
features of Java 1.5 (but which will still remain "language version
neutral") and/or b) a C# version of my first book (BC#O). A third
possibility is a sequel to BJO, which will address deploying Java-based
web apps using selected J2EE component technologies (servlets/JSPs in
particular). If readers are interested in following my progress on these
various projects, I encourage them to visit my website, objectstart.com. But, my first priority
is the techie career guide.
JavaRanch: How do you find the
world of Apress vs. the old Wrox Press?
Jacquie Barker:
Apress has been far more organized/responsive to me than Wrox was for most
of the time that I worked with them. (The individual people at Wrox were
great, but somehow the corporate "glue" just wasn't there to make things
flow smoothly.) I am impressed with the professionalism of everyone that
I've dealt with at Apress. I wasn't very familiar with Apress before they
acquired my title, because their initial focus (as a relatively new
publisher) was on C# and Microsoft technologies overall, and of course
I've been dedicated to the Java/open source arena for many years. But,
Apress (which stands for "the Author's Press"), with the acquisition of a
wide variety of formerly Wrox titles, is definitely expanding their
vision.
It's also impressive that the founder of Apress, Gary
Cornell, is a noted author himself! I first became acquainted with him
when he co-authored several of Prentice Hall/Sun Microsystems' Core
Java titles.
So, I have high hopes that Apress will do great
things for my book!
JavaRanch: Ahhh that's where I
recognize that name -- I see it on my desk every day
Jacquie
Barker: Yes! And, the funny thing is that when Gary first contacted me
about writing for Apress, I didn't make the connection either; and, he is
so modest, that it didn't come out until our second or third phone chat
(and even then, it was only mentioned indirectly). He said something about
having been a Java author, and I glanced up at my bookshelf and said, "You
are THE Gary Cornell?" It was quite a fun discovery!
JavaRanch: I think I'm about out of questions, is there
anything else you'd like to add?
Jacquie Barker: Hmmm ...
let's see ... I'm passionate about the fact that people who want to do
justice to an object oriented programming language must learn about
objects first. Most programmers dive right into Java from a non-OOP
background, thinking that learning yet another language cannot be that
tough; they focus on Java language syntax, but miss the boat on its object
oriented "bone structure".
Now that J2EE is mainstream, there are
many legacy programmers who (a) missed the object technology wave in the
early 90's, (b) missed the Java wave in the mid 90's, and (c) are now
trying to play "catch up" in a BIG way! I hope that my book will continue
to be a launching point for folks trying to get from (a) => (b) =>
(c).
I welcome reader inquiries, and encourage folks to contact me
via email at jjbarker@objectstart.com (or
via my website) if I can be of help to them in any way in their "Java
journey"!
Lastly, if any instructors are interested in potentially
adopting my book as a textbook, I have lots of supporting materials --
PowerPoint presentations, exam questions, and homework assignments -- that
I am happy to share.
JavaRanch: Excellent, thanks for
taking the time to chat with me.
Jacquie Barker: Jessica,
thanks to you (and JavaRanch) for giving me the opportunity!
|
Return to Top
|
Touring the Commons - part 2
by Jason Menard (jason@javaranch.com)
This is the second in a three part series discussing elements of the Jakarta Commons project. The first part discussed the Commons BeanUtils package, the second part discusses the Commons Digester package, and the final part will demonstrate using these packages together to build a framework for dynamically generating data transfer objects.
Introduction
Last month we took a look at using the Jakarta Commons BeanUtils package to dynamically create and manipulate JavaBeans. This month we take a look at another very useful component of the Commons project - Digester. Digester is a component that facilitates the easy mapping of XML documents to Java objects.
The reasons why you might want to map an XML document to a set of Java objects are nearly limitless. A primary reason you might do this is to extract configuration information stored in an XML file to use in your own classes. Maybe you need this capability simply because "that's where the data is". XML is a popular format for storing a large variety of information, and having the ability to easily map this data to your own set of application specific objects is nothing to sneeze at. Regardless what your motivation is, it's very likely that Digester is just what you've been looking for.
The Problem: A Collection of Book Reviews
We have an XML file containing the book reviews here at JavaRanch, along with
information about the books being reviewed. We want to write a Swing application
to add new reviews and edit existing reviews. It is obvious to us that we need
a way to import the XML data and have it mapped to a set of Java classes which
we will use within our application. We decide to use Digester to handle the
object mapping for us.
First, let's take a look at a snippet of our XML. See reviews.xml for the entire file.
<books>
<book>
<title>Design Patterns</title>
<category>Design Patterns, UML, and Refactoring</category>
<edition number="1">
<author>
<lastName>Gamma</lastName>
<firstName>Erich</firstName>
</author>
<author>
<lastName>Helm</lastName>
<firstName>Richard</firstName>
</author>
<author>
<lastName>Johnson</lastName>
<firstName>Ralph</firstName>
</author>
<author>
<lastName>Vlissides</lastName>
<firstName>John</firstName>
</author>
<isbn>0201633612</isbn>
<review>
<rating>8</rating>
<content>The most popular computer science book of all time...</content>
<reviewer>Paul Wheaton</reviewer>
<ranchCategory>trailboss</ranchCategory>
<reviewDate>
<month>1</month>
<year>2000</year>
</reviewDate>
</review>
</edition>
</book>
</books> |
This looks straightforward enough. We have a collection of books, each of which has a title, a category for the type of book it is, and one or more editions. We see that each edition has one or more authors (each having first and last names), an ISBN number, and one or more reviews. Taking a look at the reviews, we can see that each review is given a rating, has the month and year the review was done, the text of the review, and the name and JavaRanch category of the person who did the review. Based on this information we come up with Books.java, Book.java, Edition.java, Author.java, and Review.java. Since the review month and review year are one-to-one mappings with Review, we made them properties of Review since there was no need for a separate class just to store those two pieces of information.
Let's take a look at our Book class.
public class Book {
private String title;
private ArrayList editions = new ArrayList();
public Book() {
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public List getEditions() {
return editions;
}
public void addEdition(Edition edition) {
editions.add(edition);
}
} |
The only thing to really note here is that there is an addEdition()
method for adding an Edition object to an instance of Book.
This is done throughout the classes we wrote where a class is maintaining a
collection of objects, just like Book has a collection of Editions.
We will need to have methods like this when we start working with Digester.
Now that we have some XML and some classes to map the XML to, let's take a look at using Digester.
Inside Digester
Digester uses three main concepts that must be understood in order to effectively make use of it: the object stack, element matching patterns, and processing rules.
The Object Stack
The Digester class maintains an internal stack of objects. Typically objects are pushed onto the stack or popped off of the stack according to processing rules. The Digester class contains the typical operations for manipulating the stack: clear(), peek(), push(), and pop().
- clear() - removes all objects from the stack
- peek() - gets a reference to the top object on the stack, but doesn't remove it
- push() - places an object on top of the stack
- pop() - removes the top object from the stack
Just to make sure we are all clear on how a stack works, let's walk through a quick example. I have a stack 'S' which is currently empty. I will represent it like so:
===
S
Next let's push an Object 'A' onto the stack using the push() method.
Our stack now looks like the following:
A
===
S
After pushing two more objects on the stack, 'B' and 'C' in that order, the stack is in the following state:
C
B
A
===
S
A call to peek() would return a reference to 'C', but the stack would remain in its current state. If we were to now pop() the stack, we would get a reference to 'C' and our stack would be left in the following state:
B
A
===
S
Calling clear() would naturally remove all objects from the stack:
===
S
Element Matching Patterns
Digester uses element matching patterns to describe the location of elements of your XML document relative to each other. You can think of it as similar to a directory hierarchy. Looking back at our XML document we can see that the first element in the document is the <books> element. The element matching pattern for the <books> element is simply:
books
Getting back to the analogy of our XML document as a directory tree, if we can imagine our XML document as being the "directory" that we are currently in, then referencing the <books> element with the element matching pattern that is simply "books" seems to make sense.
Well how about the <book> element? Our XML document lays it out like this:
<books>
<book>
The element matching pattern for this structure is:
books/book
Once again, if we could imagine our XML document as a directory tree structure, this makes perfect sense. Let's try one more. What would the element matching pattern be for the author's last name? If you said...
books/book/edition/author/lastName
...then you are absolutely correct. Nothing too fancy here. It's a fairly straightforward concept.
Processing Rules
Processing rules are used by Digester to determine what actions need to be
taken when the parser encounters a given element matching pattern. Processing
rules typically are used to manipulate the stack (for example, popping an object
off of the stack), create objects, and manipulate objects on the stack. Digester's
processing rules are classes that implement the Rule interface.
Processing rules are fired when the parser matches the rule's element matching pattern. In other words, when the parser encounters the specified element in the XML document, the rule is triggered. Just like an XML element has a beginning tag, body content, and a closing tag, a Rule has a begin() method, a body() method, and an end() method. The begin() method of the Rule is called when the beginning of the XML element is encountered, the body() method is called when the body of the XML element is encountered, and the end() method is called when the end of the XML element is encountered. When parsing is complete, the finish() method of the rule is called, in order to take care of any resources which might need to be cleaned up.
While you may write your own rules, and in fact may often need to do so, the Digester package comes with several common Rule implementations. The Digester class has methods to register these processing rules. We'll take a look at a few of the more common processing rules and the Digester methods which register them.
ObjectCreateRule - This rule is used to create an instance
of an object. The object is created by callings its no-argument constructor
and pushed onto the stack when the begin() method is called. When the
end() method is called, the object is popped off of the stack. To register
an ObjectCreateRule that creates a new Book object whenever
the <book> element is encountered, we make a call to Digester's
addObjectCreate() method:
Digester digester = new Digester();
digester.addObjectCreate("books/book", Book.class); |
We can see that addObjectCreate() take an element matching pattern and the class of the Java object to be created. In fact, every Digester method we'll look at that creates a Rule will take an element matching pattern as its first parameter.
BeanPropertySetRule - Sets a property of the bean that is the top object in the stack. By default, the property of the bean set is the same as the name of the current XML element being examined. The value set is the body content of the XML element.
digester.addBeanPropertySetter("books/book/title"); |
In the above example, setTitle() will be called on the bean on top
of the object stack, setting that property with the body content of the <title>
tag.
SetPropertiesRule - Sets a property of the bean that
is the top object in the stack to the value of an XML attribute.
digester.addSetProperties("books/book/edition", "number", "number"); |
This example registers a SetPropertiesRule that calls the method setNumber()(the
third argument of addSetProperties()) of the object on top of the stack,
setting the value to the number attribute (the second argument of addSetProperties())
of the <edition> element.
SetPropertyRule - Sets a property of the bean on
top of the stack to a value of an XML attribute. The property of the bean to
be set is specified by another XML attribute.
For example, given the XML element <set-property property="name"
value="jason"/>...
digester.addSetProperty("some/pattern/set-property", "property", "value"); |
...would call the setName() method of the object on top of the stack,
passing the value "jason" as the argument.
CallMethodRule and CallParamRule
- These two rules used in conjunction with each other allow the execution of
arbitrary methods of the top bean on the stack. A CallMethodRule specifies
the name of the method to call, the number of arguments that the method expects,
and of course when it should be called as indicated by the element matching
pattern. The method is called when the CallMethodRule's end()
method executes. A CallParamRule indicates the values to be passed
to method specified by the CallMethodRule. Values for the CallParamRule
may be taken from either the character data of an XML element, or from an attribute
of an XML element.
digester.addCallMethod("books/book/edition/isbn", "setIsbn", 1);
digester.addCallParam("books/book/edition/isbn", 0); |
The first line in the above code specifies that the setIsbn() method
should be called on the object on top of the stack, and that it takes one argument.
The second line states that the character data of the <isbn>
element should be passed as the first parameter (parameters are indexed zero-relative,
so the first parameter has an index of 0) to the setIsbn() method.
If we wanted to pass a parameter value from an XML element's attribute instead
of its character data, our addCallParam() method might look something
like this:
digester.addCallParam("books/book/edition", 0, "number"); |
In this case, the value passed will be taken from the number attribute
of the <edition> element.
Looking back at the addCallMethod() method of Digester, one
might think that to call a method that takes no attributes then we would use
"0" as the value of the method's third argument. This is not the case
however.
digester.addCallMethod("books/book/edition/isbn", "setIsbn", 0);
|
This example is a shorthand for the previous example where we used both addCallMethod()
and addCallParam(). What this says is that we will call setIsbn() and
pass the character data of the <isbn> element as the value of
the argument to the method.
If these examples look like they accomplish essentially the same thing as a
similar call to addBeanPropertySetter(), that is absolutely correct!
The combination of addCallMethod() and addCallParam()do give
us the flexibility to invoke arbitrary method calls however, which addBeanPropertySetter()
does not provide for.
But what if we want to invoke a method that takes no arguments? In that case
we can use the signature of addCallMethod() which takes only two methods
- the element matching pattern and the name of the method, as in the following
example:
digester.addCallMethod("some/pattern", "someMethod");
|
SetNextRule - This rule sets a property of the object
that is next from the top of the stack, passing the object that is at the top
of the stack as the value of the property being set. When the end()
method is called, the object on top of the stack is popped and set to a property
of the newly exposed top object. Typically a SetNextRule will be used
to add one or more child objects to a parent object.
digester.addSetNext("books/book/edition/review", "addReview"); |
The example code shown here will call the addReview() method of the
object that is next from the top of the stack, passing the object that is at
the top of the stack as an argument. It is important to keep in mind that the
stack is popped by this rule.
Using Digester
Once you understand the concepts outlined in the preceding sections, actually
using Digester is really rather easy. All we need to do is follow a
few simple steps and we are on our way.
The first thing we must do is create a new instance of Digester.
Digester digester = new Digester(); |
Now that we have our instance of Digester, we need to set any configuration
properties that we might need. Configuration operations include whether or not
the XML document should be validated against a DTD, the class loader to use
for loading objects created by an ObjectCreateRule, and whether or
not namespace aware parsing is enabled. There are a host of other configuration
options, and I would urge you to read the API documents for further information.
digester.setValidating(false); |
Next we must register our processing rules.
digester.addObjectCreate("books", Books.class);
digester.addObjectCreate("books/book", Book.class);
digester.addBeanPropertySetter("books/book/title");
digester.addObjectCreate("books/book/edition", Edition.class);
digester.addSetProperties("books/book/edition", "number", "number");
digester.addBeanPropertySetter("books/book/edition/isbn");
digester.addObjectCreate("books/book/edition/author", Author.class);
digester.addBeanPropertySetter("books/book/edition/author/lastName");
digester.addBeanPropertySetter("books/book/edition/author/firstName");
digester.addSetNext("books/book/edition/author", "addAuthor");
digester.addObjectCreate("books/book/edition/review", Review.class);
digester.addBeanPropertySetter("books/book/edition/review/rating");
digester.addBeanPropertySetter("books/book/edition/review/content");
digester.addBeanPropertySetter("books/book/edition/review/reviewer");
digester.addBeanPropertySetter("books/book/edition/review/reviewDate/month");
digester.addBeanPropertySetter("books/book/edition/review/reviewDate/year");
digester.addSetNext("books/book/edition/review", "addReview");
digester.addSetNext("books/book/edition", "addEdition");
digester.addSetNext("books/book", "addBook");
|
Once we register our processing rules we are almost home. In order to proceed
we must identify our input XML document. In this example we are specifying a
File, but the API specifies several other suitable input sources.
File input = new File(REVIEWS_XML);
|
If necessary, push any objects onto the stack that we need to. Finally all
we need to do is call parse(), which returns the root object of the
stack.
Books books = (Books)digester.parse(input);
|
That's all there is to it!. See ReviewDigester.java
for the complete source code.
Conclusion
In this article we've seen just how easy it can be to create a mapping between
an XML document and a hierarchy of Java objects. We focused on using the Rule
implementations that Digester provides for us. Next month we will learn how
to write our own Rule implementations, as well as what to do when you want to
create an object using a constructor that takes arguments.
Digester has a few other tricks up its sleeve that we won't have time to look
at. These include specifying our processing rules in XML and pluggable rules
processing, among others. Take a look at the API documentation for more information.
Resources
Please feel free to email me with
any questions or comments concerning this article.
Return to Top
|
The Coffee House
by Solveig Haugland
This Month's Story: How to Convince Yourself or Your Grumpy Sysadmin to
Adopt OpenOffice.org
"You know," said Lacey, "I know in my heart it's wrong to be using
Microsoft Office here in the coffee shop. But I'm just scared to death
of what would happen if we switched over to OpenOffice.org. What about
our beautifully formatted menus? Would OpenOffice.org screw up the formatting?
What about them budgets we send over to the bank and all our forms?"
"I'm a little afeared myself," admitted Brenda. "Guess this is one of
them things they make movies about, ordinary people facing extraordinary
challenges and courage and all that stuff."
Just then, like it happens in the movies, the swinging doors of the
coffee house flung open and a tall, dark, handsome, and very very tired
cowboy walked on into the coffee house and kinda slumped over the bar.
"Espresso...triple shot...please..." he gasped.
"Brenda, get this man a shot, pronto!" The women swung into action and
before you could say JavaBeans, they had him perked up and feelin' good
on espresso, with a cafe au lait chaser.
"Thank you, ladies! I can't say as I've ever had a finer Egyptian roast,
'cept maybe in Kansas City a few years ago in the height of the coffee
boom."
Brenda blushed and could hardly respond, since she was the one who roasted
the beans herself.
"And you know, I thought I overheard you gals talkin' about making the
big courageous switch to OpenOffice.org. Did I hear right?"
Brenda and Lacey nodded. "You know somethin' about it, mister?"
"Call me Sam. Why yes I do, ladies. I ride my horse Ned throughout the
West, stoppin' wherever people need a helpin' hand to make the switch from
Microsoft Office to OpenOffice.org. I show folks how to do it smart, and
that it ain't as hard as the Microsoft Folks make out."
"That would be just dandy, mister! I mean Sam." And before they could
say 'Richard Stallman', the stranger had a couple of laptops set up with
a projector, and had a clipboard out on his knee.
"All righty. Now there's usually about five things folks are afeared
of when they want to switch from Microsoft Office to OpenOffice.org. Here's
one of'em."
1. General fear of the unknown, fear of going to something that?s
open source and potentially flaky or unsupported.
"Now I don't know about you ladies, but I ain't exactly had a fabulous
time with the support you gotta pay for. You gals need to go on the
users@openoffice.org list (just look on the www.openoffice.org site) and
talk to other folks who?ve switched. You mighta heard of Cassens Transport
in Illinois, Ernie Ball Guit-tar in Washington, and Jefferson County government
in Golden, Colorado, just down west apiece. Once you've talked to other
folks who've done it, succeeded, and liked it, there'll be less general
fear of the unknown."
"That's mighty true," Brenda admitted. "I sure would like to talk to
other folks; that'd make me feel better for sure."
Sam nodded. "The folks on the users@openoffice.org list, by the way,
are not only a font of information but they are as prompt and courteous
as a lady could want."
"So let's take another look at something else y'all will have to do."
2. Converting existing documents.
"This can be a big ol' job, but it might be not so bad. All depends
on what's in your documents. You could probably get some folks who come
in here regular to help convert a few test documents to just see what all
happens when you switch over. You got some guys who just sit here at the
bar all day long who would help you switch over your spreadsheets and invoices
and stuff to OpenOffice.org to see what would happen?"
"We sure do! Lefty and Sid, and Zeke too I think, have been itching
to take their ranches Open Source. They'd sure help us out, that's a great
idea."
"Dandy, that's dandy," replied Sam. "All righty. Here's the third thing."
3. Training
"This isn?t trivial-like," Sam began, "but it?s certainly manageable.
If you take a look at the programs, you'll see they look a heck of a lot
alike. You drive on into Dodge for a couple days, get yourself a couple
days of training, get a couple books to take back, and you'll be surprised
how much you can do. . Do the training early and often and in manageable
chunks, Oh, and OpenOffice.org is just a bit weird with some things, you'll
take a long time trying to find out how to do them. so make sure you get
them books. I use them myself, this Norwegian feller is the one who wrote
my "OpenOffice.org Resource Kit" and I like it real fine. Big index. Oh,
and the whole OpenOffice.org CD is tucked real neat in the back, so you
don't gotta download it. That's kinda nice."
"Well, OK," said Lacey, "that sounds like it could work. It doesn't
sound like it would be all that expensive to head into Dodge. And I shore
think it would be tax deductible."
4. Ya gotta commit.
"Here's the thing. If you gals keep Microsoft Office on your computers,
you ain't never going to learn OpenOffice.org proper. You gotta take off
the Awfice after a month or two and just use OpenOffice.org. Just like
when you go to France for a trip -- you ain't never learnin' no French
if you hang out with your American buddies."
5. It's just too much work, ain't it?
"It's finally just the effort of doing it. It seems intimidating, but
think about it. Think about when you've done some test documents, and you've
got some learnin' under your belt, and you've talked to other folks. It'll
seem real easy at that point, once you've got your mental obstacles overcome-
like."
"And I just wanna mention a couple dandy things. OpenOffice.org file
sizes are tiny. If you're concerned about disk space that files take up
on servers or going through email, OpenOffice.org will be a dandy change.
And if you ladies have a lot of licenses for Canvas, Illustrator, or Visio,
you might be able to get rid of those too and just use OpenOffice.org Draw.
It's got them connector lines from Visio, the object and text manipulation
things you can do in Illustrator, and the general types of things you can
do in Canvas. Plus it's the easiest thing to use in the whole OpenOffice.org
program, I think."
Brenda and Lacey sighed happily and looked at each other. Brenda exclaimed
"Dang, I can hardly wait to put that OpenOffice.org program on our computer!
We can sure save a lot of money, not sendin' in to Uncle Bill for the upgrades
and support and stuff. And I kinda like the idea of a nice drawing program
tucked into it too. I could sure do a lot with that Draw thing."
"We should ask Sam if he could show us a couple things before he leaves.
Sam--?? What in tarnation? He was here a second ago!"
But the swinging doors of the coffee house told the story clearly --
Sam had cleared out. Onto another town, to free people from their fears
and from Uncle Bill.
Riding, always riding, into the west. Every day, one mile closer to
Redmond.
Solveig Haugland is an independent writer and trainer based in Colorado.
You can contact her through her myriad Web sites, www.getopenoffice.org,
www.datingdesignpatterns.com,
www.cafepress.com/datingpatterns,
and www.cafepress.com/techspeak.
If you or your organization are leaning toward learning OpenOffice.org,
Solveig can provide you with training, learning materials, and consulting.
Contact her through solveig@getopenoffice.org.
Return to Top
|
Book Review of the Month
A look at two popular books on Eclipse
Michael Yuan - Bartender,
July 2002
|
Eclipse has generated a lot of buzz among developers these days. It seems to get everything right:
- It is small, fast and cross-platform;
- It is code-centric with support for as-you-type error highlighting, auto code completion, refactoring and common stub generation;
- It is extensible with many plugins and features an open architecture for plugin development;
- It supports agile methodologies and collaborative development;
- Best of all, it is Open Source.
Although it is easy to get started, few developers can appreciate the full power of Eclipse as both an IDE and a complete development platform. Good guide books on this subject can empower users to explore more features in the platform and maybe even contribute back to the Eclipse community as a plugin developer someday. Two Eclipse books caught my eye as the best sellers on Amazon:
From the surface, the Addison-Wesley book seems to be a better bargain: It has 854 pages with a CDROM, sells for $49.99 and is written by members of the IBM Eclipse Jumpstart team. Addison-Wesley is actually publishing an entire book series on Eclipse. A draft of the second book in the series "Eclipse Modeling Framework" is in my hands as I write this review. On the other hand, the Manning book is "merely" 383 pages and costs a rather steep $44.95. However, after reading both books in the past week, I come to the conclusion that the two books serve very different purposes. I would like to have them both on my desk. Now, let’s start from the Manning book.
|
Eclipse In Action
David Gallardo, Ed Burnette, Robert McGovern |
|
Manning Publications Company
Published: 15 May, 2003 | |
The "Eclipse in Action" book covers much more than the Eclipse IDE or the Eclipse Framework. It should be accurately named "How to use Eclipse to develop agile software". Using a single project as the example throughout the book, the authors cover the Eclipse core IDE (e.g. editor, project manager and debugger) and important add-on tools such as ant, log4j, junit and cvs. The book also covers advanced topics such as how to develop and use Eclipse plug-ins.
After spending a little time studying the example project itself, the reader forms a concrete idea on how the development should proceed. Given this context, it is easy to understand how the directories are laid out; how to construct ant build files; how to auto generate test cases or JavaBean wrappers; and how to manage the CVS. Most importantly, the authors discussed adequately why and how to apply test-driven development methodologies in the application. They even refactored example application multiple times to demonstrate Eclipse’s superior code refactoring support. Overall, it is an excellent guide book on how to use Eclipse in your projects. After reading it, you can learn a lot about Eclipse as well as agile methodologies.
However, due to the limitations of the single example, the book cannot cover all the features in Eclipse. This book is a very smooth read from cover to cover. But if you are looking for description of a particular feature or menu item, you might be disappointed since the example application just does not go that far. The "plug in development" chapters of this book also only scratch the surface.
| |
|
More info at Amazon.com ||
More info at Amazon.co.uk
| |
Java Developer's Guide To Eclipse
Sherry Shavor, Jim D'Anjou, Dan Kehn, Scott Fairbrother, John Kellerman, Pat McCarthy |
|
Addison Wesley
Published: 19 May, 2003 | |
"The Java developer's Guide to Eclipse" book is almost exactly the opposite to "Eclipse in Action". It focuses on the Eclipse tool and platform, not any particular sample application. That allows the authors to describe almost all the menu items and details of supported features. However, without context, those descriptions are hard to understand or remember. I think this book makes a great reference book or textbook if supplemented with classroom and lab teaching. In fact, since the authors develop teaching materials for living, the book includes 7 chapters of "Exercises". Those materials are very good for serious learners but may not be suitable for casual readers who just want to get started with Eclipse quickly.
The Addison-Wesley book really shines when it comes to Eclipse platform development materials. It presents basic and advanced tutorials on plugin development. It also describes how to build plugins into features that can be managed by the Eclipse update manager. A major characteristic of the Eclipse platform is its tight integration with the native platform. A chapter in the book is dedicated to COM interoperation on the Windows platform. Another chapter covers interoperating the native-based SWT toolkit with the standard Swing UI toolkit. If you are using Eclipse as a platform to develop your own tools, "Java Developer’s Guide to Eclipse" is a must-have book.
| |
|
More info at Amazon.com ||
More info at Amazon.co.uk
| |
Other books reviewed in
July :
Java Extreme Programming Cookbook by
Eric M. Burke and Brian M. Coyner | Design for Community, the art of connecting real people in virtual places by
Derek M. Powazek | Java Web Services Architecture by
James McGovern, Sameer Tyagi, Michael Stevens, Sunil Mathew | JDBC API Tutorial and Reference by
Maydene Fisher, Jon Ellis, Jonathan Bruce | Unit Testing in Java by
Johannes Link, Peter Froehlich | Java Web Services in a Nutshell by
Kim Topley | MIDP 2.0 Style Guide for the Java 2 Platform, Micro Edition by
Cynthia Bloch, Annette Wagner | The Art of Interactive Design by
Chris Crawford | Sams Teach Yourself Extreme Programming in 24 Hours by
Stewart Baird | Blogging - Genius Strategies for Instant Web Content by
Biz Stone | Building Embedded Linux Systems by
Karim Yaghmour | Java Development on PDAs: Building Applications for Pocket PC and Palm Devices by
Daryl Wilding, McBride | Google Pocket Guide by
Tara Calishain, Rael Dornfest , D. J. Adams | Web Services and Service-Oriented Architecture: The Savvy Manager's Guide by
Douglas K. Barry | Secure Coding by
Mark G. Graff, Kenneth R. van Wyk |
Return to Top
|
Build a servlet-based application that executes SQL statements against a database
by Joel Murach - (While he may not be a JavaRanch regular, yet, he did provide us with this article to be included in our Newsletter.)
This tutorial shows how to use a Java servlet, a JavaServer Page (JSP), and a static Java class to create an application that can be used to interactively execute any standard SQL statement against a database that's running on a server. You can use an application like this one to work with a database as you're developing an application. In this article, this application will be referred to as the SQL Gateway application.
If you're working with a database that's hosted by an Internet Service Provider (ISP), the ISP will usually include an HTML-based way to work with the database that's similar to this application. If not, you can upload this application to work with the database. Either way, this application shows how to use JDBC within a servlet to work with a database that's running on a server.
Prerequisites
This tutorial is an excerpt from chapter 11 of Murach's Java Servlets and JSP by Andrea Steelman and Joel Murach. It assumes that you have a basic understanding of the Java language, servlets, and JavaServer Pages. If you don't, you might be interested in Murach's Beginning Java 2 or Murach's Java Servlets and JSP.
This tutorial also assumes that an appropriate servlet/JSP container and database server are available on the server that you're using. The source code for this tutorial has been tested using Tomcat 4.0 and MySQL, but it should work with other servlet/JSP containers, and it should work for most database servers if you supply a valid driver and connection string for that database.
Source code
Before you begin this tutorial, you may want to download the source code for this application. That way, you can open the source code in your favorite text editor to see how it all fits together.
The user interface
Here's the user interface for the SQL Gateway application after it has executed an INSERT statement:
As you can see, the bottom of the page shows a message that indicates the number of rows that were affected by the statement. If the SQL statement is a SELECT statement that runs successfully, the result set will be displayed within an HTML table as shown here:
Of course, if the SQL statement doesn't execute successfully, the result will be a message that displays information about the exception that was thrown.
The code for the JSP
The code for the JSP starts with a scriptlet that contains Java code that retrieves two attributes from the session object:
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
<%
String sqlStatement =
(String) session.getAttribute("sqlStatement");
if (sqlStatement == null)
sqlStatement = "";
String message =
(String) session.getAttribute("message");
if (message == null)
message = "";
%>
The first attribute is the string that contains the SQL statement, and the second attribute is the string that contains the result message. If these attributes contain null values, they haven't been set yet so this code sets the sqlStatement and message variables to empty strings.
This JSP also contains an HTML form that contains a text area and a submit button:
<form action="../servlet/murach.sql.SQLGatewayServlet" method="post">
<b>SQL statement:</b><br>
<textarea name="sqlStatement" cols=60 rows=8>
<%= sqlStatement %>
<textarea><br>
<br>
<input type="submit" value="Execute">
<form>
Here, the text area allows the user to enter the SQL statement. This code creates a text area that's approximately 60 characters wide and 8 lines tall. Within this area, the sqlStatement variable is displayed, which is empty the first time this JSP is run. Then, when the user clicks the submit button, this JSP calls the SQLGatewayServlet that's described later in this article.
The table near the end of the JSP displays the message string that contains the result of the SQL statement:
<b>SQL result:</b><br>
<table cellpadding="5" border="1">
<%= message %>
<table>
Since this message contains the rows and columns for an HTML table, it's coded within the Table tags.
The code for the servlet
The SQLGatewayServlet, which is stored in the murach.sql package, starts by importing the java.sql package so it can use the JDBC classes. In addition, it declares a Connection object so the database connection can be used by all of the methods in the servlet:
package murach.sql;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.sql.*;
public class SQLGatewayServlet extends HttpServlet{
private Connection connection;
When the servlet engine places this servlet into service, the init method opens the connection to the database.
public void init() throws ServletException{
try{
Class.forName("org.gjt.mm.mysql.Driver");
String dbURL = "jdbc:mysql://localhost/murach";
String username = "root";
String password = "";
connection = DriverManager.getConnection(
dbURL, username, password);
}
catch(ClassNotFoundException e){
System.out.println("Database driver not found.");
}
catch(SQLException e){
System.out.println(
"Error opening the db connection: "
+ e.getMessage());
}
}
Usually, this occurs when the first user uses the application. That way, the database connection will be open and available for all subsequent users. Then, a new thread is spawned for each user that uses this servlet.
In this example, the servlet uses a driver for the MySQL database to open a connection to a database named "murach" that's running on the same server as the servlet. In addition, this servlet uses MySQL's default username of "root" and a blank password. However, you can modify this code to connect to just about any type of database running on any type of server. Either way, you'll need to make sure that an appropriate driver for the database is installed on the server. For more information about getting, installing, and configuring MySQL, you can go to www.mysql.com. In addition, there's an introduction to MySQL in chapter 10 of Murach's Java Servlets and JSP.
Before the servlet engine takes a servlet out of service, the destroy method closes the database connection and frees up the resources required by the connection.
public void destroy() {
try{
connection.close();
}
catch(SQLException e){
System.out.println(
"Error closing the db connection: "
+ e.getMessage());
}
}
When the JSP shown earlier calls the doPost method, this method calls the doGet method.
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException{
doGet(request, response);
}
Within the doGet method, the first statement gets the SQL statement that the user entered in the JSP, and the second statement declares the message variable.
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException{
String sqlStatement =
request.getParameter("sqlStatement");
String message = "";
Then, within the try block, the first statement uses the Connection object to create a Statement object, and the next two statements use the trim and substring methods of a String object to return the first six letters of the SQL statement that the user entered.
try{
Statement statement = connection.createStatement();
sqlStatement = sqlStatement.trim();
String sqlType = sqlStatement.substring(0, 6);
If the first six letters of the SQL statement are "select", the executeQuery method of the Statement object returns a ResultSet object. Then, this object is passed to the getHtmlRows method of the SQLUtil class that's shown later in this article, and it returns the result set formatted with the HTML tags for rows and columns.
if (sqlType.equalsIgnoreCase("select")){
ResultSet resultSet =
statement.executeQuery(sqlStatement);
message =
SQLUtil.getHtmlRows(resultSet);
}
However, if the first six letters of the SQL statement aren't "select", the executeUpdate method of the Statement object is called, which returns the number of rows that were affected. If the number of rows is 0, the SQL statement was a DDL statement like a DROP TABLE or CREATE TABLE statement. Otherwise, the SQL statement was an INSERT, UPDATE, or DELETE statement. Either way, the code sets the message variable to an appropriate message.
else{
int i = statement.executeUpdate(sqlStatement);
if (i == 0) // this is a DDL statement
message =
"<tr><td>" +
"The statement executed successfully." +
"</td></tr>";
else // this is a DML statement
message =
"<tr><td>" +
"The statement executed successfully.<br>" +
i + " row(s) affected." +
"</td></tr>";
}
statement.close();
}
If any of the statements within the try block throw an SQLException, the catch block sets the message variable to display information about the SQLException. If, for example, you enter an SQL statement that contains incorrect syntax, this message will help you troubleshoot your syntax problem.
catch(SQLException e){
message = "Error executing the SQL statement: <br>"
+ e.getMessage();
}
After the catch block, the next three statements get the session object and set the sqlStatement and message variables as attributes of that object.
HttpSession session = request.getSession();
session.setAttribute("message", message);
session.setAttribute("sqlStatement", sqlStatement);
Then, the last two statements return a RequestDispatcher object that forwards the request and response objects to the JSP shown earlier in this article.
RequestDispatcher dispatcher =
getServletContext().getRequestDispatcher(
"/sql/sql_gateway.jsp");
dispatcher.forward(request, response);
}
}
The code for the utility class
The code for the utility class named SQLUtil is shown below. This class contains a static method named getHtmlRows that is called by the servlet shown eariler. Like the SQLGatewayServlet, this class is stored in the murach.sql package.
package murach.sql;
import java.sql.*;
public class SQLUtil{
The getHtmlRows method accepts a ResultSet object and returns a String object that contains the HTML code for all of the column headings and rows in the result set. To build the information for that String object, the getHtmlRows declares a StringBuffer object named htmlRows and appends data to it as the method is executed. At the end of the method, the toString method is used to convert the StringBuffer object to the String object that is returned to the servlet.
public static synchronized String
getHtmlRows(ResultSet results) throws SQLException{
StringBuffer htmlRows = new StringBuffer();
ResultSetMetaData metaData = results.getMetaData();
int columnCount = metaData.getColumnCount();
htmlRows.append("<tr>");
for (int i = 1; i <= columnCount; i++)
htmlRows.append("<td><b>"
+ metaData.getColumnName(i) + "</td>");
htmlRows.append("</tr>");
while (results.next()){
htmlRows.append("<tr>");
for (int i = 1; i <= columnCount; i++)
htmlRows.append("<td>"
+ results.getString(i) + "</td>");
}
htmlRows.append("</tr>");
return htmlRows.toString();
}
}
To get the column headings that are returned, the getHtmlRows method uses the getMetaData method of the ResultSet object to create a ResultSetMetaData object. This type of object contains information about the result set including the number of columns and the names of the columns. To get that information, the getHtmlRows method uses the getHtmlRows and getColumnName methods of the ResultSetMetaData object.
To get the data from the result set, the getHtmlRows method uses a for loop within a while loop to get the data for each column in each row. Within these loops, the code uses the getString method of the result set to get the data for each field. That converts the data to a string no matter what data type the field is.
Please note that this method is declared with the synchronized keyword. This prevents two or more threads of a servlet from executing this method at the same time.
Thanks for reading. Please let me know if you found this tutorial helpful.
Joel Murach
joelmurach@yahoo.com
Related Downloads and Resources
Source Code - Free Download
http://www.murach.com/books/jsps/download_sql_gateway.htm
Feel free to download the code for this application. Then, you can install and configure it to work on your system.
Murach's Java Servlets and JSP
http://www.murach.com/books/jsps
If you want to learn more about servlet and JSP development using a MySQL database, JDBC, and connection pooling, this book uses a unique format to methodically present these topics. In addition, it presents other essential topics such as JavaBeans, custom JSP tags, JavaMail, SSL, security, and XML.
Murach's Beginning Java 2
http://www.murach.com/books/java
If you had any trouble understanding the Java syntax presented in this tutorial, this book provides great introduction to the Java language and also makes a great reference.
|
Return to Top
|
Programming Diversions Puzzle
by Jason Menard
Binary Reflected Gray Code
Background
A Gray code is an ordered set of binary numbers such that only one bit changes
from one element to the next. Any n-bit Gray code will have 2n elements.
{000, 001, 011, 010, 110, 111, 101, 100} and {000, 010, 011, 001, 101, 100,
110, 111} are both examples of 3-bit Gray codes. Note that only one bit changes
between each element and each set has 8 (23) elements.
A binary reflected Gray code (BRGC) is a particular encoding for non-negative
integers. To find a BRGC of n bits, take the BRGC of ( n - 1 ) bits, writing
it forward and then backward. Prefix the first half of the binary numbers with
0, and prefix the second half of the binary numbers with 1. The binary reflected
Gray code of 1 bit (integer values 0 and 1) is:
Integer BRGC
======= ====
0 0
1 1
To find the BRCG up through 2-bit integers (0, 1, 2, 3), write the BRCG of 1 bit
going forward (0, 1), then backwards (1, 0), to get (0, 1, 1, 0). Prefix the first
half of those numbers with 0 and the second half with 1, giving us:
Integer BRGC
======= ====
0 00
1 01
2 11
3 10
Looking at the above chart we came up with, we can see that the BRCG encoding for the integer 2 is 11.
Let's try it one more time, finding the BRCG for integers up to 3-bits (0, 1, 2, 3, 4, 5, 6, 7). First we write the 2 bit BRGC forward then backwards (00, 01, 11, 10, 10, 11, 01, 00). Finally we prefix the first half of those numbers with 0, and the second half with 1:
Integer BRGC
======= ====
0 000
1 001
2 011
3 010
4 110
5 111
6 101
7 100
Looking that the chart above tells us that the BRGC encoding for the integer
7 is 100.
The Challenge
Write a class BRGC containing three static methods. The first method displays
a table of long integers and their BRGC encoded values up to n-bits. It should
have the following signature:
public static void displayBRCG(long n)
Calling the method...
BRGC.displayBRGC(3);
...should produce something similar to the following output:
Integer BRGC
======= ====
0 000
1 001
2 011
3 010
4 110
5 111
6 101
7 100
The second method returns the BRGC encoded representation of an input non-negative
long integer. It should have the following signature:
public static String encode(long n)
Calling the method...
System.out.println(BRGC.encode(5));
...should display 111 on the console.
The third method returns the long integer representation of an input BRGC encoding.
It should have the following signature...
public static long decode(String brgc)
Calling the method...
System.out.println(BRGC.decode("111"));
...should display 5 on the console.
See the thread August
Newsletter Puzzle in the Programming
Diversions forum to post your answer and discuss this problem.
Return to Top
|
The Big Moose Saloon Question and Answer of the
Month
Mosey on in and pull up a stool. The
JavaRanch Big Moose Saloon is the place to get your Java questions answered.
Our bartenders keep the peace, and folks are pretty friendly anyways, so don't
be shy!
Over in The
Java In General (Beginner) Forum, JavaRanch's founder, Kathy
Sierra, did a heck of a job tellin' folks about that dot in the whole CLASSPATH
thing. Following is an excerpt from the
original forum thread.
Question: Why do we define . in the Java classpath environment setting?
Answer: Both the compiler and the JVM need to find any of the classes
that you're using in your code. If those classes are from the standard edition
API, then no problem -- both java and javac know where *those* are. But they
don't know about your *own* classes... the ones you're writing.
So... if you have a class that you just wrote, in a directory "foo", and the
class is NOT in a package, then you cd to directory "foo" and then compile from
that directory. That's the simplest way, to start out with. Including the dot
"." in your classpath is the way you tell they system to "when you're looking
for classes, be sure to look in the current directory (i.e. the one you cd to)."
Where to put that "."? You can add it permanently to your classpath
as an environment variable in DOS (via autoexec.bat, if you're still on Windows
98!), or a property in Windows NT (I think -- can't remember it's been so long
since I've seen NT). Or if you're on some flavor of Unix (including Mac OSX),
you can put it in one of several places, including your .cshrc file (or whatever
your initialization file is for your particular shell).
That's my preferred way... I never have to think about the current directory
that way. (And you can still override that if you do NOT want the current directory
to be included, which is sometimes necessary with RMI, but that's another story...)
Or, you can make sure that you have the "." by using the -classpath flag with
java and javac:
java -classpath . MyClass
Or, you can do it just for your current terminal session, by using whatever
it is you have to do for your particular shell. Something like:
%SET CLASSPATH = ${CLASSPATH}:.
(this says, "Take the current classpath, and add the current directory (.)
to it, and then make that the new classpath setting for as long as this terminal
is active.")
%java MyClass
(this is not necessarily *real* syntax)
If you use packages, it gets a little more complicated, although you'll still
need the "." on the classpath.
What has troubled some programmers is that they are using an IDE which makes
all kinds of settings for the classpath, and which may NOT include the current
directory. That's when it's probably easiest to just use the -classpath flag:
javac -classpath . MyClass.java
There is of course more to the story than this, but if you're just starting
out, this should work fine.
Return to Top
|
Movin' them
doggies on the Cattle
Drive
It's where you come to learn Java, and just like the cattle drivers of the
old west, you're expected to pull your weight along the way.
The Cattle Drive forum is where the drivers
get together to complain, uh rather, discuss their assignments and encourage
each other. Thanks to the enthusiastic initiative of Johannes de Jong, you can keep
track of your progress on the drive with the Assignment Log. If you're tough enough
to get through the nitpicking, you'll start collecting moose heads at
the Cattle Drive Hall of Fame.
Fresh riders on the Drive...
Got us three new ranchers this month signed up for that wild bronco ride
known 'round here as the Cattle Drive. Tip your ten-gallon to Marie
Mazerolle, Craig Thomas, and Greg Neef -- our latest
pardners on the trail.
Another moose on the wall for...
Yep, that's right, you make it through, you get yerself a nice little moose to hang on the wall. Well, OK, so it's a virtual moose on a virtual wall, but you can be right proud of 'em! Thanks to the efforts of Marilyn deQueiroz, you can now proudly admire your codin' accomplishments at the Cattle Drive Hall of Fame. Check it out, pardner, it's worth a wink.
Ol' timer Greg Harris bagged himself a moose for the servlets
assignments and is hard at work on that mean varmint known as JDBC. Sherry
Cuenco's got herself a moose this month for completin' the first set
of Cattle Drive assignments. And whoa, Nelly! Chuck "just call me Chuck"
Wannall's servin' up mooseburgers after finishin' up them OOP assignments.
Back in the saddle...
Hadn't heard from Cattle Driver Adalberto Altamirante for a spell,
but he's back in the saddle, wrasslin' down them cattle (and codin' some
Java assignments too!).
Nitpicking is hard work
too... We know they're workin' reeeeeally
hard, after all, we've seen what those assignments look
like once the nitpickers have combed through 'em. Hats
off to Marilyn deQueiroz, Pauline McNamara, and Jason Adam for their dedication
and patience with the pesky vermin that always manage to
make their way into those assignments.
Those gentlemen behind the bar...
Notice the fellas wipin' the bar and shinin' up the sarsparila glasses?
Updating that assignment log is tough work too. Big thanks to Michael Matola and Barry Gaunt. Mosey up and place
yer orders. Rumor has it Michael keeps some special stuff under the bar,
if you know what to ask fer.
Joinin' the Drive
You think ya got what it takes? You ready for some work and some good learnin'? Then pull up a stool and read up on Joinin' the Drive. Good luck!
Content and format adapted from Ol' Timer Pauline
McNamara's original column. -Michael Matola.
|
Return to Top
|
Scheduled Book Promotions for August (and early September) :
Return to Top
|