AdSense Mobile Ad

Sunday, April 11, 2010

GlobalSAN iSCSI initiator for Mac OS/X v. 4 has been released

As I told you in another blog post, I'm using GlobalSAN iSCSI initiator for Mac OS/X to remotely connect to my time machine disk, which happens to be a ZFS volume managed by a Solaris host. Studio Network Solutions has just released GlobalSAN version 4: alongside some UI enhancements, this new version of the GlobalSAN software takes advantage of Snow Leopard characteristics. A screenshot of the new GlobalSAN UI is the following:


A word of warning: if you're using an older version of GlobalSAN (such as version 3), in order to successfully install this new version you've got to completely remove the older software by using the uninstaller which comes with the older package. If you no longer have it, please download it once more, uninstall it and then install the new version.


JSR 303 - Overview, part 3

Table of contents:
Introduction

The JSR 303 API

The JSR 303 API is made of the following functional subsets:
  • The bootstrap SPI
  • The validator API (which itself is made up the client API and the validation routine)
  • Important helper classes and interfaces used during the validation process such as the ConstraintViolation class and the message interpolators.
  • The constraint metadata request API

The API a JSR 303 will be most interested in is probably the validation API, which is the API used to trigger the validation process.

The bootstrap process: how to obtain a Validator

During the bootstrap process the service provider which implements the JSR 303 is discovered, configured and initialized. I won't cover the details of the bootstrapping API and if you're interested, you can check the specification. From an user standpoint, this API is important because it's the entry point to the validation API. After discovering and configuring all the available providers, you'll use the Validation class to obtain an instance of a ValidatorFactory.

ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();

The validator API

The validator API defines a series of interfaces which let an user programmatically trigger the validation process on a bean of a given class. The Validator interfaces is the following:

public interface Validator {
  <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups);
  <T> Set<ConstraintViolation<T>> validateProperty(T object, String propertyName, Class<?>... groups);
  <T> Set<ConstraintViolation<T>> validateValue(Class<T> beanType, String propertyName, Object value, Class<?>... groups);
  BeanDescriptor getConstraintsForClass(Class<?> clazz);
}

The first three methods of this interfaces trigger the validation process on an object of type T whose logic was described in Part 2. While the first method triggers the complete validation process, the other two methods can be used to validate just a property. The third is a convenience methods which trigger the validation of a bean's property if its value were the object passed as parameter. This way you'll be able to validate a property beforehand and, most importantly, without triggering any side effect of the property change or in the case the property were read only.

No matter which validate method you choose it will return a set of contraint violations for the type T. A constraint violation is a type which is part of the JSR 303 API whose purpose is describing the errors found during the validation process. Such a type will be described later on.

The last method of the Validator interface is used to retrieve a BeanDescriptor, which is a structure which describes the constraints applied to a specific class' instances. You usually won't use this method in your daily life with a JSR 303 implementation unless you are building sophisticated logic which has to rely to such information at runtime.

Also, you won't be using the validator API directly when using API which can automatically validate beans. Such APIs are, for example, JPA and JSF with CDI beans and those are the use cases I'll be focusing on.

Defining a constraint

To define a constraint the first thing you need to do is defining the constraint annotation you're going to use. For example, let's define an annotation to validate a String instance representing an email address.

package es.reacts.validators;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;

/**
 *
 * @author http://thegreyblog.blogspot.com/
 */
@Documented
@Constraint(validatedBy = EmailValidator.class)
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface EmailAddress {

    String message() default "{email.invalid}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

It's important to note the following:
  • The @Constraint annotation is used to declare that the following annotation will be used as a constraint annotation. The validatedBy attribute of the @Constraint annotation is used to declare the class of the associated constraint validator, in this case the class EmailValidator.
  • The standard @Target annotation is used to indicate which kind of element type this annotation will be used with. A JSR 303 compliant implementation will let you define and use constraint for the FIELD, METHOD and TYPE element types. In this example an email address is represented by a String instance so that TYPE is not specified in the constraint definition. If we were to define a class to represent an email address, we could define a constraint and a validator to annotate our class.
  • The required RUNTIME @Retention policy is necessary so that the JSR 303 implementation be able to read validation metadata at runtime.
  • The message() element is used to return a message in case of a validation error. The JSR 303 supports a flexible mechanism to define messages and this example uses the standard "{...}" notation to internationalize our messages in a properties resource bundle.

Defining a constraint validator

Constraint validators are instances of the ConstraintValidator<T, V> class, being T the type of the constraint and V the type of the validated objects. In this case, T is EmailAddress and V is String so that the skeleton of our validator will be:

package es.reacts.validators;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

/**
 *
 * @author http://thegreyblog.blogspot.com/
 */
public class EmailValidator implements ConstraintValidator<EmailAddress, String> {

    public void initialize(EmailAddress constraintAnnotation) {
    
    }

    public boolean isValid(String value, ConstraintValidatorContext context) {

    }
}

The initialize method is used to initialize the validator during the validation process: if you're defining attributes in your constraint, the initialize method body will scan the constraint passed as a parameter and save it in its state. The isValid method will validate the current object. Since our @EmailAddress constraint contains no attributes, the validator will only need to implement the validation logic in the isValid method and, for the sake of the current example, we'll use a standard regular expression to check if the current String instance represents a valid email address:

package es.reacts.validators;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

/**
 *
 * @author http://thegreyblog.blogspot.com/
 */
public class EmailValidator implements ConstraintValidator<EmailAddress, String> {

  private static final Pattern emailPattern = Pattern.compile("[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?");

    public void initialize(EmailAddress constraintAnnotation) {
    
    }

    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (value == null) {
            return true;
        }

        Matcher match = emailPattern.matcher(value.toLowerCase());

        return match.matches();
    }
}

