Free as in Speach or Free as in Beer?
I never understood this line when discussing Open-Source Software. Richard Stallman attempted to clarify the differences in Open-Source distribution models by saying "Free as in speach, not free as in beer".
"Free as in beer" is meant to signify a gratis, or no-cost (no money) distribution (but it is not necessarily free to do with as you please), while "Free as in speach" is meant to represent freedom of use - with little or no restrictions.
When was the last time you received free beer?
And if you did receive a free beer, couldn't you do with it as you pleased? Like drink it or maybe even give it to another friend because you know if you drink more, you'll have no cognitive functions left to try and understand what the stupid phrase "Free as in speach, but not free as in beer" means?
I think we shud shtop wif fis analogie. It surtanly onli cnfsed me mur. Hiccup.
Wikipedia explains it well enough by saying Gratis vs Libre
See? Latin is still useful!
Hiccup.
Java Class Naming Conventions
Ok, I'm about to go on a rant, because I come across something regularly that really, really, REALLY irritates me:
Whenever you see a class that implements an interface SomeName, and the name of that class is SomeNameImpl.
Guess what folks, EVERY implementation of an interface is an 'Impl'. If you suffix 'Impl' at the end of your class name, you're being short sighted and portraying a potential lack of understanding of Interface-Driven Design: that you can have more than one implementation.
What if you ever create a new implementation? What if, when testing other components, you create a TestSomeName implementation or a MockSomeName implementation? Then the SomeNameImpl doesn't make much sense anymore, does it? It could be a cause of confusion as to why you have more than one 'Impl', or, worse, perhaps it might make people think that you should only ever have one 'Impl'.
Instead, if you need a default implementation, and can't yet think of other cases where you might have other implementations, just call it DefaultSomeName. Then you're telling the world, "Hey, this is our default implementation of this interface, and if any more ever are needed, we can create them, prefixed with a more meaningful name.".
Yes, I'm an OO naming zealot, but you'd be surprised at how this little change, in conjunction with other 'trivial' changes, make code more readable, easy to understand, and most important, adaptable to change over time.
Root Persistent Class for ORM Hierarchies (Hibernate, et. al.)
Ok, I'm about to divulge to the world one of my little programming gems - something I've used on every single project for almost the last 4 years now. It is very easily translated to any other OO language as well, especially C# for the .NET/Hibernate.NET folks.
I haven't been keeping it secret or anything, I guess I just never took the time to write it out for general public. So when someone reading my blog asked to see the source for it, I figured now is as good a time as any to write about it.
It is a root/base class from which all my persistent Classes extend. To put it another way, if I have Java instances that I need to store to a database through Hibernate or some other EIS API, every one of those instance Classes extend from this base class (either directly or indirectly in an OO hierarchy). Every entity in every persistent class hierarchy I've used in the last 4 years has it as its hierarchy root - it is versatile and resilient
Now, if you've used Hibernate much before, you'll realize this isn't the world's biggest secret - most people do something similar. Its a great idea. I'm just making mine available to the world in case there are those that haven't done something similar yet, or if those who have just want to see how I do things.
What is this class called? I call it Entity. In Object-Relational Mapping circles, the word Entity often comes up in the context of object persistence discussions - "Persistent Object", "Persistent Entity", "Base Persistent Object", etc. I personally think "Entity" is elegantly succinct, so I stuck with it.
Before going on to the code, I just want to clarify my Entity class a little bit. It is not an implementation of what many call the "Active Record design pattern". This means this base entity class doesn't know how to persist or delete itself via any save() or delete() methods.
I'm a firm believer in keeping persistence logic code out of my domain model to prevent the chance of polluting the rest of my application with those APIs (it goes beyond API pollution too - google the principal of "Low Coupling, High Cohesion" for more info). Anyway, and I relegate all such logic to DAO implementations and all of my domain classes remain nice and clean.
Ok, so now that point is settled, here's my oh-so-yummy-and-incredibly-useful Entity class:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.io.Serializable;
/**
* Root parent class for all persistent object entities.
*
* <strong>NOTE:</strong> Subclasses should <em>always</em> provide a unique
* onEquals() and hashCode() implementation and these should not use
* the id() property - i.e. always keep in mind the subclass' 'business keys'
* when implementing those methods.
*
* @author Les Hazlewood
*/
public abstract class Entity implements Identifiable, Serializable, Cloneable {
protected transient final Log log = LogFactory.getLog(getClass());
/**
* RDBMS Primary key, aka 'surrogate key'. Long surrogate keys are best
* for RDBMS performance (for many reasons that can't be expanded on here)
* But, every single table should _always_ have a 'business key' - a unique
* constraint across one or more columns that guarantee row duplicates will
* never occur. Null value means the object hasn't been persisted to the RDBMS
*/
protected Long id = null;
/**
* Used for optimistic locking to ensure two threads (even across different machines)
* don't simultaneously overwrite entity state - not necessarily used by all subclasses.
* Pretty much required if in a high-concurrency environment and/or if using distributed
* caching in a cluster. It (and its corresponding mutator methods) is not called
* 'version' to prevent eliminating that name from subclasses should the business
* domain naming conventions require it. Also 'entityVersion' is self-documenting
* and leaves little room for incorrect interpretation.
*/
protected int entityVersion = -1;
public Entity() {
}
public Long getId() {
return this.id;
}
/**
* Should <em>never</em> be called directly. Only via Hibernate or other EIS framework, since
* they get the ID from the RDBMS directly.
*
* This method can be removed entirely if the EIS framework supports setting the ID property
* directly (e.g. through reflection). Hibernate does support this, it is called 'property access'.
*/
public void setId(Long id) {
this.id = id;
}
public int getEntityVersion() {
return this.entityVersion;
}
/**
* For the same reasons as the setId() method, this should only be called by a
* framework and never directly. Can be removed if the framework supports property access.
*/
public void setEntityVersion(int entityVersion) {
this.entityVersion = entityVersion;
}
/**
* This method is declared final and does a lot of performance optimization:
*
* It delegates the actual "equals" check to subclasses via the onEquals method, but
* it will only do so if the object for equality comparison is
*
* <ol>
* <li>not the same memory location as the current object (fast sanity check)</li>
* <li>of type Entity or one of its subclasses</li>
* <li>Does not have the same id() property</li>
* </ol>
*
* #3 is important: this is because if two different entities have the ID property
* already populated, then they have already been inserted in the database, and
* because of unique constraints on the database (i.e. your 'business key'), you
* can <em>guarantee</em> that the objects are not the same and there is no need
* to incur attribute-based comparisons for equals() checks.
*
* This little technique is a massive performance improvement given the number of times
* equals checks happen in most applications.
*/
public final boolean equals(Object o) {
if (o == this) {
return true;
}
if (o instanceof Entity) {
Entity e = (Entity) o;
Long thisId = getId();
Long otherId = e.getId();
if (thisId != null && otherId != null) {
return thisId.equals(otherId) &&
getClass().isAssignableFrom(e.getClass());
} else {
return onEquals(e);
}
}
return false;
}
/**
* Subclasses must do an equals comparison based on business keys here.
*/
public abstract boolean onEquals(Entity e);
public abstract int hashCode();
/**
* If children classes override they must always call super.clone() to get the object
* with which they manipulate further to clone remaining attributes. Never acquire
* the cloned object directly via 'new' operator (this is true regardless of this Entity
* class or not).
*/
@Override
@SuppressWarnings({"CloneDoesntDeclareCloneNotSupportedException"})
public Object clone() {
Entity e;
try {
e = (Entity) super.clone();
} catch (CloneNotSupportedException neverHappens) {
// Should _never_ happen since this class is Cloneable and
// a direct subclass of Object
throw new InternalError("Unable to clone object of type [" + getClass().getName() + "]");
}
e.setId(null);
e.setEntityVersion(-1);
return e;
}
/**
* Returns a StringBuffer representing the toString function of the class implementation. This
* should be overridden by all children classes using <tt>super.toStringBuffer()</tt> as the
* base, adding properties to the returned StringBuffer.
*
* @return a <tt>StringBuffer</tt> reperesenting the <tt>toString</tt> value of this object.
*/
public StringBuffer toStringBuffer() {
StringBuffer sb = new StringBuffer();
sb.append("id=").append(getId());
return sb;
}
/**
* Returns toStringBuffer().toString(). Declared as 'final' to require subclasses to override
* the {@link #toStringBuffer()} method, a cleaner and better performing mechanism for toString();
*
* @return toStringBuffer().toString()
*/
public final String toString() {
return toStringBuffer().toString();
}
}
You'll notice that the Entity class also implements Identifiable, which is nothing more than this:
/**
* @author Les Hazlewood
*/
public interface Identifiable {
Long getId();
}
This doesn't look too useful, but I have another interface that subclasses ('sub interfaces'?) it:
/**
* @author Les Hazlewood
*/
public interface Referenceable extends Identifiable {
String getLabel();
}
Referenceable is particularly useful in GUI/web code where you might want to present a list of options to the user, and the list-generation code only cares about IDs and readable strings to present to the user. For example, a drop-down/select box:
$referenceable.label
The list generation code doesn't care if the collection it is processing has User elements, or EmailAddress elements, or anything else. Ahh, the beauty of polymorphism
Anyway, I hope you find this Entity class as useful as I have - it is the staple by which I develop all of my domain models in Java.
Cheers,
Les
Configuration-hell remedy with Singleton injection – DON'T do it
So, I just finished reading this blog post about Spring configuration advocating static getInstance() methods in some places in your code to reduce the amount of Spring xml config. Since I posted a reply on that blog, and the author would probably be inclined to moderate my entry and delete it because I directly oppose his position, I've reposted it here for the benefit of others to read.
THAT POST ADVOCATES POOR ARCHITECTURE. IGNORE IT.
If you're relatively new to the Spring framework, ignore the recommendations in that post entirely - you'll be saving yourself a _lot_ of pain in your software architecture.
Basically, here's my reply:
This is a really bad idea and is exactly what Spring pojo-based Dependency Injection was created to avoid - to replace the Service Locator pattern. What you're providing in a static getInstance() call is essentially a type-specific Service Locator.
Statics are evil - they're inherently non-OO and usually encourage poor programming practices, especially the proliferation of unnecessary functional programming in an OO language. They should only be used to overcome poor programming situations outside of your control - i.e. a tool to use in an extremely limited basis only when you can't use something else.
And although what you describe might make your life easier in the immediate sense, it significantly complicates it in other ways. How, for example, would you unit test your code properly without introducing dependencies not required for the test? Cleaner instance-level DI allows you do do things such as creating mock objects and anonymous inner classes for testing that is not possible with static singletons or where you would have to change a lot of code.
If you want to make your life easy, use autowiring - that's exactly why it was created. The new Spring 2.0 XML namespaces also simplify things greatly, reducing XML config. And, with IDEs like Eclipse and IntelliJ IDEA that actually can traverse, manage, and refactor the XML spring files for you, the "XML Hell" argument for using Static singletons, especially when your own code suffers greatly in flexibility, is not really an issue.
Bottom line - never let laziness dictate your software architecture (especially when similar alternatives like autowiring exist), and stick with the pragmatic, well-thought and proven truly Object-Oriented solution.
I just thought it important to raise the issue on this for anybody reading this blog entry, especially those relatively new to Spring. What is mentioned is _not_ a good idea for 99% of cases, and the less-experienced Spring folks shouldn't be led down a dangerous path. It could introduce really bad habits that would hurt you later on.
Consistent Cache Configuration: Spring, Hibernate, EhCache, Shiro, et. al.
Have you ever wanted to use caching in your Spring/Hibernate application beyond just supporting Hibernate's 2nd-level cache?
If you know what a Hibernate 2nd-level cache is, you really know how huge its performance benefits are. Wouldn't it be useful to utilize caching for other things in your application? Even if you don't explicitly use a caching API in your app, you still might already be using caching without knowing it - other open source frameworks in addition to Hibernate utilize caching internally for the same performance benefits.
This article explains how to achieve the following:
1) I know I'm going to utilize caching for Hibernate's 2nd-level cache, but I want to enable that same caching support to other libraries and frameworks that might need it. It would also nice to have if I ever need to use it in my own application code directly.
2) My application is Spring-configured, so I want to configure that caching support in Spring like everything else and then have all the frameworks/libraries, including Hibernate, to use these Spring-configured cache beans.
Unfortunately Hibernate makes this a pain to do.
Hibernate uses something called a CacheProvider to support its 2nd-level cache. A Hibernate SessionFactory uses a single CacheProvider to maintain/manage the individual Cache instances used by the 2nd-level cache.
Now here's the problem: This CacheProvider is instantiated by Hibernate based on text configuration properties specified to the SessionFactory. When the SessionFactory starts up, it reads these properties, finds the one called hibernate.cache.provider_class which specifies a fully-qualified class name of the CacheProvider implementation, and creates a new instance of that class via reflection. It then uses that instance from then on to manage the Cache instances it needs.
For existing spring configs, here is a simplified example (note the 2nd hibernate property):
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.cache.provider_class = net.sf.ehcache.hibernate.EhCacheProvider
Why is this a problem? Because you can't easily configure your CacheProvider instance yourself and then just tell the SessionFactory to use it. The SessionFactory interface and its default implementation do not have setter methods that would allow you to do so. This means you can't use Dependency-Injection to set the CacheProvider instance on the Hibernate SessionFactory in Spring or any other DI microcontainer.
This is a problem for me too. The scenario that prompted this article happens to me quite a bit - I use Hibernate plus other libraries that benefit from caching. My own open-source project, Apache Shiro, can use caching to greatly speed up security checks. When I use Hibernate and Shiro in the same application, I want both frameworks to use the same underlying cache infrastructure. And although Shiro supports DI for its cache support, Hibernate does not, which means I have to jump through hoops to get Hibernate to play nice.
Where does Ehcache come in to this? Well, Ehcache is one of the more well-known and stable open-source caching solution for enterprise applications. It is stable and has a long history, it is extremely efficient with goodies like smart multi-threading under the hood, and now with Ehcache 1.3+, supports multicast distributed caching in a cluster - a huge benefit in enterprise apps. Basically, for open-source options, it is one of the best you can get. Cheers to Greg Luck for creating and supporting this great library (Another wonderful Open Source alternative is TerraCotta, take a look at that too).
So, in this particular example, I'm using EhCache but I also want to use it not just for Hibernate, but for Shiro and everything else that could use a Cache. And until now, I've been using Ehcache as Hibernate's cache provider using the aforementioned text property. Hibernate would create an instance of EhCacheProvider and use it internally. Basically this EhCacheProvider implementation is a wrapper around EhCache's own API of a CacheManager.
The CacheManager is really what I want to configure in Spring. Typically it is good practice and much easier to specify a single CacheManager for an application, which uses a single ehcache.xml file for all configuration. Then you can use this one ehcache.xml file for your Hibernate cache configuration, as well as for any other library that would use EhCache under the hood.
So, since you can't inject a CacheManager into Hibernate's SessionFactory, how do you do this in Spring?
Well, Since Hibernate instantiates the CacheProvider itself, and we can't inject anything, our only option left is via static memory. Blech, I know - I don't like statics any more than you do, but don't worry - it is _only_ used as a mechanism to make Hibernate play nice and its never used anywhere else in your config or application code.
*Note that static memory will only allow a single CacheManager to be used across the entire VM, so if you need more than one Hibernate SessionFactory, each with its own separate cache configs, you'll need to do more trickery (maybe 2 static fields? one per SessionFactory? You'll know more about your app than I do, so I'll leave how to do that to you. But you can use this the following technique and expand on it for your environment).
Let's get to the code, its only one class. You'll create your own CacheProvider implementation to statically reference a CacheManager instance. The CacheManager instance will be configured in Spring, and we'll get to that in a bit. Here's the CacheProvider implementation:
package com.leshazlewood.hibernate;
import net.sf.ehcache.CacheManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.cache.Cache;
import org.hibernate.cache.CacheException;
import org.hibernate.cache.CacheProvider;
import org.hibernate.cache.Timestamper;
import java.util.Properties;
/**
* @author Les Hazlewood
*/
public class ExternalEhCacheProvider implements CacheProvider {
protected transient final Log log = LogFactory.getLog(getClass());
private static CacheManager cacheManager = null;
/**
* This is the method that is called by an external framework (e.g. Spring) to set the
* constructed CacheManager for all instances of this class. Therefore, when
* Hibernate instantiates this class, the previously statically injected CacheManager
* will be used for all hibernate calls to build caches.
* @param cacheManager the CacheManager instance to use for a HibernateSession factory using
* this class as its cache.provider_class.
*/
public static void setCacheManager(CacheManager cacheManager) {
ExternalEhCacheProvider.cacheManager = cacheManager;
}
public Cache buildCache(String name, Properties properties) throws CacheException {
try {
net.sf.ehcache.Ehcache cache = cacheManager.getEhcache(name);
if (cache == null) {
if ( log.isWarnEnabled() ) {
log.warn( "Unable to find EHCache configuration for cache named [" + name + "]. Using defaults.");
}
cacheManager.addCache( name );
cache = cacheManager.getEhcache(name);
if (log.isDebugEnabled()) {
log.debug("Started EHCache region '" + name + "'");
}
}
return new net.sf.ehcache.hibernate.EhCache(cache);
} catch (net.sf.ehcache.CacheException e) {
throw new CacheException(e);
}
}
public long nextTimestamp() {
return Timestamper.next();
}
public void start(Properties properties) throws CacheException {
//ignored, CacheManager lifecycle handled by the IoC container
}
public void stop() {
//ignored, CacheManager lifecycle handled by the IoC container
}
public boolean isMinimalPutsEnabledByDefault() {
return false;
}
}
Ok, now that you have this class, what do you do with it? Well the first thing is to change your hibernate.cache.provider_class value to now be com.leshazlewood.hibernate.ExternalEhCacheProvider in your Hibernate SessionFactory bean definition. Then you want to define your CacheManager instance as a bean in your Spring config. Next you want to tell this CacheProvider implementation to use that instance when Hibernate needs to use caching functions.
We do that via a cool little Spring trick - by using the MethodInvokingFactoryBean. Basically this bean will call a static method at application startup with specified method arguments. Its a handy little tool that we can use to statically call the setter method that makes the CacheProvider work:
So the above spring config says: At application startup, create the CacheManager instance named 'ehcacheCacheManager' and then inject it into the ExternalEhCacheProvider via that class's 'setCacheManager' static method.
But are we finished?
Well, not quite. We have one piece of cleanup work to do.
The experienced Spring folks will recognize that there can possibly be a race condition with our Hibernate SessionFactory and CacheManager/CacheProvider definitions. Yes, our Spring-configured CacheManager instance will be created and injected into the ExternalEhCacheProvider class correctly, and our Hibernate SessionFactory bean instance will be created correctly. But, what if the Hibernate SessionFactory tries to use a ExternalEhCacheProvider instance before it is ready to be used? (i.e. before the static CacheManager property has been injected?)
To prevent this race condition and guarantee that the ExternalEhCacheProvider's internal CacheManager instance is set so it is available when the Hibernate SessionFactory needs it, we use the spring bean 'depends-on' attribute in our SessionFactory definition:
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
depends-on="cacheProviderCacheManagerInjector">
hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.cache.provider_class = com.leshazlewood.hibernate.ExternalEhCacheProvider
So, although our Hibernate SessionFactory bean doesn't actually use the CacheManager as a property - otherwise this whole article would be pointless
- we force it to wait until the cacheProviderCacheManagerInjector bean has done its work before we allow it to initialize.
We make the 'depends-on' attribute point to this injector (MethodInvokingFactoryBean) instance specifically (as opposed to the ehcacheCacheManager bean) because we care that it is not only created, but also injected too.
There. Now we're done.
Now when the Hibernate SessionFactory bean starts up and creates its hibernate.cache.provider_class instance, we can rest assured that it will access our Spring-configured CacheManager.
And, you'll be able to use that same Spring-configured 'ehcacheCacheManager' bean and inject it into Shiro, or any other framework that supports simple Dependency Injection. Because this bean is an application singleton and uses a single config file, now all of your caching config across the entire application is easily manged from the same location - very convenient.
Have fun!
Spring Application Bootstrap Data
When you install an application for the first time, many times you want 'bootstrap' data to exist before the application is used for the very first time. Here's a simple but easy technique to get bootstrap data inserted into your application upon first startup.
Prior to the following approach, I used to have 'default.data' and 'sample.data' tasks in my ant scripts that either ran SQL manually, or started up a separate Spring ApplicationContext and inserted data explicitly. You had to run it manually from ant, which 1) required that ant be installed and 2) that you had the project checked out on the box that you were installing data to. Many production and QA environments didn't meet this criteria, and even if they did, it is still cumbersome and isn't as nice as an 'automatic' solution.
My newer automatic solution moves this type of data insertion logic into the actual application, where it is better managed and tested. There is another benefit too though: Since I use Hibernate and JCR as the EIS-tier APIs, it is far easier to insert data via these standard APIs than to do so via raw SQL. This is because you can write all of your initial data objects and graphs with Java or Groovy POJOs, utilizing the benefits of powerful IDE coding features, and let the Hibernate and JCR frameworks insert all the data with dependencies for you: a massive time saver.
So, here's a simple way to do this:
You create a POJO that will execute at application startup automatically after its dependencies have been injected. Here's an example:
import org.springframework.beans.factory.InitializingBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
public class BootstrapDataPopulator implements InitializingBean {
private transient final Log log = LogFactory.getLog( getClass() );
//Spring's transaction manager - needed to ensure data is inserted in a transaction:
//any failures, and we can roll back everything.
private PlatformTransactionManager transactionManager = null;
//all other managers/dependencies here
public BootstrapDataPopulator() {
}
public void setTransactionManager( PlatformTransactionManager transactionManager ) {
this.transactionManager = transactionManager;
}
//other dependency setter methods
public void afterPropertiesSet() throws Exception {
if ( this.transactionManager == null ) {
throw new IllegalStateException( "transactionManager property must be set." );
}
//assert other injected dependencies here
TransactionTemplate txnTemplate = new TransactionTemplate( this.transactionManager );
txnTemplate.afterPropertiesSet();
txnTemplate.execute( new TransactionCallback() {
public Object doInTransaction( TransactionStatus status ) {
try {
insertBoostrapData();
} catch ( Exception e ) {
//error - roll back. Runtime exception triggers rollback:
if ( e instanceof RuntimeException ) {
throw (RuntimeException)e;
} else {
throw new RuntimeException( e );
}
}
return null;
}
} );
}
private boolean guestUserExists() {
return userManager.findUserByUsername( "guest" ) != null;
}
protected void insertBoostrapData() throws Exception {
//if the guest user account exists, take this as a sign that the bootstrap data populator has
//already been run, so just exit quietly:
if ( guestUserExists() ) {
if ( log.isDebugEnabled() ) {
log.debug( "Bootstrap data insertion has already occurred. Returning quietly." );
}
return;
}
if ( log.isInfoEnabled() ) {
log.info( "Inserting bootstrap data..." );
}
//otherwise, populate bootstrap data:
log.debug("Creating guest user...");
User guestUser = someManager.create( new User( "Guest", "guest@domain.com" ) );
//insert all other objects and call any other helper methods here
}
}
The key to this code working as a POJO in your normal application configuration is due to two things:
- The insertBootstrapData() method is wrapped in the TransactionTemplate. If anything goes wrong during the execution of that method, it will be rolled back and the database remains in a consistent state
- The first bit of code in insertBootstrapData() checks to see if a well-known entity already exists in the database. If it does, you can assume that the bootstrap data has already been inserted, and return quietly.
You can create other 'Bootstrap Beans' like this to do other things as well. The above one initialized RDBMS data. You can have another one that initializes your JCR repository. Or another that checks against a license store to ensure that the application installed is allowed to be installed. All sorts of things...
Java Email Address class
UPDATE: This Java class was updated on February 1st, 2008 to account for domain literals and quoted strings such as "John Smith" <john.smith@somewhere.com>. It is now effectively the only complete and semantically correct email validator for Java.
PETTY REQUEST: The update required considerably more effort than the original as it now accounts for all valid RFC parsing conditions. Because of this, and that this page is easily my most visited, I'd appreciate it if you could show your appreciation by hooking a brother up and clicking on some ads. It helps pay for my hosting. Thanks!
I'm writing a new open source CMS (Community Management System) based entirely on the Spring Framework and Hibernate.
This CMS will take many cues from Drupal and other PHP based CMS systems, but be far more flexible, have fantastic OO and design pattern architectures and be a benefit to the Java Enterprise software community. I've decided to abandon JSR-168 support - I want a much cleaner, easier to implement, OO-based and typesafe "plugin" support framework - which I'm working on now. Suffice it to say I'm not a fan of JSR-168, but that's a whole 'nuther post.
Anyway, In this CMS, I'm using time-honored OO classes I've used on many many projects. One such is the EmailAddress class that I've referenced in earlier posts in this blog for email address validation. I've gotten some good feedback on this class, so I thought I'd just post the whole thing in case anyone wants to benefit from it (instead of just using code chunks I've posted before).
Here it is:
/*
* Copyright 2008 Les Hazlewood
*
* 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.io.Serializable;
import java.util.regex.Pattern;
/**
* An email address represents the textual string of an
* RFC 2822 email address and other corresponding
* information of interest.
*
*
If you use this code, please keep the author information in tact and reference
* my site at leshazlewood.com. Thanks!
*
* @author Les Hazlewood
*/
public class EmailAddress implements Serializable {
/**
* This constant states that domain literals are allowed in the email address, e.g.:
*
*
someone@[192.168.1.100] or
* john.doe@[23:33:A2:22:16:1F] or
* me@[my computer]
*
*
The RFC says these are valid email addresses, but most people don't like allowing them.
* If you don't want to allow them, and only want to allow valid domain names
* (RFC 1035, x.y.z.com, etc),
* change this constant to false.
*
*
Its default value is true to remain RFC 2822 compliant, but
* you should set it depending on what you need for your application.
*/
private static final boolean ALLOW_DOMAIN_LITERALS = true;
/**
* This contstant states that quoted identifiers are allowed
* (using quotes and angle brackets around the raw address) are allowed, e.g.:
*
*
"John Smith" <john.smith@somewhere.com>
*
*
The RFC says this is a valid mailbox. If you don't want to
* allow this, because for example, you only want users to enter in
* a raw address (john.smith@somewhere.com - no quotes or angle
* brackets), then change this constant to false.
*
*
Its default value is true to remain RFC 2822 compliant, but
* you should set it depending on what you need for your application.
*/
private static final boolean ALLOW_QUOTED_IDENTIFIERS = true;
// RFC 2822 2.2.2 Structured Header Field Bodies
private static final String wsp = "[ \\t]"; //space or tab
private static final String fwsp = wsp + "*";
//RFC 2822 3.2.1 Primitive tokens
private static final String dquote = "\\\"";
//ASCII Control characters excluding white space:
private static final String noWsCtl = "\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F";
//all ASCII characters except CR and LF:
private static final String asciiText = "[\\x01-\\x09\\x0B\\x0C\\x0E-\\x7F]";
// RFC 2822 3.2.2 Quoted characters:
//single backslash followed by a text char
private static final String quotedPair = "(\\\\" + asciiText + ")";
//RFC 2822 3.2.4 Atom:
private static final String atext = "[a-zA-Z0-9\\!\\#\\$\\%\\&\\'\\*\\+\\-\\/\\=\\?\\^\\_\\`\\{\\|\\}\\~]";
private static final String atom = fwsp + atext + "+" + fwsp;
private static final String dotAtomText = atext + "+" + "(" + "\\." + atext + "+)*";
private static final String dotAtom = fwsp + "(" + dotAtomText + ")" + fwsp;
//RFC 2822 3.2.5 Quoted strings:
//noWsCtl and the rest of ASCII except the doublequote and backslash characters:
private static final String qtext = "[" + noWsCtl + "\\x21\\x23-\\x5B\\x5D-\\x7E]";
private static final String qcontent = "(" + qtext + "|" + quotedPair + ")";
private static final String quotedString = dquote + "(" + fwsp + qcontent + ")*" + fwsp + dquote;
//RFC 2822 3.2.6 Miscellaneous tokens
private static final String word = "((" + atom + ")|(" + quotedString + "))";
private static final String phrase = word + "+"; //one or more words.
//RFC 1035 tokens for domain names:
private static final String letter = "[a-zA-Z]";
private static final String letDig = "[a-zA-Z0-9]";
private static final String letDigHyp = "[a-zA-Z0-9-]";
private static final String rfcLabel = letDig + "(" + letDigHyp + "{0,61}" + letDig + ")?";
private static final String rfc1035DomainName = rfcLabel + "(\\." + rfcLabel + ")*\\." + letter + "{2,6}";
//RFC 2822 3.4 Address specification
//domain text - non white space controls and the rest of ASCII chars not including [, ], or \:
private static final String dtext = "[" + noWsCtl + "\\x21-\\x5A\\x5E-\\x7E]";
private static final String dcontent = dtext + "|" + quotedPair;
private static final String domainLiteral = "\\[" + "(" + fwsp + dcontent + "+)*" + fwsp + "\\]";
private static final String rfc2822Domain = "(" + dotAtom + "|" + domainLiteral + ")";
private static final String domain = ALLOW_DOMAIN_LITERALS ? rfc2822Domain : rfc1035DomainName;
private static final String localPart = "((" + dotAtom + ")|(" + quotedString + "))";
private static final String addrSpec = localPart + "@" + domain;
private static final String angleAddr = "<" + addrSpec + ">";
private static final String nameAddr = "(" + phrase + ")?" + fwsp + angleAddr;
private static final String mailbox = nameAddr + "|" + addrSpec;
//now compile a pattern for efficient re-use:
//if we're allowing quoted identifiers or not:
private static final String patternString = ALLOW_QUOTED_IDENTIFIERS ? mailbox : addrSpec;
public static final Pattern VALID_PATTERN = Pattern.compile(patternString);
//class attributes
private String text;
private boolean bouncing = true;
private boolean verified = false;
private String label;
public EmailAddress() {
super();
}
public EmailAddress(String text) {
super();
setText(text);
}
/**
* Returns the actual email address string, e.g. someone@somewhere.com
*
* @return the actual email address string.
*/
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
/**
* Returns whether or not any emails sent to this email address come back as bounced
* (undeliverable).
*
*
Default is false for convenience's sake - if a bounced message is ever received for this
* address, this value should be set to true until verification can made.
*
* @return whether or not any emails sent to this email address come back as bounced
* (undeliverable).
*/
public boolean isBouncing() {
return bouncing;
}
public void setBouncing(boolean bouncing) {
this.bouncing = bouncing;
}
/**
* Returns whether or not the party associated with this email has verified that it is
* their email address.
*
*
Verification is usually done by sending an email to this
* address and waiting for the party to respond or click a specific link in the email.
*
*
Default is false.
*
* @return whether or not the party associated with this email has verified that it is
* their email address.
*/
public boolean isVerified() {
return verified;
}
public void setVerified(boolean verified) {
this.verified = verified;
}
/**
* Party label associated with this address, for example, 'Home', 'Work', etc.
*
* @return a label associated with this address, for example 'Home', 'Work', etc.
*/
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
/**
* Returns whether or not the text represented by this object instance is valid
* according to the RFC 2822 rules.
*
* @return true if the text represented by this instance is valid according
* to RFC 2822, false otherwise.
*/
public boolean isValid() {
return isValidText(getText());
}
/**
* Utility method that checks to see if the specified string is a valid
* email address according to the * RFC 2822 specification.
*
* @param email the email address string to test for validity.
* @return true if the given text valid according to RFC 2822, false otherwise.
*/
public static boolean isValidText(String email) {
return (email != null) && VALID_PATTERN.matcher(email).matches();
}
public boolean equals(Object o) {
if (o instanceof EmailAddress) {
EmailAddress ea = (EmailAddress) o;
return getText().equals(ea.getText());
}
return false;
}
public int hashCode() {
return getText().hashCode();
}
public String toString() {
return getText();
}
public static void main(String[] args) {
String addy = "\"John Smith\" ";
if (isValidText(addy)) {
System.out.println("Valid email address.");
} else {
System.out.println("Invalid email address!");
}
}
}
Connecting to Ingres 2006 on Linux via JDBC
Ok, I had a hell of a time trying to get this figured out. It seems like my Ingres 2006 install environment did not match the documentation on the ingres website, which looks to be docos for the older r3 product. This seriously sucked. C'mon guys - get the docos right.
Anway, here's what I had to do.
I didn't install this ingres instance, but I did realize that a process named 'iijdbc' was running. Apparently this is what allows jdbc to connect to an Ingres 2006 installation. We do not have Data Access Server running (iigdc).
When doing a process listing, this is what I get:
> ps aux | grep ingres
ingres 3903 0.0 0.0 11140 2228 pts/0 S 15:50 0:00 /ingres/application/ingres/bin/iigcn II gcn
ingres 4038 0.0 1.0 145164 55068 pts/0 Sl 15:50 0:00 /ingres/application/ingres/bin/iidbms recovery (dmfrcp) II
ingres 4156 0.0 0.0 86212 3748 pts/0 S 15:50 0:00 /ingres/application/ingres/bin/dmfacp II
ingres 4177 0.0 0.7 322120 37260 pts/0 Sl 15:50 0:00 /ingres/application/ingres/bin/iidbms dbms (default) II
ingres 4335 0.0 0.0 59244 2768 pts/0 S 15:50 0:00 /ingres/application/ingres/bin/iijdbc II jdbcAnd here is the corresponding output from the 'ingstatus' command (corroborates the above, just less verbose):
> ingstatus
Ingres II name server (iigcn) - running
Ingres II recovery server (dmfrcp) - running
Ingres II DBMS server (iidbms) - 1 running
Ingres II Net server (iigcc) - not active
Ingres II Data Access server (iigcd) - not active
Ingres II JDBC server (iijdbc) - 1 running
Ingres II archiver process (dmfacp) - runningSo, given this starting point, here's what I had to do:
As the ingres user, we had created a 'cls' database via the createdb command. Then we used accessdb to create the 'cls' user account inside ingres. Then we loaded the sql schema via accessdb.
So now, I had a cls user account and a schema with tables, but I couldn't connect for the life of me over JDBC using Ingres 2006's provided jdbc driver (found at $II_SYSTEM/ingres/lib/edbc.jar).
It turns out this is because Ingres uses Operating System user accounts for logging in over tcp. So, this meant I had to create a cls user as root:
# adduser clsand gave it a suitable password:
# passwd cls(this OS level password is then used for the JDBC connection later on).
Now that there is an OS user called 'cls' - exactly the same as my previously created Ingres database - I then had to let ingres know about this os user account and password:
(as root):
# . /home/ingres/.ingIIbash
# mkvalidpwThis command compiles and installs a program called 'ingvalidpw' that is not is not included in the standard Ingres2006 installation. This allows you to validate if a password is valid against an operating system user account known to Ingres.
Once that's done, you'll have to restart Ingres (as root):
# /etc/init.d/ingresII restartTo validate that Ingres password checking works, you should see that the Ingres env var II_SHADOW_PWD is set to the location of that compiled ingvalidpw executable:
# su - ingres
> ingprenvIn the list that is generated, you should see the II_SHADOW_PWD var set.
Now, you can verify that the username and password you would use for JDBC for your user will work:
echo
| $II_SYSTEM/ingres/bin/ingvalidpw ; echo $? If you see any value other than 0 returned, then the username/password entered doesn't match the OS username/password. If you do see non-zero, then you can look in the $II_SYSTEM/ingres/files/iipwd/ingvalidpw.c file and see what the integer corresponds to find out what went wrong.
I then fired up DB Visualizer, pointed it to the edbc.jar file I specified earlier, and then used this url:
jdbc:edbc://:21071/ So, in my case it looked like this:
jdbc:edbc://localhost:21071/clsI clicked 'test connection' in DbVisualizer, and lo and behold! I was able to access all my tables!
I hope this is of use for someone - it took me close to 3 or 4 hours to get this working.
Here is the original Ingres forums thread that led me to my posting (you may need an Ingres account to access it, but its free):
http://opensource.ingres.com/projects/ingres/forum/30/121418044682?b_start:int=0#235464875124
Google Maps is Awesome
Ok, I know Google Maps has been out for a long time now, but I just wanted to proclaim yet again at how incredibly cool it is.
Here are some recent direction results:
10. Take exit 5 to Dunwoody/Sandy Springs - go 0.3 mi
11. Turn left at Abernathy Rd NE - go 0.2 mi
12. Bear right and head toward Peachtree Dunwoody Rd NE - go 177 ft
...
Go 177 feet! That's awesome. Ahhh...Google and GPS, what a nice combination
Delving deeper into languages – Kanji, Hiragana, Katakana, Romaji
So I wrote in my last post about my Utada Hikaru interest. Well, I really loved the songs, but there was one problem - I don't speak Japanese.
For those who don't know me, this kind of thing drives me crazy - If I find something really interesting, I have to learn as much about that subject as I possibly can. I'm like a sponge - I crave learning new things and soak it all up as much as I possibly can. I quite often go overboard and immerse myself in whatever the topic is. Sometimes its downright debilitating, and I just saturate myself.
So, really liking the songs wasn't good enough for me. I just couldn't leave well enough alone. I started google wandering.
I first found a web page that translated the Keep Tryin' lyrics to English, representing the Japanese characters as romaji. I thought this was awesome. So, what did I do? I memorized the song in a few hours so I could sing it from memory. In Japanese
Languages fascinate me. Mouth formations, syllabic pronunciations, vocal inflection, grammar - you name it, I'm interested. In my opinion, Linguistics is the perfect balance of left-brain and right-brain activity, and I'd like to think my brain is equally as balanced (I sing first tenor and enjoy numerous artistic hobbies to balance my logic-heavy career path). If I didn't love Computer Science so much, I know I would have done something professionally in languages, maybe becoming a UN translator or something.
Maybe that's why I enjoy CS so much. I love the algorithmic thought processes and problem solving that I experience when programming, but I get a semi-linguistic satisfaction as well - there are a lot of programming languages out there today as well, some as different from each other as spoken languages. But I say semi-linguistic satisfaction though, because although you learn different grammars, programming languages don't exercise right-brained speech functions.
So anyway, while memorizing the Romaji lyrics, it wasn't good enough to read it and just sing along. I very carefully watched the video over and over again, staying in sync with what I was reading, so I could watch exactly how Hikaru (everyone calls her Hikki) formed her mouth to pronounce the words. Because of this, and my past experience with learning languages and focusing on strict pronunciation, I would now venture to say that I could sing the song with enough proficiency to pass as a long-time or maybe even native speaker. Especially in a karaoke bar where a lot of the natives could be drunk
So, in my google wandering, I found a lot of sites/blogs talking about Hikki, how much they liked her, etc. Of course, most of these web sites were in Japanese, using Japanese characters. Well, that was one more thing I didn't understand, so, you guessed it - I went to learn about Japanese writing...
The Japanese writing system is composed of 3 character sets - Kanji, which is the older 'traditional' character set, and 2 simplified sets, Hirigana and Katakana, together called 'Kana' for short. In my research I found that there are a common core of 2,000 Kanji characters, half of which youth learn formally in school, but there are actually a complete total of around 48,000 individual Kanji characters. Japanese spend their whole lives learning and remembering the full Kanji set.
The reason why is that Kanji characters represent physical things and ideas - one character for the word 'tree', another character for the word 'bush', and yet another for the word 'forest'. This alphabet originates from the ancient Chinese character set, which is very similar even today and equally as complex.
Kanji and its Chinese parent are a complete opposites of Roman and Greek based languages, like English, which are entirely phonetic in nature: a very small set of characters are used together to represent sounds. Those sounds together form spoken words.
So, as might be expected, Japanese's other two 'simplified' character sets (Kana) are phonetic in nature, like English. Hiragana is used for representing standard Japanese words and phrases. Katakana is an entirely different alphabet primarily used in representing formal names and places, especially foreign names.
Romaji is not really a separate character set - its just a hacky name for using Roman letters to form Japanese sounds so westerners can learn to pronounce the language without learning new character sets. At the end of the day though, any serious student of Japanese is far better off learning Hiragana and Katakana while learning vocabulary to immediately start training their brains in a proper manner - this is how elementary school children in Japan learn. Romaji is actually counterproductive to someone learning Japanese, because it acts as a crutch and prevents the student from reaching the full potential of being fluent and literate in Japanese.
It is interesting to note though that computers in Japan expect Romaji input which the operating system then converts into the respective character sets. This is done for practicality - could you imagine what a keyboard would look like if it had to support all the different character sets?!? Today its very common for Kanji, Hiragana, Katakana and Romaji to be used in the same document. So, one must really learn all 4 to be perfectly literate.
So where did I end up after this maelstrom of searching?
I'm going to start Japanese classes later this month
Yeah, yeah, I know this is going overboard and I'm a little nuts, but why not? My brain craves a scholastic environment pretty often actually. But I don't want to have to go through full enrollment in a university again, so this is a great option for me. The classes are twice a week in the evenings and accomodate my work schedule perfectly.
I did this a couple of years ago for Spanish to continue what I learned while living in Spain. I'm now quasi-fluent in Spanish and feel pretty comfortable in that language. Unfortunately, my vocabulary has been decreasing since then...
Who knows...in a few months, I could be functionally fluent in Japanese too (which learning to speak is, in all honesty, much easier to learn than Western languages - its just the writing system is much harder).
All because of a few Utada Hikaru songs