Archive for the ‘Castle’ Category.

Javascript compression for Monorail

Last year, Hammett posted a blog entry on combining Javascript files into a single file using Monorail.  I was looking to enhance the code so that it would minify Javascript and CSS files on the fly, so I took his original code and enhanced it.  Alex Henderson was also looking for the same functionality, so he contributed to the patch as well.  You can download it here:  http://support.castleproject.org/projects/MR/issues/view/MR-ISSUE-457

The new component uses a .NET port of the Yahoo! UI Library Compressor that is available on Codeplex.  The component worked great, but they did not have a strongly signed version of the library release.  I made a request and they quickly turned out a release that same day, which was awesome response time.

You can now have all of your Javascript and CSS combined for you on the fly by using the component:

   1: #blockcomponent(BuildJS with "key=layout")
   2:     $jsBuilder.Add("Content/css/main.css")
   3:     $jsBuilder.Add("Content/css/someOther.css")
   4:     $jsBuilder.Add("Content/js/prototype.js")
   5:     $jsBuilder.Add("Content/js/someOther.js")
   6: #end

ActiveRecord Flush Control

There are a lot of times in your application where you will load a lot of entities in a single session (to display a lot of data on a page, build a report, etc).  Since you are not planning on doing a mutable operation on an entity, there is a big saving that you can get from not flushing the session.  To get an idea on everything that happens when you do a flush, check out the AbstractionFlushingEventListener from the NHibernate source.

If you are using explicit SessionScope’s, not flushing the session is trivial:

   1: using (new SessionScope(FlushAction.Never))
   2: {
   3:     repository.DoSomeReadOperation();
   4: }

This will execute the operation without flushing the session at the end.

Another way to control this behavior is by using an interceptor.  For example, if you are using the Castle’s Automated Transaction Facility, you probably already have a way of determining whether or not your methods do mutable operations by their transaction attributes.  You can then use an interceptor to control flushing:

   1: public class UnitOfWorkInterceptor : IInterceptor
   2: {
   3:     private readonly ITransactionManager transactionManager;
   4:
   5:     /// <summary>
   6:     /// Initializes a new instance of the <see cref="UnitOfWorkInterceptor"/> class.
   7:     /// </summary>
   8:     /// <param name="transactionManager">The transaction manager.</param>
   9:     public UnitOfWorkInterceptor(ITransactionManager transactionManager)
  10:     {
  11:         this.transactionManager = transactionManager;
  12:     }
  13:
  14:     #region Implementation of IInterceptor
  15:
  16:     /// <summary>
  17:     /// Intercepts the specified invocation.
  18:     /// </summary>
  19:     /// <param name="invocation">The invocation.</param>
  20:     public void Intercept(IInvocation invocation)
  21:     {
  22:         ITransaction transaction = transactionManager.CurrentTransaction;
  23:         FlushAction flushAction = transaction == null ? FlushAction.Never : FlushAction.Config;
  24:
  25:         ActiveRecordUnitOfWork.Before(flushAction);
  26:         invocation.Proceed();
  27:         ActiveRecordUnitOfWork.After();
  28:     }
  29:
  30:     #endregion
  31: }

Note that in this example, interceptor ordering is important.  If you register the unit of work interceptor before the transaction interceptor in the ATM facility, then transactionManager.CurrentTransaction will always return null.  (The ActiveRecordUnitOfWork class in the above example is just a facade for controlling the session in a thread local as discussed in this post http://erichauser.net/2008/08/06/activerecord-session-scope-and-wcf-redux/).  If you do not want to tie your flushing to transactions, then you can always create your own metadata and read that metadata at runtime in the interceptor.  The ATM facility code is a great example of how to inspect metadata on initialization and use that metadata in your interceptor.

Hopefully, this little trick will some increased performance for your queries that return a lot of results.

Validating method parameters with Castle Validator

Been pretty busy at work, so short post. 

I’ve added a facility in Castle contrib for validating method parameters using Castle Validator.  The goal is to eventually allow have this used for validate parameters in Monorail, but right now I’m using it to do input validation for web service parameters.  I wrote up a brief blurb on how to use it here: http://using.castleproject.org/display/Contrib/Castle.Facilities.MethodValidator.  Should be pretty self explanatory.

If anyone finds any issues, let me know.

Castle Validator Enhancements

I have contributed a couple of enhancements to Castle.Components.Validator that have been committed to the trunk.  Besides using attributes, validations can now be supplied in code using the [ValidateSelf] attribute:

Each of the above validations *could* be done by using an attribute and a custom validator, but expressing validations in code is much simpler for these types of one off validations. You can have as many methods decorated with [ValidateSelf] on an object you want as long as they have the above method signature (void return and one ErrorSummary parameter).  You can also specify the RunWhen and ExecutionOrder just like regular validators.

The second enhancement is the IValidationContributor interface. This allows you contribute to the validation of an object beyond the default validation. The interface is fairly simplistic:

You can extend AbstractValidationContributor so that you can perform initialization for a given type.  The SelfValidationContributor implements the logic for recognizing and executing the self validation feature above.  You can write custom contributors that can be injected into the DefaultValidatorRunner for things like retrieving validations from the container and invoking them on the object.

Enjoy!