|
|
||
Michael Nascimento Santos's BlogDecember 2003 ArchivesJXPath to rescue!Posted by mister__m on December 31, 2003 at 07:36 AM | Permalink | Comments (6)Querying a database is no big deal. SQL has been around for a long time and has become the de facto standard for doing that. So has JDBC, even though nowadays it is being used more as the foundation of other solutions and frameworks. But what you do when you have to query objects? Most people wouldn't be able to answer it, really. Three more common ways of querying your objects in Java are custom indexing, OQL and JXPath. This entry is specifically about JXPath. Jakarta Commons JXPath basically defines a simple XPath interpreter that can be applied to general object graphs: POJOs, Maps, Servlet contexts, DOMs and more. XPath is a W3C standard originally conceived for navigating XML nodes, but can be easily applied to Java. Let's see it in action. To ilustrate its use and advantages, we will work with the classical Order problem (Order, LineItem and Product). Let's assume all Orders are stored in a Collection which is a property of our OrderHistory object. What if we wanted to get all the Orders which contained more than 5 CDs? In plain Java:
Collection selectedOrders = new ArrayList();
Order order;
LineItem item;
for (Iterator orders = orderHistory.getOrders().iterator(); orders.hasNext(); ) {
order = (Order)orders.next();
for (final Iterator items = order.getLineItems().iterator(); items.hasNext(); ) {
item = (LineItem)items.next();
if (item.getQuantity() > 5 && item.getProduct().getType().getName().equals("CD")) {
selectedOrders.add(order);
}
}
}
return selectedOrders.iterator();
To avoid being unfair, using 1.5 sintax: Collection With JXPath:
JXPathContext history = JXPathContext.newContext(orderHistory);
return history.iterate("/orders[lineItems[quantity = 5 and product/type/name = 'CD']]");
That is it. As simple as that. JXPath becomes more valuable as your queries become more complex, but I am not going to show an example here. Someone might ask: hey, but when I would like to manipulate objects in memory? There are a lot of occasions, actually. One very common is when you have a small application that needs to persist a small amount of data. If you combine Prevayler - an option to databases, as it keeps everything in memory and performs persistence through serialization and guarantees data integrity - and JXPath, you have a very fast solution with fewer lines of code. Consider using it when you have the chance. As a final note, JXPath has many powerful features, as compiled expressions and variables - similar to PreparedStatements -, pointer, and many more, but you can find more about these by yourself. Go to the above link, download and start using it. The User Manual in the docs is probably the best one for a Apache Project and is highly recommended reading. Try it as soon as you can: you may become addicted to it... A simple method call: that is all it takesPosted by mister__m on December 29, 2003 at 06:56 PM | Permalink | Comments (0)Not having the burden of managing transactions by yourself - a.k.a Container Managed Transactions, CMT for short - is a compelling reason for using EJBs. Obviously, EJB is not the only technology that gives you that, but that's a entirely different discussion. Back to the point, the fact you don't have to call any transaction management method neither in The most obvious thing - at least it should be - you should do is to specify which transaction attribute applies to each method in each EJB you wrote. There are a bunch of ways of doing it in the deployment descriptor, from specifying different attributes to each overloaded version of a method to using the same for all of them, and some containers have decent default values for when you don't declare anything, but I'm not going to cover this here. Today's point is more subtle than that and is something I've seen a considerable number of developers - including some good ones - not doing: calling
Mark the current transaction for rollback. The transaction will become permanently marked for rollback. A transaction marked for rollback can never commit. Only enterprise beans with container-managed transactions are allowed to use this method. Note that only EJBs that use CMT - most of them - are allowed to use this method. But when are they required to? When it must be called? The answer is relatively simple, but astonishing for some people (from now on, everything here refers to CMT EJBs). Let's start to answer these questions by taking a look at section 17.3.4.2 of the recently published EJB 2.1 spec: Typically, an enterprise bean marks a transaction for rollback to protect data integrity before throwing an application exception, because application exceptions do not automatically cause the container to rollback the transaction. I highlighted the bold part and I wish it was already printed in bold in the pdf, actually. A lot of people read this section and simply ignore this important sentence. An application exception does not cause the container to rollback a transaction. It is a simple, but ignored fact. But what is an application exception? Section 18.1.1 defines it: An application exception is an exception defined in the throws clause of a method of an enterprise bean’s home, component, message listener, or web service endpoint interface, other than the Enterprise bean business methods use application exceptions to inform the client of abnormal application-level conditions, such as unacceptable values of the input arguments to a business method. A client can typically recover from an application exception. Application exceptions are not intended for reporting system-level problems. Although the explanation is somewhat deceiving - Java won't stop you from declaring any The Bean Provider can rely on the container to perform the following tasks when catching a non-application exception:
So, if you throw a
// Some code goes here
public BigDecimal withdraw(BigDecimal amount) throws InsufficientBalanceException {
BigDecimal balance = getBalance();
//Ooops, trying to do something that shouldn't be done
if (balance.compareTo(amount) < 0) {
// This call is necessary as the exception to be thrown does not derive from RuntimeException
entityContext.setRollbackOnly();
throw new InsufficientBalanceException(balance, amount);
}
balance = balance.subtract(amount);
setBalance(balance);
return balance;
}
// And more code goes here
Throwing a checked exception is not enough; you need to call To end up, be aware that The container must throw the So, if all you are bean methods are configured with the Achieving better compression with DeflaterPosted by mister__m on December 26, 2003 at 10:48 AM | Permalink | Comments (4)I've recently been playing more intensively with CVS - I've always used either IDE support for it or any nice GUI client for CVS available - and found out more about GZIP compression than I knew before. That's my main motivation for this post. It's been quite a while - since JDK 1.1, according to javadocs - Java has been providing support for working with ZLIB compression through its API. The package So, getting straight to code, if you want to compress an object you are writing to a stream:
public void writeCompressed(OutputStream os, Object toWrite) throws IOException {
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new GZIPOutputStream(os));
oos.writeObject(toWrite);
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException ioe) {
/*
* The day someone gives me a sensible explanation why this method
* throws an exception (as if there was something I could do about it or
* if I cared!), I will be sooooo grateful :-D
*/
ioe.printStackTrace();
}
}
}
Besides the ugly Indeed, Deflater supports compression levels through a method named The problem is that
public void writeCompressed(OutputStream os, Object toWrite) throws IOException {
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new GZIPOutputStream(os) {
{
def.setLevel(Deflater.BEST_COMPRESSION);
}
});
oos.writeObject(toWrite);
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException ioe) {
/*
* The day someone gives me a sensible explanation why this method
* throws an exception (as if there was something I could do about it or
* if I cared!), I will be sooooo grateful :-D
*/
ioe.printStackTrace();
}
}
}
Using If you happen to be using Prevayler and would like to get smaller snapshots, take a look at reusable-components and download the latest version from here. Also, the Building javadoc from J2SDK source codePosted by mister__m on December 25, 2003 at 07:04 AM | Permalink | Comments (8)If you read my last blog entry about J2SDK 1.5 alpha availability, you know you cannot make public comments about. So, with that information in mind, let's move on :-D Suppose you download a J2SDK version from Sun that comes with no documentation at all. Well, all of them come without it, but for most you can get the docs as a separate bundle and install them. Very recently, I downloaded a J2SDK version for which there is no documentation at all. And no, you cannot download it from Sun's site; it is not there. How am I supposed to work with a JDK that has no documentation? At least, I can build javadoc from its source code and it becomes more usable - though not completely, as the new features summary and those sections where concepts are explained and detailed are necessary for a full experience :-D. In case you happen to face the same problem - if you read my blog frequently, there is a chance you are :-D -, here is a sample Ant build script - not the best possible, it's not the point - you may use to build javadoc from source code: That is it, folks! Remember to edit the script so JDK_HOME becomes your real JDK installation home (ex: C:\j2sdk1.4.2_02), JDK_MAJOR_VERSION becomes the major version of the JDK you are using (ex: 1.4, 1.5 ...) and PLATFORM_EXTENSION becomes the extension used by executables in your platform (ex: for Windows, it's exe). And yeah, it consumes a lot of memory. You can change the value -J-Xmx512m as you want, but it didn't work for me with 128mb, for example. It took around 8 minutes to run it in a P4 2.4GHz with 1GB - hey, but I was making normal use of it (4 IM softwares, email client, etc.) BREAKING NEWS: Got Tiger?Posted by mister__m on December 24, 2003 at 04:36 AM | Permalink | Comments (0)I was going to blog about Date and Calendar (and how terrible they are), but these must wait now. Straight to the point: if you want to get J2SDK 1.5.0 alpha, just go to: http://www.javalobby.org/members/j2se15.jsp This is a cooperation between JavaLobby - hey, just became a member 3 weeks ago, after years of Java, can you believe it? - and Sun. This is really a private release, so, you are not allowed to share your opinions about it with anyone except Sun. No, no feedback on this blog or any comments about J2SDK 1.5 alpha are allowed at all. You must be a member of JavaLobby to download it. Are you still reading this??? Go there and download it now! Writing enums before TigerPosted by mister__m on December 10, 2003 at 10:46 PM | Permalink | Comments (12)One thing I've been missing in Java is support for enums. Some of you might be asking: but what is a enum and why should I care about them? A enum is, in a simple way, a class with a limited domain. For example, a class representing the seasons we have during the year - although climate seems crazy these days, anyway, but that's a different story - is a enum. Another example would be a class that represents gender, as it only has two values, male and female (though, again, some might argue it is not that simple :-D). Enums for J2SE 1.5 are being defined by JSR-201. I recommend you read the draft spec when you have the chance, but I'll cite the relevant points as needed. First, let's take a look at the main features both - my implementation and the future J2SDK 1.5 one - share, as specified by the draft spec at the JCP site:
How is it possible to achieve these things now? By using the
import net.java.dev.reusablecomponents.lang.Enum;
public final class Gender extends Enum implements MyInterface {
public static final Gender MALE = new Gender("Male");
public static final Gender FEMALE = new Gender("Female");
private Gender(String name) {
super(name);
}
}
In this example, MyInterface is a simple marker interface that is implemented just to show you it is possible to do so. :-D The code doesn't look that complicated, but it gives you all those things and also these additional features quoted from the JCP spec: All enum classes have high-quality toString, hashCode, and equals methods. All are Serializable, Comparable and effectively final. None are Cloneable. Arbitrary fields may be added to enum classes, and to individual enum constants. To be exact, you have to make your Enum subclasses final. If you subclass an Enum subclass, it simply won't work. However, the greatest feature these Enum subclasses have is that their instances may be compared using the Surely, there are some differences between my Enum and the one provided by the JSR-201. I hope to explain most of them here, but to be sure you understand all the differences, read the spec linked above and browse the most recent version of my Enum implementation. While the J2SE 1.5 enum is intended to give you comparability, it limits the way you naturally compare your instances by making
public enum Gender implements MyInterface {
male, female
}
Although it is by far cleaner than the code I showed above, it requires special compiler features and most IDEs won't support it now. Maybe you could be thinking: but why I need to use a superclass if I can write an enum implementation on without one? Well, you would have to rewrite things you need, such as serialization and Now that I gave you a general idea of what If you are interested enough, I recommend you check the code. You can ask questions and leave your comments below. reusable-components is intended to give you more than that, though; in the next few weeks, I expect to commit some validators for user input and also a cool image generator for use in forms to make sure users aren't frauding your application. Join the project if you want to help. And stay tuned. | ||
|
|