Since Pattern instances are thread-safe, our EmailValidator will take advantage of it by caching the regular expression used to validate email addresses. The isValid method simply checks that the String instance is not null (in which case the email address is considered to be valid, as suggested by the JSR 303 spec), and uses a Matcher instance to match it against our pattern.

Although a bit primitive, this is a sound constraint validator and you can take advantage of it immediately by annotating the fields of your beans. In my case, for example, I'm using it in a JPA entity and in a CDI bean which backs a JSF page in which users are submitting their email address. Without additional code, I'm taking advantage of JSF, JPA and JSR-303 to enforce a validation policy on both the web channel and the persistence layer of my Java EE 6 application.









Tuesday, March 9, 2010

Who likes Mondays?

I do *not*. But today, I like them less than usual.

First: since two days, Saturday and Sunday, are more than enough to upset my biological clock, returning to the weekly routine is pretty hard for me. I try to tame my nocturnal instincts but constraining that little Count Dracula inside me is harder and harder.

Second: winter is not exactly my favorite season to go out of the bed, undress and have a shower. Particularly when the average outdoor temperature is about -5 degree Celsius and the memory of the warmth beneath the blankets is still vivid inside my mind. Despite that, and after the first coffee, the week has begun and Sunday just seems so far away.

Monday is the day of "good intentions": an entire working week is there before you, and it's the perfect day to schedule executive meetings.

So simple were my plans and, for a time, I wasn't late either. But I'd reckoned without my... clutch. Yep. The gear lever was stuck and the clutch pedal seemed to offer few or no resistance. Bad news. I called a crane, waited for it in a chilly and busy street of Madrid. It finally took me to the nearest garage just to discover that your bank account will shortly be drained. Ah, I almost forget! The icing on the cake: I never arrived to that meeting.

Who likes Mondays? I don't know. But I certainly do not.

Sunday, March 7, 2010

Is Safari leaking memory?

I was working at some Java EE application with my MacBook while I realized that I was running out of memory. Strange, isn't it? I was just running the following:

Not so much for a MacBook equipped with a 4GB of RAM to experience a memory shortage. When I opened the Activity Monitor I was shocked to discover that my MacBook experience was jeopardized by the Safari web browser.

Since then, I'm monitoring Safari resource consumption. I've also been searching for information about Safari leaks and it seems that since a long time there are "outstanding" memory leaks which, apparently, haven't been corrected so far.

After using Safari some time that's what I see:


Although I'm reasonably happy with Safari speed, almost one gigabyte is simply too much for some newspaper reading and a maximum of a couple of tabs open. I'm seriously thinking about switching to Google Chrome.


Apple Mac OS X' "Safe Sleep"

Safe sleep is no new kid on the block: at least as far as it concerns major operating systems such as Microsoft Windows, GNU/Linux or even Sun Microsystems' Solaris: never heard about Windows' hibernation or Solaris suspend and resume? I bet you have.

Apple has christened this functionality as "Safe Sleep" in its flagship OS, Mac OS/X. What's most "astonishing" about "Safe Sleep" is that you're not going to find any reference to it in your Finder menu or even in your System Preferences panes. You'll only find references to a "generic" sleep function.

Safe Sleep

During safe sleep the system will persist to disk all of the machine state (such as RAM's) so that it could be restored in the case all of the power is lost, for example during battery replacement. Under normal conditions, you'll hardly notice a resume from disk since the laptop battery power will maintain data on RAM even when the battery power has run real low. That's why during battery calibration Apple suggests to let the laptop sleep at least 5 hours. The next time you calibrate your battery, you should notice a slightly different boot screen when your laptop wakes up and reads its state from disk.

How to force a safe sleep?

Despite other implementations of a similar technology, Mac OS/X does not provide a way to force a system hibernation simply because every time your computer goes to sleep, it will persist its state to disk. This way you can let your battery discharge without worrying about your data. You could remove it, too. Next boot, it would simply read state from disk and restore it.

That's counterintuitive for who's accustomed to other OS where such a process should be explicitly triggered by the user. When using an Apple laptop, simply don't worry. You'll quickly get used to never, or very rarely, shutting down your system.

Handling your laptop while sleeping

When your laptop is sleeping, most of the hardware components will be completely off. That's the case of the hard disk: if you're laptop is equipped with a good old rotating hard drives, as soon as the computer state has been persisted, the disks will be switched off. The only evidence about this is the white led in front of your laptop: it will switch from a solid on state to a blinking state when the drives have been switched off.

Until complete disk shutdown, handle your laptop with care.

Once the laptop is sleeping, you can safely handle it as if it had been completely shut down. The real difference between a sleeping and a shut down laptop is RAM electrical state. As far as it concerns mechanical parts, there will be no difference at all. Hence:

No need to worry about hard disk heads landing on the platters. Put your sleeping laptop into your bag and safely transport it.

No need to emphasize the obvious, but I noticed a bit of misinformation about how safe sleep works and about the dos and don'ts. Indeed, safe sleep is the best way to forget about quit all applications and shut down. Reboots won't ever be faster.