Skip to main content

Posts

Showing posts from June, 2013

su and sudo in Spring Security applications

Long time ago I worked on a project that had a quite powerful feature. There were two roles: user and supervisor. Supervisor could change any document in the system in any way while users were much more limited to workflow constraints. When a normal user had some issue with the document currently being edited and stored in HTTP session, supervisor could step in, switch to special supervisor mode and bypass all constrains. Total freedom. Same computer, same keyboard, same HTTP session. Only special flag that supervisor could set by entering secret password. Once the supervisor was done, he or she could clear that flag and enable usual constraints again.

This feature worked well but it was poorly implemented. Availability of every single input field was dependent on that supervisor mode flag. Business methods were polluted in dozens of places with isSupervisorMode() check. And remember that if supervisor simply logged in using normal credentials, this mode was sort of implicit so secur…

Clojure macros for beginners

This article will guide you step-by-step (or even character-by-character) through the process of writing macros in Clojure. I will focus on fundamental macro characteristics while explaining what happens behind the scenes.

Imagine you are about to write an assertions library for Clojure, similar to FEST Assertions, ScalaTest assertions or Hamcrest. Of course there are such existing but this is just for educational purposes. What we essentially need first is a assert-equals function used like this:

(assert-equals (count (filter even? primes)) 1) Of course this is more than trivial:

(defn assert-equals [actual expected] (when-not (= actual expected) (throw (AssertionError. (str "Expected " expected " but was " actual))))) Quick test with incorrectly defined primes vector:

user=> (def primes [0 2 3 5 7 11]) #'user/primes user=> (assert-equals (count (filter even? primes)) 1) AssertionError Expected 1 but was …

Mapping enums done right with @Convert in JPA 2.1

If you ever worked with Java enums in JPA you are definitely aware of their limitations and traps. Using enum as a property of your @Entity is often very good choice, however JPA prior to 2.1 didn’t handle them very well. It gave you 2+1 choices:

@Enumerated(EnumType.ORDINAL) (default) will map enum values using Enum.ordinal(). Basically first enumerated value will be mapped to 0 in database column, second to 1, etc. This is very compact and works great to the point when you want to modify your enum. Removing or adding value in the middle or rearranging them will totally break existing records. Ouch! To make matters worse, unit and integration tests often work on clean database, so they won’t catch discrepancy in old data.

@Enumerated(EnumType.STRING) is much safer because it stores string representation of enum. You can now safely add new values and move them around. However renaming enum in Java code will still break existing records in DB. Even more important, such representation is…