<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8828114559044739709</id><updated>2012-01-30T11:01:28.442-08:00</updated><title type='text'>Continuous Investigation</title><subtitle type='html'>Thoughts, articles and observations on modern software trends and ideas</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://grzegorzborkowski.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8828114559044739709/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://grzegorzborkowski.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Grzegorz Borkowski</name><uri>http://www.blogger.com/profile/16063009050017401077</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_Iu6FMYlWXN4/SeD5_rszBpI/AAAAAAAAAkQ/17qtFY-14Ag/S220/DSC_4313_1.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8828114559044739709.post-6696558122327337298</id><published>2010-08-17T15:58:00.000-07:00</published><updated>2010-08-17T16:20:12.606-07:00</updated><title type='text'>"Spring Security 3" by Packt Publishing - review</title><content type='html'>&lt;p&gt;I've just finished reading &lt;a href="https://www.packtpub.com/spring-security-3/book"&gt;Spring Security 3&lt;/a&gt;, and I may honestly recommend it to any Spring Security user. Peter Mularien's book is well written and easy to follow. I can't say it's the best Spring Security book on the market - simply because it is the only one... so there is no comparison to make. But even without it, it is highly recommended and worth its price.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The book is especially important, because Spring Security (SS - for short) documentation is not so user friendly as, for example, Spring Framework documentation. Spring Framework has one of the best documentation (I mean reference manual here) of open source project I ever see. Spring Security also has such manual, which is not that bad, and is definitely a good start point (when I started with SS, there was no other point of reference, so it had to suffice to start) - but it can't be compared to Spring Framework documentation. Because of this, any additional high-quality materials on SS are valuable. The Mularien's book is definitely such material.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The book covers all important topics related to Spring Security: authentication and authorization mechanisms, namespace and bean-based configuration, additional services (e.g. remember me, session management, custom filters), advances topics, like ACLs, and integration features (OpenID, CAS, etc). Really broad spectrum of SS applications is covered there. I really like the approach of presenting logic flow and classes relationships on diagrams - in case of such complicated  beast as Spring Security is, they are really necessary to get a clear picture. Also, I really liked the fact that author points the user to the places in code or javadocs where additional or comprehensive information may be found - for example he put a note: "Methods and pseudo-properties for SpEL access expressions are declared by the public methods provided by the WebSecuirtyExpressionRoot class, and its superclasses" - very practical link to the right place (in Spring Security it is often not easy to find the exact class, which JavaDoc contains relevant information - that's why such information is valuable). The book also warns about some peculiarities of SS naming (e.g. interface Authentication is implemented by classes XxxAuthenticationToken - really strange and not intuitive), so it's good to be warned, it's then easier to remember such facts and not get lost.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;To make this review fair, I have to also point some shortcomings.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;First - some things which are not directly related to Spring Security, and because of this don't have to be described in this book, but are so closely related to the topic that I believe they deserve a bit more focus. For example, author mentions some typical security flaws and attack, but doesn't describe them (only points to external resources). I understand it's a book about Spring Security, not general web security. But in such context adding 3 more pages describing few most important threats, mistakes and attacks (SQL injection, XSS, CSRF) would be nice, I think. For sure the book will be read also by some beginners, who may not be aware of those attacks. And two other small missing things. The book described hypothetical security audit results: audit identified that user passwords were stored in clear text in database - and then we can read how to fix it. However, it doesn't mention the typical security problem: storing database password in clear text in spring security configuration file (e.g. if you use standalone DBCP bean) - which would be probably identified by such audit too. Obviously, Spring Security (nor Spring Framework, unfortunately) doesn't have any answer to this, and that's why it is not in the book. Still, if we talk about securing web application, I expected this problem to be at least mentioned there. And, similarly, it would be nice to have some information about protecting from brute force attack on passwords in database - again, Spring Security doesn't have any built-in tools for dealing with it, but it is worth mentioning at least (for example, how we can use Spring Security events in order to try to identify such attacks).&lt;/p&gt;&lt;br /&gt;&lt;p&gt;For me, the biggest missing point of the book is the lack of description of using UserDetails with mutable objects, such as JPA @Entities. This used to be one of the most unclear points in Spring Security - documentation in the past recommended using immutable objects as UserDetails implementations, but most of applications used some sort of ORM, like Hibernate, with mutable entities. The documentation has been actually fixed - now UserDetails javadoc clearly says that immutability is not required. However, taking into account that it is so common setup, and it used to be unclear in context of UserDetails, and caused many questions on SS forums, I expected to have example with such setup in this book - with info how it influences user caches etc (UserCache is not mentioned at all in the book, if I remember correctly).&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Few other points - remember me services are described very good, but then, when second type of remember me is introduces, author says that, "...something that you may have noticed by now...", basic Remember Me tokens will not survive server restart. I rewound back to Remember Me service description and tried hard to find out why it won't - but couldn't find any clue. So something is missing here (or I didn't read carefully enough). Next: on page 143, author says "be aware that it is strongly encouraged to declare AOP rules on interfaces, and not on implementation classes". Well, this is embarrassing. I always though exactly opposite. See the citation from Spring Framework reference docs: "Spring recommends that you only annotate concrete classes (and methods of concrete classes) with the @Transactional annotation, as opposed to annotating interfaces." (and @Transactional is definitely kind of AOP rule). Next weak point: in section devoted to session-fixation attack protection, description of the attack itself is very unclear, and doesn't touch real problem I think. The book says "if hacker steals your session, he can only use it until you log in, because session-fixation protection will change your session identifier then". But if he stole my session before I logged in, he can do it again after, so what's this protection about? For me, the real session fixation attack is based on sending someone a link with session ID in it. So in fact the hacker don't steal the session, instead he "suggests" you the session. (Maybe this is not the only possible case, but the most popular at least.) Then this protection makes sense. But you probably won't figure it out from the book.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;All in all, despite those small shortcomings, the book is really good, and highly recommended to everybody who starts using Spring Security, or already knows it, but doesn't feel Spring Security expert yet (also experts can learn some new things from this book, for example bout integration with external authentication systems). Because of those small shortcomings, I wouldn't probably give it full 5 stars, but 4.5 is a fair note.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8828114559044739709-6696558122327337298?l=grzegorzborkowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grzegorzborkowski.blogspot.com/feeds/6696558122327337298/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8828114559044739709&amp;postID=6696558122327337298' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8828114559044739709/posts/default/6696558122327337298'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8828114559044739709/posts/default/6696558122327337298'/><link rel='alternate' type='text/html' href='http://grzegorzborkowski.blogspot.com/2010/08/spring-security-3-by-packt-review.html' title='&quot;Spring Security 3&quot; by Packt Publishing - review'/><author><name>Grzegorz Borkowski</name><uri>http://www.blogger.com/profile/16063009050017401077</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_Iu6FMYlWXN4/SeD5_rszBpI/AAAAAAAAAkQ/17qtFY-14Ag/S220/DSC_4313_1.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8828114559044739709.post-1960108742686515250</id><published>2010-07-21T11:39:00.000-07:00</published><updated>2010-07-21T13:03:08.708-07:00</updated><title type='text'>"Spring Security 3" published by Packt</title><content type='html'>&lt;p&gt;Recently (well, actually more than a year) I had not much time for updating this blog - this is because we started our own business and own project, which is very challenging and consumes 100% of my precious time.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;This month, however, I was contacted by Packt Publishing, as &lt;a href="https://www.packtpub.com/spring-security-3/book"&gt;they just published the book on Spring Security 3&lt;/a&gt; and asked me if I would like to get a copy of this book, in order to write a review. From what it seems (at least looking at Amazon), it's the very first book on the market dedicated to Spring Security (there are books on Spring, containing some chapters about Spring Security, but it looks like there was no book on Spring Security itself). Obviously, I was interested, and just today I found the book in my mailbox. First impressions are very good: for example, fast scanning of the book reveals many UML and pseudo-UML diagrams, presenting decision flows and Spring Security classes hierarchies - this is great, personally I believe that learning this framework without such diagrams is hardly possible. The plethora of Spring Security classes, interfaces, and relations between them, makes them really hard to follow - that's why such diagrams are so important.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So, I start to read the book, and you can expect a new post with the book review soon.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8828114559044739709-1960108742686515250?l=grzegorzborkowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grzegorzborkowski.blogspot.com/feeds/1960108742686515250/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8828114559044739709&amp;postID=1960108742686515250' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8828114559044739709/posts/default/1960108742686515250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8828114559044739709/posts/default/1960108742686515250'/><link rel='alternate' type='text/html' href='http://grzegorzborkowski.blogspot.com/2010/07/spring-security-3-published-by-packt.html' title='&quot;Spring Security 3&quot; published by Packt'/><author><name>Grzegorz Borkowski</name><uri>http://www.blogger.com/profile/16063009050017401077</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_Iu6FMYlWXN4/SeD5_rszBpI/AAAAAAAAAkQ/17qtFY-14Ag/S220/DSC_4313_1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8828114559044739709.post-7279547126076914472</id><published>2009-05-07T07:10:00.000-07:00</published><updated>2009-05-08T15:06:38.130-07:00</updated><title type='text'>Spring Framework 3.0 M3 and REST enhancements</title><content type='html'>&lt;p&gt;In my &lt;a href="http://grzegorzborkowski.blogspot.com/2009/03/test-drive-of-spring-30-m2-rest-support.html"&gt;previous blog post&lt;/a&gt;, I described how Spring 3.0 Milestone 2 can be applied in real REST web service project, and I enumerated several limitations and problems. M3 is out now. What has changed then?&lt;/p&gt;&lt;br /&gt;&lt;p&gt;M3 contains several enhancements over M2, addressing my postulations:&lt;/p&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Fixed URL mapping with &lt;code&gt;@RequestMapping&lt;/code&gt; annotations: type-level and method-level finally work together in the logical manner, allowing for easy writing of one controller per one REST resource (&lt;a href="http://jira.springframework.org/browse/SPR-5631"&gt;SPR-5631&lt;/a&gt;). I also noticed that at container startup, all the resolved mappings are printed to the log at INFO level - that's nice too.&lt;/li&gt;&lt;br /&gt;&lt;li&gt; Trailing slashes insensitive mapping (&lt;a href="http://jira.springframework.org/browse/SPR-5636"&gt;SPR-5636&lt;/a&gt;)&lt;/li&gt;&lt;br /&gt;&lt;li&gt; Input data (body) conversion - easy access to request body as controller method param, converter for form encoded data (and other types) (&lt;a href="http://jira.springframework.org/browse/SPR-5409"&gt;SPR-5409&lt;/a&gt;)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Type conversion error for @PathVariable annotated params returns code 400, not 500 (&lt;a href="http://jira.springframework.org/browse/SPR-5622"&gt;SPR-5622&lt;/a&gt;)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Custom processing of object returned from controller method (&lt;a href="http://jira.springframework.org/browse/SPR-5426"&gt;SPR-5426&lt;/a&gt;)&lt;/li&gt;&lt;br /&gt;&lt;li&gt; Header-based request matching (&lt;a href="http://jira.springframework.org/browse/SPR-5690"&gt;SPR-5690&lt;/a&gt;)&lt;/li&gt;&lt;br /&gt;&lt;li&gt; Flexible exception handling (&lt;a href="http://jira.springframework.org/browse/SPR-5622"&gt;SPR-5622&lt;/a&gt; and related)&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;p&gt;I haven't yet verified in practice the last three of them, but overall it looks pretty good, and the picture is now much more complete than in case of M2.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Small bugs that I've found:&lt;/p&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Exception when method-level annotation starts with slash (&lt;a href="http://jira.springframework.org/browse/SPR-5631"&gt;SPR-5631&lt;/a&gt;, &lt;a href="http://jira.springframework.org/browse/SPR-5726"&gt;SPR-5726&lt;/a&gt;) - should be already fixed&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Code 404 returned, when it should be 405 (&lt;a href="http://jira.springframework.org/browse/SPR-4927"&gt;SPR-4927&lt;/a&gt;)&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;One thing that worries me is the sentence from M3 documentation: &lt;q&gt;Available separately is the JacksonJsonView included as part of the Spring JavaScript project.&lt;/q&gt; I thought it was supposed to be moved to core REST packages? As I said earlier, JSON is not a JavaScript. It's a data exchange format you can use to talk Java to .NET, with no JavaScript involved. So having dependency on JavaScript project makes no sense.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I really like the idea of FormHttpMessageConverter, which can bind body data to MultiValueMap:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;@RequestMapping(method=PUT, value="{projectName}")&lt;br /&gt;public HttpResponse createOrUpdate(@PathVariable String projectName,&lt;br /&gt;                                   @RequestBody MultiValueMap&amp;lt;String,String&amp;gt; newValues)&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;It solves (at least partially) problem of servlet &lt;code&gt;getParameter&lt;/code&gt; method used with PUT (see my post for REST in M2, and also &lt;a href="http://jira.springframework.org/browse/SPR-5628"&gt;SPR-5628&lt;/a&gt;). Actually, &lt;code&gt;FormHttpMessageConverter&lt;/code&gt; calls the &lt;code&gt;getInputStream&lt;/code&gt; method on &lt;code&gt;ServletResponse&lt;/code&gt;, so after it is called by the framework, the attempt to call &lt;code&gt;getParameter&lt;/code&gt; inside controller method will return &lt;code&gt;null&lt;/code&gt; not only for PUT requests, but also for POST, because body was already parsed into &lt;code&gt;MultiValueMap&lt;/code&gt; (this behavior is valid according to servlet API).  But having the map of parameters, there is no need for calling &lt;code&gt;getParameter&lt;/code&gt; again.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I have only one problem with &lt;code&gt;MultiValueMap&lt;/code&gt;. Previously, I parsed manually the form data from body into &lt;code&gt;PropertyValues&lt;/code&gt; object, which was then passed to Spring's &lt;code&gt;DataBinder&lt;/code&gt; for updating the model entity class. Now, in M3, the form data is parsed by Spring and I get &lt;code&gt;MultiValueMap&amp;lt;String,String&amp;gt;&lt;/code&gt; directly. That's nice, but how to pass it to &lt;code&gt;DataBinder&lt;/code&gt;? There is a &lt;code&gt;bind(Map)&lt;/code&gt; method in &lt;code&gt;DataBinder&lt;/code&gt;, but the problem is that &lt;code&gt;MultiValueMap&amp;lt;String,String&amp;gt;&lt;/code&gt; at the very bottom is actually the &lt;code&gt;Map&amp;lt;String,List&amp;lt;String&amp;gt;&amp;gt;&lt;/code&gt;. Now if I pass it to &lt;code&gt;bind&lt;/code&gt; method directly, I get many binding errors saying "cannot convert List&amp;lt;String&amp;gt; to String", because model class has fields of type &lt;code&gt;String&lt;/code&gt;, and the &lt;code&gt;MultiValueMap&lt;/code&gt; keeps it as one-element string lists. The simplest solution would be to extend &lt;code&gt;MultiValueMap&lt;/code&gt; interface with one method, called e.g. 'asFlatMap()' or so, that would return either copy or the live view of the &lt;code&gt;MultiValueMap&amp;lt;K,V&amp;gt;&lt;/code&gt; as &lt;code&gt;Map&amp;lt;K,Object&amp;gt;&lt;/code&gt; with all values which are single-element lists replaced by the element itself (so &lt;code&gt;Object&lt;/code&gt; is actually either &lt;code&gt;V&lt;/code&gt; or &lt;code&gt;List&amp;lt;V&amp;gt;&lt;/code&gt;). This way I could pass the map returned by this method to the DataBinder easily. The code below shows the conversion:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Map&amp;lt;String,Object&gt; asFlatMap(MultiValueMap&amp;lt;String,String&gt; map) {&lt;br /&gt;        Map&amp;lt;String,Object&gt; convertedMap = new LinkedHashMap&amp;lt;String,Object&gt;();&lt;br /&gt;        for (Entry&amp;lt;String,List&amp;lt;String&gt;&gt; entry : map.entrySet()) {&lt;br /&gt;            if (entry.getValue().size() == 1) {&lt;br /&gt;                convertedMap.put(entry.getKey(), entry.getValue().get(0));&lt;br /&gt;            } else {&lt;br /&gt;                convertedMap.put(entry.getKey(), entry.getValue());&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        return convertedMap;&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;I've created a &lt;a href="http://jira.springframework.org/browse/SPR-5733"&gt;SPR-5733&lt;/a&gt; issue for this. AFAIK, Spring binding is going to be refactored in RC1, so perhaps it can be aligned with it too.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8828114559044739709-7279547126076914472?l=grzegorzborkowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grzegorzborkowski.blogspot.com/feeds/7279547126076914472/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8828114559044739709&amp;postID=7279547126076914472' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8828114559044739709/posts/default/7279547126076914472'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8828114559044739709/posts/default/7279547126076914472'/><link rel='alternate' type='text/html' href='http://grzegorzborkowski.blogspot.com/2009/05/spring-framework-30-m3-and-rest.html' title='Spring Framework 3.0 M3 and REST enhancements'/><author><name>Grzegorz Borkowski</name><uri>http://www.blogger.com/profile/16063009050017401077</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_Iu6FMYlWXN4/SeD5_rszBpI/AAAAAAAAAkQ/17qtFY-14Ag/S220/DSC_4313_1.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8828114559044739709.post-1202308205334563165</id><published>2009-04-25T10:14:00.000-07:00</published><updated>2009-04-25T13:53:33.177-07:00</updated><title type='text'>NullPointered</title><content type='html'>&lt;p&gt;As I mentioned &lt;a href="http://grzegorzborkowski.blogspot.com/2009/04/fortunately-xslt-is-dead-in-web.html"&gt;in one of the previous posts&lt;/a&gt;, I have been outsourced to some project, which uses a home-made, rather naive web framework. This framework has something in common with Struts: it has an abstract &lt;code&gt;Action&lt;/code&gt; class, that must be implemented by any action in the system. The main method from this class, that must be implemented by concrete actions, has signature of this shape:&lt;p&gt;&lt;br /&gt;&lt;pre&gt;abstract protected Result perform(...) throws ProcessDataException, NullPointerException;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;So, how would you implement the "Hello World!" example in this framework? I guess, more or less this way:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;public Result perform(...) throws ProcessDataException, NullPointerException {&lt;br /&gt;   throw new NullPointerException("Hello World!");&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Well, this looks like a good candidate for &lt;a href="http://thedailywtf.com/"&gt;The Daily WTF&lt;/a&gt; :)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8828114559044739709-1202308205334563165?l=grzegorzborkowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grzegorzborkowski.blogspot.com/feeds/1202308205334563165/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8828114559044739709&amp;postID=1202308205334563165' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8828114559044739709/posts/default/1202308205334563165'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8828114559044739709/posts/default/1202308205334563165'/><link rel='alternate' type='text/html' href='http://grzegorzborkowski.blogspot.com/2009/04/nullpointered.html' title='NullPointered'/><author><name>Grzegorz Borkowski</name><uri>http://www.blogger.com/profile/16063009050017401077</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_Iu6FMYlWXN4/SeD5_rszBpI/AAAAAAAAAkQ/17qtFY-14Ag/S220/DSC_4313_1.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8828114559044739709.post-2488441325030858548</id><published>2009-04-15T04:39:00.000-07:00</published><updated>2010-09-23T12:38:52.273-07:00</updated><title type='text'>Ext Core - a new weapon in your arsenal</title><content type='html'>&lt;p&gt;Recently, the Ext-JS team &lt;a href="http://extjs.com/blog/2009/04/04/ext-core-30-beta-released/"&gt;announced&lt;/a&gt; introduction of the new product, Ext Core. At this moment it is in the beta stage, but I guess we should see the final version soon. The good news is that Ext Core will have free MIT license for any use, as opposed to Ext-JS, which is not free for commercial use.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Why is this announcement so important? Well, the Ext-JS is excellent JavaScript library, so if you want to build the really big pure-javascript client, Ext-JS is the best choice. However, such clients are still not that popular, and the server-side frameworks remain mainstream. So what most developers do is enhancing the server-side-generated web pages with javascript addons. The low-level DOM manipulation libraries, like Prototype or JQuery are perfect for this purpose. They are lightweight and free, and that's why they got so popular. Obviously, you could use Ext-JS for the same purpose, because it contains the low-level tools capable of doing the same thing. But the whole power of Ext-JS, the component-based UI, wouldn't be used at all. So would you pay for Ext-JS with features you won't use, if the JQuery can do it for free? Obviously, not. This I believe was an important barrier for Ext-JS adoption.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Now, from what I understand, beginning from from version 3, Ext will be split into two distinct layers (and products). Ext Core will contain the low-level code, for dealing with DOM elements and with API concentrated around &lt;code&gt;Ext.Element&lt;/code&gt; class, while Ext-JS will contain full Ext distribution: bundled Ext Core plus all the UI widgets, tools and managers, with API concentrated around &lt;code&gt;Ext.Component&lt;/code&gt;.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;This means that Ext Core becomes a viable alternative for jQuery: it's also lightweight and free, and has fantastic community support on Ext-JS forum (I must say I've never met the second forum where the questions receive so fast responses, in spite of traffic being really high). I haven't done the comparison of Ext Core vs JQuery in terms of API: which library is more powerful and/or simpler. Many concepts are similar, even if they are named or implemented a bit different. In fact, I haven't used much of the low-level features of Ext-JS before, because when you use Ext components, it is usually not needed to bother with DOM-level details. The Ext Core is at beta stage, so probably API can evolve a bit yet. (For example, it's strange for me that there is no simple method in &lt;code&gt;Ext.Element&lt;/code&gt; to get attribute value of the element; there is only namespaced-version &lt;code&gt;getAttributeNS(namespace, name)&lt;/code&gt;, but why there is no &lt;code&gt;getAttribute(name)&lt;/code&gt;? How often do you come across namespaced attributes in HTML pages?)&lt;/p&gt;&lt;br /&gt;&lt;p&gt;One big advantage of Ext-JS is documentation. I've always found the Ext-JS API documentation more clear and complete than that of jQuery. Ext Core, I hope, will not be worse in this area. At this moment there is an &lt;a href="http://extjs.com/products/extcore/docs/"&gt;API documentation&lt;/a&gt; available, but it also looks like "beta" version, because there is no details section (like in standard Ext-JS docs), and method links point directly to the source, instead of to the details section. That's good idea to link to the source, but I shouldn't be forced to go to the source every time I want to check the full method description. I hope this will be fixed before final release. There is also &lt;a href="http://extjs.com/products/extcore/manual/"&gt;the Ext Core manual&lt;/a&gt; available, which looks very promising, even if it is also not finished yet (there are typos and errors, and some sections are only sketched). One thing is very interesting: authors of the manual teach you the Ext Core with aid of FireBug: there are plenty of examples based on FireBug. That's really cool. On the other hand, the section describing the effects is poor: you see red rectangle and the code which is supposed to do some effects on it (fade, switch off, ...), but you can't execute the code and see it in action. Quite annoying. But I hope it will be also fixed before Ext Core goes final.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Ext Core being free, lightweight and high-quality, should attract many developers. And obviously, in the longer term those people who started to use Ext Core and got to know it well, will be more eager to do one step further and switch to the "full version" of Ext-JS. Things are getting more and more interesting in JavaScript frameworks circle. With the new player, I guess we'll watch some significant changes in JavaScript libraries usage statistics soon.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8828114559044739709-2488441325030858548?l=grzegorzborkowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grzegorzborkowski.blogspot.com/feeds/2488441325030858548/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8828114559044739709&amp;postID=2488441325030858548' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8828114559044739709/posts/default/2488441325030858548'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8828114559044739709/posts/default/2488441325030858548'/><link rel='alternate' type='text/html' href='http://grzegorzborkowski.blogspot.com/2009/04/ext-core-new-weapon-in-your-arsenal.html' title='Ext Core - a new weapon in your arsenal'/><author><name>Grzegorz Borkowski</name><uri>http://www.blogger.com/profile/16063009050017401077</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_Iu6FMYlWXN4/SeD5_rszBpI/AAAAAAAAAkQ/17qtFY-14Ag/S220/DSC_4313_1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8828114559044739709.post-2373529928291328399</id><published>2009-04-09T00:38:00.000-07:00</published><updated>2009-04-25T10:25:15.723-07:00</updated><title type='text'>Fortunately, XSLT is dead (in web frameworks)</title><content type='html'>&lt;p&gt;Several years ago there was a trend in Java web frameworks to use XML processing as a foundation for the framework logic: take the data from database and present it as XML document (either convert it from relational data, or use XML capable database), and transform it to HTML using XSLT. There were some books written about it, and some frameworks created (like Cocoon). After some time the hype started to decline, and currently virtually no modern web framework apply this approach, I think.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Actually I've never used it on myself, but I liked the idea at that time. It seemed to be clear and powerful. Funny that only now I have a chance to check how it works in practice. And at least now I know why this approach failed.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;For two weeks, I'm outsourced to help some company in their web project. They use their own, home-made web framework for this, to talk to their own, home-made document-repository system. Unfortunately, both seemed to be buggy and unstable, though they say that's not the first project they use them in (I can't believe it's true, really). I guess they would be better off using standard Java Content Repository (JSR-170) for implementing documents repository, and some modern web framework instead of their own home-grown one. If they insisted on XML/XSLT transformations, they could use Cocoon. At least there would be more documentation available, and it would be well-tested and stable. But ok, that's not the first company that suffers from NIH syndrome, or guys are simply too lazy or overloaded to look around for other stuff. The interesting point is: how the XML-based processing works in practice? The short answer is: very poor. And the weakest link in the whole chain is XSLT.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;XSLT bloat&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;I won't dare to say that XSLT is worthless - perhaps in some contexts it can be useful, especially for transforming one document tree into another (valid) document tree, i.e. from DOM to DOM. XSLT gives you guarantee that input and output documents will be valid XML - this is crucial e.g. in SOA applications, transforming one document into other documents, to be processed by machines. (X)HTML is a document tree too, at least formally, but from the point of view of web browser to have perfectly valid XHTML is good, but not crucial, and from the point of view of web designer or developer the DOM behind it doesn't matter at all, and making the template valid XML is of no importance. For dynamic generation of HTML pages in most cases it is much easier if you treat the HTML code as a unformatted text, and make a web page template by embedding some special processing directives in such text. This approach was applied by JSP (first with scriptlets, and than with JSTL), Velocity, FreeMarker, and other  technologies. Neither of those technologies use the strict XML as template. On the opposite side we have JSPX (JSP using strict XML) - it never caught on and I guess many Java developers have never met it; and XSLT.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I've used a lot of JSPs with JSTL. It wasn't perfect, but it worked. Now I have to do the same with XSLT and it's a nightmare. Things that took me half an hour to do with JSP take several hours in XSLT. This is a list of things I hate the most in XSLT:&lt;/p&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Conditional arguments. For example: how to hide the row in table (using different CSS style), based on some &lt;em&gt;CONDITION&lt;/em&gt;, with XSLT? See:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;tr&gt;&lt;br /&gt;    &amp;lt;xsl:attribute name="style"&gt;&lt;br /&gt;        &amp;lt;xsl:choose&gt;&lt;br /&gt;          &amp;lt;xsl:when test="CONDITION"&gt;&lt;br /&gt;            &amp;lt;xsl:value-of select="'visibility: visible'"&gt;&lt;br /&gt;          &amp;lt;/xsl:when&gt;&lt;br /&gt;          &amp;lt;xsl:otherwise&gt;&lt;br /&gt;            &amp;lt;xsl:value-of select="'visibility: collapse'"&gt;&lt;br /&gt;          &amp;lt;/xsl:otherwise&gt;&lt;br /&gt;        &amp;lt;/xsl:choose&gt;&lt;br /&gt;    &amp;lt;/xsl:attribute&gt;&lt;br /&gt;    ...&lt;br /&gt;&amp;lt;/tr&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;and now the same with JSP 1.x:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;tr style='visibility:&amp;lt;%=CONDITION ? "collapse" : "visible"%&gt;'&gt;&lt;br /&gt;   ...&lt;br /&gt;&amp;lt;/tr&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;or with JSP 2.x:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;tr style='visibility:${CONDITION ? "collapse" : "visible"}'&gt;&lt;br /&gt;   ...&lt;br /&gt;&amp;lt;/tr&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Nested loops. In JSTL the &lt;code&gt;&amp;lt;for-each&gt;&lt;/code&gt; tag has the &lt;code&gt;var&lt;/code&gt; attribute, which is variable that gets assigned the current element from the collection during looping. In nested loops, you choose different &lt;code&gt;var&lt;/code&gt; names, and you have easy access to variable at any level. In similar &lt;code&gt;&amp;lt;for-each&gt;&lt;/code&gt; in XSLT there is not &lt;code&gt;var&lt;/code&gt; attribute. You must use additional variables as child nodes, or some other workarounds. Its very easy to get lost.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Every XML-like fragment which is not an actual XML must be escaped. Say you have inlined javascript function which appends row to the table:&lt;br /&gt;&lt;pre&gt;onclick="append('&amp;lt;tr&gt;&amp;lt;td&gt;&amp;lt;/td&gt;&amp;lt;td&gt;&amp;lt;/td&gt;&amp;lt;/tr&gt;')"&lt;/pre&gt;&lt;br /&gt;This will work in JSP quite good, but will blow up in XSLT with "could not compile stylesheet" message. You must escape each &lt;code&gt;&amp;lt;&lt;/code&gt; character:&lt;br /&gt;&lt;pre&gt;onclick="append('&amp;amp;lt;tr&gt;&amp;amp;lt;td&gt;&amp;amp;lt;/td&gt;&amp;amp;lt;td&gt;&amp;amp;lt;/td&gt;&amp;amp;lt;/tr&gt;')"&lt;/pre&gt;&lt;br /&gt;Nobody could understand what is going on here at first look now.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The functional approach applied in XSLT design, instead of the well known (for all programmers) procedural one, makes "thinking in XSLT" very hard. "Normal" approach (JSP, Velocity, etc) takes the HTML template starting from familiar &lt;code&gt;&amp;lt;html&gt;&amp;lt;head&gt;...&amp;lt;body&gt;...&lt;/code&gt; and looks for special markers, where it puts data from "model". This data can be Java object or XPath-extracted data from other XML. XSLT does it in completely reverse way: it starts with &lt;code&gt;&amp;lt;template match="..."&gt;&amp;lt;apply-templates&gt;...&lt;/code&gt; so it takes the XML data document first, and tries to manipulate its content to obtain other document. As I said, in SOA processing this is fine. But in HTML generation it looks completely alien. I must say I always had problems with mental visualization of this process.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;No formal XML schema for XSLT 1.0 exists. At least I couldn't find it - there is only unofficial DTD somewhere. This ruins IDE code completion abilities. And the XSLT is so complicated, that you can't simply learn it in one day (or even week), so some inline-help would be of real help.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;p&gt;Now take all those points together and multiply by all the places on the web page where dynamic content generation happens. Lengthy, complicated, with all those escapings, plus complicated XPath expressions, plus this "other-way-round" functional approach. That is developer horror. And worse, it is maintainer hell. In the current project, after two weeks I'm not able to understand the sections I have written a few days ago. I cannot imagine looking at it after several months. What's worse, the template code is so different than resultant HTML code, that navigation in the template and finding the actual place I need to edit takes always too much time.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;After two weeks I'm fed up with XSLT. It's absolutely unproductive in web frameworks. Now I know why none of XML-based frameworks got big popularity ever. And I know I was completely wrong 3 years ago when I could bet that in the short time JSPX would replace JSP. Fortunately, it didn't.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Any alternatives?&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Now that we know XSLT is evil, which view technology should we use in our projects? Stick with JSP? For JSF-based project I wouldn't use JSP for sure, because it simply doesn't play well with JSF, and instead I would go for something like facelets. But actually I wouldn't go for JSF either any longer (that's another story about the thing I used to believe in and predict long life to it, and that I was finally disappointed completely with). So for non-JSF projects there are JSP/JSTL, Velocity, FreeMarker, GSP for Grails projects, SiteMesh for page layouts, perhaps other technologies that I'm not aware of. JSP/JSTL is the most widely used, best known, and has best tool support, even if it is probably the worst one from the group. Take those crazy SQL-based tags in JSTL, or funny standard tags from JSP to deal with request parameters. Whey didn't they just took those tags from JSTL that are used always (if, for-each, format, ...) and make them part of standard JSP? Why I always have to include it as separate library on Tomcat? Besides, I said earlier that the actual input template doesn't have to be valid XML, but I must say I don't like constructs like &lt;code&gt;&amp;lt;input value="&amp;lt;c:out ...&gt;"&gt;&lt;/code&gt;. Tag inside other tag's attribute - this looks horrible. That is why now I think that template directives should not be constructed with XML tags: so all those custom tags, JSTL tags etc is the wrong direction. Such code is simply too hard to read, because it resembles too much HTML (ok, templates not always are used to generate HTML, but I guess in about 95% of cases they are). The better approach is to use some special characters, like &lt;code&gt;#&lt;/code&gt; directives in Velocity, or &lt;code&gt;[#&lt;/code&gt; in FreeMarker, or EL syntax &lt;code&gt;${...}&lt;/code&gt; in JSP/JSTL (but EL is too much limited and it is actually not directive; besides assumption that only getters can be called from EL was serious mistake: e.g. you cannot check collection size, because there is no &lt;code&gt;getSize()&lt;/code&gt; method, only &lt;code&gt;size()&lt;/code&gt;). Compare the if-then-else block created with JSP/JSTL:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;c:choose&gt;&lt;br /&gt;&amp;lt;c:when test="${expr1}"&gt;&lt;br /&gt;  ...&lt;br /&gt;&amp;lt;/c:when&gt;&lt;br /&gt;&amp;lt;c:when test="${expr2}"&gt;&lt;br /&gt;  ...&lt;br /&gt;&amp;lt;/c:when&gt;&lt;br /&gt;&amp;lt;c:otherwise&gt;&lt;br /&gt;  ...&lt;br /&gt;&amp;lt;/c:otherwise&gt;&lt;br /&gt;&amp;lt;/c:choose&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;with the same written with Velocity:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#if (expr1)&lt;br /&gt;  ...&lt;br /&gt;#elseif (expr1)&lt;br /&gt;  ...&lt;br /&gt;#else&lt;br /&gt;  ...&lt;br /&gt;#end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Which one is easier to read?&lt;/p&gt;&lt;br /&gt;&lt;p&gt;FreeMarker can be also good replacement for existing projects that already use XSLT. From what I see, you can bind the XML data document to some variable, and then access it with XPath queries from FreeMarker template to extract data. Velocity offers similar thing, it's called DVSL, but I doesn't look good to me, because it applies the same functional, other-way-round-alien-looking "apply-templates" approach as XSLT.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Velocity or FreeMarker integrates also well with Spring. Form my point of view, the only serious drawback of those technologies when compared to JSP, is IDE support. In the company where I do my painful job with XSLT, "the only IDE" is NetBeans (I think it is not obligatory, but simply all guys use it and all projects are not build with external Ant script or Maven, but simply by NetBeans, so it is hard to use other IDE anyway). I tried to find some plugin with Velocity or FreeMarker support for Netbeans (at least for syntax highlighting), but looks like there is no one. That's really strange for me - those technologies are on the market for many years, and are quite popular I think. So why there is no support in second most popular Java IDE for them? For Eclipse the situation is better, from what I see.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So if you start new project, think twice (or ten times) before jumping into XSLT. And if you use Eclipse, you can even think twice before using JSP/JSTL. Velocity or FreeMarker might be a better option.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Footnote: this article was selected for the "Developer's Perspective" column at the Javalobby News newsletter from Apr 21, 2009; and also &lt;a href="http://java.dzone.com/news/death-xslt-web-frameworks"&gt;reposted on DZone&lt;/a&gt;, where it has started very interesting discussion. If you are interested, look at comments there: you will also find some good points in favor of XSLT, to complete the picture.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8828114559044739709-2373529928291328399?l=grzegorzborkowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grzegorzborkowski.blogspot.com/feeds/2373529928291328399/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8828114559044739709&amp;postID=2373529928291328399' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8828114559044739709/posts/default/2373529928291328399'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8828114559044739709/posts/default/2373529928291328399'/><link rel='alternate' type='text/html' href='http://grzegorzborkowski.blogspot.com/2009/04/fortunately-xslt-is-dead-in-web.html' title='Fortunately, XSLT is dead (in web frameworks)'/><author><name>Grzegorz Borkowski</name><uri>http://www.blogger.com/profile/16063009050017401077</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_Iu6FMYlWXN4/SeD5_rszBpI/AAAAAAAAAkQ/17qtFY-14Ag/S220/DSC_4313_1.jpg'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8828114559044739709.post-8008147982496167217</id><published>2009-04-07T06:45:00.000-07:00</published><updated>2009-04-15T04:39:32.265-07:00</updated><title type='text'>Relocating resources with RESTful web services</title><content type='html'>&lt;p&gt;Recently I spent long time on redesigning internals of a RESTful web service. In that service, I try to follow the rules presented in "REST canonical reference" book &lt;a href="http://oreilly.com/catalog/9780596529260/"&gt;RESTful Web Services &lt;/a&gt;. I decided to use "meaningful" URIs based on resource names. Resource name is editable, so when it is changed, the URI must change too (another solution is to use "non-meaniningful" URIs based on immutable, usually auto-generated IDs of the resources). Say I have the resource named "myProject" addressed by URI &lt;code&gt;http://myservice.org/v1/Projects/myProject&lt;/code&gt;. To change its name to "ourProject" one needs to send PUT request to this URI with the new name in request body. Say we use form-encoded representations in request, then we would send PUT request to &lt;code&gt;http://myservice.org/v1/Projects/myProject&lt;/code&gt; with request body &lt;code&gt;name=ourProject&lt;/code&gt;. Server processes the result, changes the name in the database, and must send the response back to the client. What should be the response? Here the interesting part starts.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;First implementation&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;According to the book, if the PUT request causes the URI to change, the response should be &lt;code&gt;301 Moved Permanently&lt;/code&gt; with the header &lt;code&gt;Location: http://myservice.org/v1/Projects/ourProject&lt;/code&gt; in order to let the client know the new location. I've implemented it this way, using Spring 3.0 REST support (with a bunch of my custom classes and annotations):&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   @RequestMapping(method=PUT, value="/projects/{projectName}")&lt;br /&gt;   public HttpResponse createOrUpdate(@PathVariable String projectName, PropertyValues newValues, @RequestUrl String url) {&lt;br /&gt;&lt;br /&gt;      SaveResult&lt;Project&gt; result = projectService.createOrUpdate(projectName, newValues);&lt;br /&gt;      if (result.isCreated()) {&lt;br /&gt;          return new HttpResponse(SC_CREATED).setHeader("Location", url);&lt;br /&gt;      } else if (result.isRenamed()) {&lt;br /&gt;          String newUrl = url.substring(0, url.lastIndexOf("/") + 1) + result.getObject().getName();&lt;br /&gt;          return new HttpResponse(SC_MOVED_PERMANENTLY).setHeader("Location", newUrl);&lt;br /&gt;      } else {&lt;br /&gt;          return new HttpResponse(SC_OK);&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;So in case when resource was renamed, I construct a new URL and return 301 code with new location. This should work, but it didn't. It looked like this response code triggered immediate GET request to the new location. Initially I thought that it is done internally on server either by Spring or Tomcat, but it turned out to be triggered by client. The same behavior happened for different clients: Firefox, IE, and pure Java client used for testing web services, the &lt;a href="http://code.google.com/p/rest-client/"&gt;Wiztools.org RESTClient&lt;/a&gt;. I don't know what HTTP Java library is used internally by the latter tool, but I guess the behavior is implemented in this library, not in the client itself.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I started to search some information about this problem, but Google was of very little help for queries like "PUT with 301 Moved Permanently". Lastly I looked at &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"&gt;RFC2616&lt;/a&gt;, the HTTP 1.1 specification. This is an excerpt with description of code 301:&lt;/p&gt;&lt;br /&gt;&lt;blockquote cite="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.2"&gt;If the 301 status code is received in response to a request other than GET or HEAD, the user agent MUST NOT automatically redirect the request unless it can be confirmed by the user, since this might change the conditions under which the request was issued.&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;So it looks like all browsers and other clients are broken in this area: they should not redirect automatically to the new location. So I had to find some workaround for this.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;A bit of theory behind it&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Suppose that after issuing PUT request which returned 301 code, the browser actually &lt;em&gt;did&lt;/em&gt; ask me for permission for redirection. And suppose I gave the permission. What should the browser (or other client) do? Obviously, send the request to the new URL. But what request? GET? or PUT (as initial request was PUT)? What does 301 response actually mean in this case? My first thinking was: I send PUT request to &lt;code&gt;http://myservice.org/v1/Projects/myProject&lt;/code&gt;, which changes the data of that resource. If URL is not changed, response is 200. If URL is changed (say to &lt;code&gt;http://myservice.org/v1/Projects/ourProject&lt;/code&gt;) as the result of new data submission, server updates the resource, and let me know the new URL with 301 response containing &lt;code&gt;Location&lt;/code&gt; header. (At least, this is the logic roughly presented in the aforementioned book, I think). So, is there any point in doing any redirection in such case? The 301 code is only information here, not obligation to do any redirect. I sent PUT request to update the resources, not GET to retrieve it. So sending (either without permission, or with permission) GET to the redirected resource makes no sense, as I didn't wanted to retrieve the resource, only update it.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;But then I looked at HTTP spec again, at general description of 3xx codes series:&lt;/p&gt;&lt;br /&gt;&lt;blockquote&gt;This class of status code indicates that further action needs to be taken by the user agent in order to fulfill the request. The action required MAY be carried out by the user agent without interaction with the user if and only if the method used in the second request is GET or HEAD.&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;This clearly indicates that action &lt;em&gt;needs to be taken&lt;/em&gt;, not &lt;em&gt;can be taken&lt;/em&gt;. Interesting. So I infer that 301 code is actually obligation for redirection. (BTW this quote says that action can be done without user interaction only if second request is GET or HEAD. At the same time, first quote says the same, but it mention &lt;em&gt;first&lt;/em&gt; request. Is it a bug in the spec? But logically, both make sense...) So perhaps my thinking was wrong. Imagine different situation: I retrieve myProject representation. After some time, I want to update its description, so I send PUT with new description to the &lt;code&gt;http://myservice.org/v1/Projects/myProject&lt;/code&gt; URL. But in the meantime, another user changed this project name to ourProject. If the server is able to remember such changes, when my request to &lt;code&gt;http://myservice.org/v1/Projects/myProject&lt;/code&gt; comes, it sees that myProject no longer exists, but remembers it was moved to &lt;code&gt;http://myservice.org/v1/Projects/ourProject&lt;/code&gt;, so it sends 301 response with new location, telling me "this is a new location our your resource, send your PUT request there". Now browser can ask me for confirmation "resource has been relocated, should I resend the same PUT request to the new URL?". If I say "Yes", it sends PUT to the new location and updates description of ourProject. So the second request should be PUT, not GET. The note from spec found below 301 description also indirectly points out that original method should be preserved for second request:&lt;/p&gt;&lt;br /&gt;&lt;blockquote cite="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.2"/&gt;Note: When automatically redirecting a POST request after      receiving a 301 status code, some existing HTTP/1.0 user agents will erroneously change it into a GET request.&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;Well, looks like not only &lt;q&gt;some existing HTTP/1.0 user agents&lt;/q&gt;, but also modern HTTP/1.1 clients do...&lt;/p&gt;&lt;br /&gt;&lt;p&gt;(Note: in the presented scenario the 409 response indicating concurrent modification problem would be probably more accurate; if another user renamed the resource, it could also have changed the description, so actually the current user could be more interested in retrieving the new representation first, and only then updating it.)&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;But GET is safe, right?&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Obviously, the confirmation (in any form, say dialog box) would work better in case of client being a human. If the client is a program (and in case of REST web services it usually will be), for example single-page, rich-client JavaScript application, the confirmation would be a bit more problematic. But that's academic discussion at this moment, because browsers are buggy for 301 codes and don't ask for confirmation anyway. Even if they did, this would be probably beyond control of actual JavaScript application (like in the case of basic authentication dialog pop-up), so it would be of very little practical usage.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So what is the solution? The first idea: in valid REST service, GET requests are safe, so sending such request automatically by the browser after obtaining 301 code would do no harm, apart from increasing a bit the load on the server (without real need). But I see two problems here: the redirection is handled by browser (or other HTTP library) in automatic way, so the actual client don't have access to the response from first request (PUT), only to the one from second request. If response to PUT request contained some special, important headers, they will be lost. But there is also second, more important problem. In case of my service, I use basic HTTP authentication, with some small trick to bypass browser authentication dialog (I'll describe this technique in one of the next posts). After user gets authenticated, I set default authentication header for all Ajax request, using Ext-JS code &lt;code&gt;Ajax.defaultHeaders = {Authentication : Basic HASH}&lt;/code&gt;. But it happens that in case of 301 response, the second, after-redirection request is launched without Ext-JS awareness, so the authentication headers are not applied, and the actual response to that request is error 401 or 403. So this seems like a dead-end.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Say goodbye to 301&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;After thinking about it, I came to the conclusion that probably authors of the book were wrong: in the case of URL change, as a direct result of PUT request, the 301 code is not the proper response. This conclusion is based on the aforementioned phrase from HTTP 1.1 spec, describing 3xx codes as indication that &lt;q&gt;further action needs to be taken by the user agent in order to fulfill the request&lt;/q&gt;. So 301 response is not meant to be just an information about resource metadata change. It is rather a kind of directive for the client: actually, most people using HTTP client libraries written in different languages, usually expect the 3xx redirections to be handled automatically be the library itself.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So what response code should be used? The 204 No Content seems to be the best choice - see the spec description for this code:&lt;/p&gt;&lt;br /&gt;&lt;blockquote cite="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.5"&gt;The server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation. The response MAY include new or updated metainformation in the form of entity-headers, which if present SHOULD be associated with the requested variant.&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;This looks like perfect fit. Server fulfilled the request and updated the resource, but doesn't have to return the resource representation, as it is already known to the client. But as the result of the change, part of object metadata has been changed: namely the URI of the resource. So the response contains &lt;code&gt;Location&lt;/code&gt; header with updated metadata. Simple, and works well with all (or most) HTTP clients.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8828114559044739709-8008147982496167217?l=grzegorzborkowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grzegorzborkowski.blogspot.com/feeds/8008147982496167217/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8828114559044739709&amp;postID=8008147982496167217' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8828114559044739709/posts/default/8008147982496167217'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8828114559044739709/posts/default/8008147982496167217'/><link rel='alternate' type='text/html' href='http://grzegorzborkowski.blogspot.com/2009/04/relocating-resources-with-restful-web.html' title='Relocating resources with RESTful web services'/><author><name>Grzegorz Borkowski</name><uri>http://www.blogger.com/profile/16063009050017401077</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_Iu6FMYlWXN4/SeD5_rszBpI/AAAAAAAAAkQ/17qtFY-14Ag/S220/DSC_4313_1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8828114559044739709.post-50721160275371174</id><published>2009-03-16T08:39:00.000-07:00</published><updated>2009-03-28T14:07:23.760-07:00</updated><title type='text'>Test drive of Spring 3.0 Milestone 2 REST support</title><content type='html'>&lt;p&gt;I'm developing a proof-of-concept application based on REST architecture, with pure-JavaScript client written in Ext-JS, and server side based on Spring. Until now, I've used Spring 2.5 to create REST service, but it was a bit problematic: it required me to write too many repetitive code. I've read about JAX-RS and it sound very good to me. There are some implementations already available, but I didn't want to learn and add yet another product to the already challenging technology stack. As it was known at that time that Spring 3.0 is going to include REST support, I decided to wait a bit for it, expecting full JAX-RS support in Spring. Now, after reading &lt;a href="http://blog.springsource.com/2009/03/08/rest-in-spring-3-mvc/"&gt;Arjen's blog entry&lt;/a&gt;, I see JAX-RS will not be implemented: that's a pity, because JAX-RS seems very well designed for me; but ok, if Spring's solution delievers the same value, this doesn't matter much. So today, after reading Arjen's introduction, I switched to 3.0 M2 to see how it fits my needs, and I'd like to share my results.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The most wanted thing, the URI templates are of great help obviously. But this is only the minimum of what I expected. After playing a bit with spring 3.0, I must say I'm a bit disappointed. I simply expected much much more. It seems to me that Spring REST is targeted at server-side web applications, the ones I call "half-REST" applications. This is not what I expected: because Spring REST support is done by Arjen Poutsma, the author of Spring Web Services, I thought REST support was going to be comparable with Spring Web Services. I really like the Spring Web Services approach, focused on real services with data, not some HTML-oriented views. Unfortunately, Spring REST doesn't seem to be like this. It doesn't help much writing real web service which return &lt;em&gt;data&lt;/em&gt;, instead of HTML-oriented views. For example, shallow ETag support and HTTP-over-POST method conversion are nice things for "half-REST" application, but they are of little value for fully RESTful applications. In my REST service I plan to rather go for deep ETag, based on database versions, cache states etc, and I use real HTTP methods: PUT, DELETE, instead of PUT-over-POST.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Requirements and assumptions&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;My application consists of two parts: server side, written in Java, based on Spring, and client-side, written in Ext-JS. Server side exposes the web service based on REST principles, following the guidelines presented in the great &lt;a href="http://oreilly.com/catalog/9780596529260/"&gt;RESTful Web Services&lt;/a&gt; book.  Service returns data in JSON format (I decided JSON better fits my needs than XML, as the client is written in JavaScript, so JSON processing will be faster, and bandwidth usage will be smaller; service can be used also by any other tool, as JSON is widely supported in virtually any language). It accepts POST/PUT request body data mostly as form-encoded pairs, but in some more complicated cases it can accept JSON data too.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Now say we have a resource called "Project". It is addressable by &lt;code&gt;http://mydomain/restservice/v1/projects&lt;/code&gt;. GET to this address returns list of projects in JSON format. GET to &lt;code&gt;http://mydomain/restservice/v1/projects/MyProject&lt;/code&gt; returns details of MyProject. DELETE to this URL removes this project. PUT to this URL creates or updates MyProject, using form-encoded data from request body (during creation, client knows the URL of project, that is why we use PUT; if we have used database IDs in URL, than creation would be done by POST to &lt;code&gt;http://mydomain/restservice/v1/projects&lt;/code&gt;).&lt;/p&gt;&lt;br /&gt;&lt;p&gt;This URL may be a base for other related resources, e.g. &lt;code&gt;http://mydomain/restservice/v1/projects/MyProject/tasks&lt;/code&gt; will return tasks for MyProject, &lt;code&gt;http://mydomain/restservice/v1/projects/MyProject/tasks/Development&lt;/code&gt; will return details about Development task in MyProject, &lt;code&gt;http://mydomain/restservice/v1/projects/MyProject/assignments&lt;/code&gt; will return assignment list for MyProject, ... etc.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Note, that those URLs actually represent virtual directories. This means that common rule "trailing slash doesn't matter" (especially for URL representing "list of resources") should be respected: &lt;code&gt;http://mydomain/restservice/v1/projects&lt;/code&gt; address is equivalent to &lt;code&gt;http://mydomain/restservice/v1/projects/&lt;/code&gt; address. If you consider that each project is also the container for its tasks or assignments, then also &lt;code&gt;http://mydomain/restservice/v1/projects/MyProject&lt;/code&gt; should be equivalent to &lt;code&gt;http://mydomain/restservice/v1/projects/MyProject/&lt;/code&gt;, etc.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Each request to the service must return proper response code: 200,201,301 (if data in PUT request changes the resource address), 304 (in conditional GETs), 400, etc. In some cases it must contain proper body (here in JSON format) and proper headers (e.g. Location header in case of 301 response). My services misses only one RESTful requirement: connectivity of representations. In my opinion application of this principle to javascript client, that must be already programmed against known service, doesn't add any value, it only increases bandwidth usage (ok, maybe some very intelligent client could take advantage of it; but for a while, it would be too complicated for my case). JSON representations doesn't fit well to handle links: if I have served linked representations, I would probably have to use XML instead. I also don't use content negotiation: all representations are JSON. Again, this would be overkill for my service, which is primary targeted at predefined JavaScript client. If it was more general, public service, this should be probably refactored.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Implementation with Spring 2.5&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Let's implement the Project service with aid of Spring. Annotation-based Spring MVC introduced in version 2.5 seemed to match quite well my requirements, and that is why I decided to use it. So let's start with Spring 2.5, and analyse all the problems I faced; then we'll see which of them are solved by Spring 3.0.M2.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I have resource "Project" with some actions to be performed on it: so logical choice is to put all operations related to Projects into one controller. Base URL of this controller is &lt;code&gt;http://mydomain/restservice/v1/projects&lt;/code&gt; or equivalent with trailing slash &lt;code&gt;http://mydomain/restservice/v1/projects/&lt;/code&gt;. Some actions (GET project list, POST - if we have used it) are done directly on this URL. Some others (GET project, PUT, DELETE) are done on &lt;code&gt;http://mydomain/restservice/v1/projects/{projectName}&lt;/code&gt; URL (or, potentially, equivalent one with trailing slash &lt;code&gt;http://mydomain/restservice/v1/projects/{projectName}/&lt;/code&gt;). There can be also other controllers in my service, either completely unrelated to Project resource, like User controller (say &lt;code&gt;http://mydomain/restservice/v1/users&lt;/code&gt;) or related to Projects, like tasks controller (&lt;code&gt;http://mydomain/restservice/v1/projects/{projectName}/tasks&lt;/code&gt;) or assignments controller (&lt;code&gt;http://mydomain/restservice/v1/projects/{projectName}/assignments&lt;/code&gt;). I won't cover those controllers, but we should keep in mind that framework should be able to match the most specific controller properly, that is for request for &lt;code&gt;http://mydomain/restservice/v1/projects/{projectName}/assignments&lt;/code&gt; the assignments controller should be picked up, not the projects controller.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So, I would like to write the ProjectController, mapped to &lt;code&gt;http://mydomain/restservice/v1/projects&lt;/code&gt; (with or without trailing slash - let's call it "base URL" for now), with 5 methods (method names doesn't matter here): list() mapped to GET with base URL, show() mapped to GET with base+projectName URL, createOrUpdate() mapped to PUT with base+projectName URL, and remove() mapped to DELETE with base+projectName URL. Something like this (assume that URL part &lt;code&gt;http://mydomain/restservice/v1&lt;/code&gt; is already mapped to dispatcher servlet) :&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@Controller&lt;br /&gt;@RequestMapping("/projects")&lt;br /&gt;public class ProjectEndpoint {&lt;br /&gt; &lt;br /&gt;  @RequestMapping(method=GET)&lt;br /&gt;  public HttpResponse list() {...}&lt;br /&gt; &lt;br /&gt;  @RequestMapping(method=GET, value="*")&lt;br /&gt;  public HttpResponse show() {...}&lt;br /&gt; &lt;br /&gt;  @RequestMapping(method=PUT, value="*")&lt;br /&gt;  public HttpResponse createOrUpdate() {...}&lt;br /&gt; &lt;br /&gt;  @RequestMapping(method=DELETE, value="*")&lt;br /&gt;  public HttpResponse remove() {...}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;I would like to take advantage of Spring's &lt;code&gt;@RequestMapping&lt;/code&gt; annotation ability to merge class-level path value (&lt;code&gt;/projects&lt;/code&gt;) with method-level relative paths. But it doesn't work. To make it work, it seems that class-level path must end with wildcard, and all methods must have some URL suffix. But you can't have methods like list() and show() in this case, one mapped to base URL, and onother to base URL + suffix. This is annoying shortcoming of Spring MVC. There are also many other problems here: The star character (*) matches zero or more characters. That's wrong, because method show() will be matched even for request when no project name was passed. There should be something like "+" character, meaning "one or more characters". Also trailing slashes are real problem here. If I mark controller class with &lt;code&gt;@RequestMapping("/projects")&lt;/code&gt; (as in the code above) then only request without trailing slash will be matched. If trailing slash is appended to the actual request, we get 404 response. What's worse, method-level annotation  will not be appended to base URL in this case. So we have to change it to &lt;code&gt;@RequestMapping("/projects/*")&lt;/code&gt;. Now methods will work, but if you send request to base url to get list of projects, and forget the slash at the end, you will get 404 response again. That's very bad in my opinion. JAX-RS handles it properly: see JAX-RS's &lt;a href="https://jsr311.dev.java.net/nonav/releases/1.0/javax/ws/rs/Path.html"&gt;@Path Javadoc&lt;/a&gt;. Finally, the only solution that works is to omit the "base URL" on class level, and repeat it at each method level (without trailing slashes). This works, but requires mapping repetition, and you can't use trailing slashes in actual requests, unfortunately.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Second problem: in method show() we actually need to extract the project name from URL. Spring 2.5 doesn't offer any help for this, we have to manually parse the URL.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;For PUT and POST method I need to get access to request body. For form-encoded data it is not that complicated: I may use &lt;code&gt;@RequestParam&lt;/code&gt; annotated params, I may use &lt;code&gt;@InitBinder&lt;/code&gt; to initialize command object etc, I may also access directly Request object and call &lt;code&gt;getParameter()&lt;/code&gt;. However I faced third problem here: &lt;code&gt;getParameter()&lt;/code&gt; works only for POST method, and not for PUT, even if request body is the same. I had not dig into this issue too deeply, but it looks like this has a root in servlet API specification flaw (or Tomcat implementation). However, it would be nice if REST support framework handled it properly, for example by wrapping the request object. In my case, I had to write myself the method to extract request parameters from POST and PUT requests in uniform way:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  public static Map&amp;lt;String, Object&amp;gt; decodeFormEncodedParamsFromBody(HttpServletRequest req) {&lt;br /&gt;     try {&lt;br /&gt;        Map&lt;String,Object&gt; results = new HashMap&amp;lt;String,Object&amp;gt;();&lt;br /&gt;        String inputString = IOUtils.toString(req.getReader());&lt;br /&gt;        // Parse a x-www-form-urlencoded string&lt;br /&gt;        String[] pairs = inputString.split("\\&amp;amp;");&lt;br /&gt;        String encoding = req.getCharacterEncoding() != null ? req.getCharacterEncoding() : "UTF-8";&lt;br /&gt;        for (String pair : pairs) {&lt;br /&gt;            String[] fields = pair.split("=");&lt;br /&gt;            String name = URLDecoder.decode(fields[0], encoding);&lt;br /&gt;            String value;&lt;br /&gt;            if (fields.length &amp;gt; 1) {&lt;br /&gt;               value = URLDecoder.decode(fields[1], encoding);&lt;br /&gt;            } else {&lt;br /&gt;               value = "";&lt;br /&gt;            }&lt;br /&gt;            if (results.containsKey(name)) {&lt;br /&gt;               List&amp;lt;String&amp;gt; values = (List&amp;lt;String&amp;gt;)results.get(name);&lt;br /&gt;               values.add(value);&lt;br /&gt;            } else {&lt;br /&gt;               results.put(name, value);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        return results;&lt;br /&gt;    } catch (IOException e) {&lt;br /&gt;       throw new RuntimeException(e);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;What if POST or PUT body is in JSON form? I would like to bind it automatically to some "object-oriented" representation: either use some JSON unmarshaller and transform it to Project bean; or bind it to JSONObject from JSON-Lib library, or use other JSON library. For example, in my case I would like to be able to write method like this:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@RequestMapping(method=PUT)&lt;br /&gt;public HttpResponse createOrUpdate(JSONObject projectJson) {...}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;But Spring's @InitBinder is not able to bind request body, only request params. After some research I found solution: &lt;code&gt;AnnotationMethodHandlerAdapter&lt;/code&gt; has a method &lt;code&gt;setCustomArgumentResolver()&lt;/code&gt; taking &lt;code&gt;WebArgumentResolver&lt;/code&gt; implementation, which can be used for this purpose. One have to write the resolver and register it in spring context. This is how such resolver could look like:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class JsonLibJSONObjectArgumentResolver implements WebArgumentResolver {&lt;br /&gt;&lt;br /&gt;  public Object resolveArgument(MethodParameter methodParameter, NativeWebRequest webRequest) throws IOException {&lt;br /&gt;     if (methodParameter.getParameterType().equals(JSONObject.class)) {&lt;br /&gt;        ServletRequest req = (ServletRequest)webRequest.getNativeRequest();&lt;br /&gt;        String inputString = IOUtils.toString(req.getReader());&lt;br /&gt;        JSONObject json = JSONObject.fromObject(inputString);&lt;br /&gt;        return json;&lt;br /&gt;     }&lt;br /&gt;     return UNRESOLVED;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Last problem relates to returning results from my methods. For GET methods I have to return JSON representations. For PUT, POST, DELETE there is actually no representation: only response code. Each response may (or sometimes must) contain also some headers. I could use JSONView for this, which was around for some time, but in fact I didn't like this approach that much. My general feeling is that Spring MVC is a result of the dominating trend in the past of abstracting away the HTTP nature of web applications: hide HttpRequest and HttpResponse, and deal with models, views, controllers. JSF is the best exmple of this approach. Spring MVC, though closer to HTTP request-response model, still tries to put abstraction layer on top of this, with its views and view resolvers. Perhaps it is good for server-side web applications and frameworks, that use forwards and redirects, templates, includes etc. But for REST service, that accepts and returns representations which are mostly data (like JSON), not "views", this abstraction may be unnecessary. In my case, in my controller methods I simply want to say "return this JSON object" or "return status this, with header this, and with JSON body that". I don't need views, view resolvers etc. The perfect example of this approach is Spring Web Services: you have an endpoint with some methods on it, each method takes some XML (or its part specified with XPath, or its unmarshalled representation by autoconversion) and returns some XML (or some object which is marshalled then). You have adapters for different XML libraries and different XOM libraries. That's great, and I expected something similar from Spring for building REST based web services.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I wasn't able to find any solution how to return simply JSONObject or something similar from controller method. See also &lt;a href="http://forum.springframework.org/showthread.php?p=222621"&gt;this thread on Spring forum&lt;/a&gt; for details. Finally I came to the conclusion that I will use Spring views, and created HttpResponse view:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public  abstract class HttpResponse implements View {&lt;br /&gt;&lt;br /&gt;  int statusCode;&lt;br /&gt;  Map&amp;lt;String, String&amp;gt; headers;&lt;br /&gt;&lt;br /&gt;  public HttpResponse(int statusCode) {&lt;br /&gt;     this.statusCode = statusCode;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public HttpResponse(int statusCode, Map&amp;lt;String, String&amp;gt; headers) {&lt;br /&gt;     this.statusCode = statusCode;&lt;br /&gt;     this.headers = Collections.unmodifiableMap(headers);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public abstract String getContentType();&lt;br /&gt;&lt;br /&gt;  public void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {&lt;br /&gt;     response.setStatus(statusCode);&lt;br /&gt;     if (headers != null) {&lt;br /&gt;        for (Map.Entry&amp;lt;String, String&amp;gt; header : headers.entrySet()) {&lt;br /&gt;           response.setHeader(header.getKey(), header.getValue());&lt;br /&gt;        }&lt;br /&gt;     }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;I have two implementations: NoBodyResponse and JSONObjectResponse. Names clearly define their meaning. JSONObjectResponse takes JSONObject (from JSONLib) in constructor, and writes it to HTTP response body. Similar implementations could be created for other JSON or XML libraries, or for XOM or JOM (Json-object-marshaller) libraries. This is a kind of basic replacement for &lt;a href="https://jsr311.dev.java.net/nonav/releases/1.0/javax/ws/rs/core/Response.ResponseBuilder.html"&gt;ResponseBuilder&lt;/a&gt; from JAX-RS.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Implementation with Spring 3.0 M2&lt;/h2&gt;&lt;br /&gt;Now let's look what we can simplify after migration to Spring 3.0 M2. The &lt;code&gt;@PathVariable&lt;/code&gt; introduced in M1 is a great help, as I no longer have to parse the URLs manually. This reduces code duplication and is less error-prone. So now my example of hypothetical ProjectEndpoint could look like this:&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@Controller&lt;br /&gt;@RequestMapping("/projects")&lt;br /&gt;public class ProjectEndpoint {&lt;br /&gt; &lt;br /&gt;  @RequestMapping(method=GET)&lt;br /&gt;  public HttpResponse list() {...}&lt;br /&gt; &lt;br /&gt;  @RequestMapping(method=GET, value="{projectName}")&lt;br /&gt;  public HttpResponse show(@PathVariable String projectName) {...}&lt;br /&gt;       &lt;br /&gt;  @RequestMapping(method=PUT, value="{projectName}")&lt;br /&gt;  public HttpResponse createOrUpdate(@PathVariable String projectName) {...}&lt;br /&gt; &lt;br /&gt;  @RequestMapping(method=DELETE, value="{projectName}")&lt;br /&gt;  public HttpResponse remove(@PathVariable String projectName) {...}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;BTW: I've found already a bug in &lt;code&gt;@PathVariable&lt;/code&gt; processing: if you have method taking for example id, which is long, marked with &lt;code&gt;@PathVariable&lt;/code&gt;, then the id from URL will be automatically converted to long. However if the actual URL contains characters nonconvertible to long, then exception is thrown, and you get 500 response. This is wrong, as this is clearly client error, so the response should be 400 (bad request), not 500. I haven't checked yet if it was already reported.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Unfortunely, the code above still doesn't work. Apart from &lt;code&gt;@PathVariable&lt;/code&gt;, nothing has actually changed (at least from what I observed): you cannot map class to &lt;code&gt;/projects&lt;/code&gt; nor &lt;code&gt;/projects/&lt;/code&gt;, you have to map it to &lt;code&gt;/projects/*&lt;/code&gt;. Now you cannot map &lt;code&gt;list()&lt;/code&gt; method to do GET for base URL, and another &lt;code&gt;show()&lt;/code&gt; method to do GET for sub-URL in the single controller - this will not work, for any reason. So still you have to throw away class-level mapping and copy base URL to each method, to make it work. And trailing slashes are still broken: you can't use it in request URL. So actually we haven't improved the code too much. Looks like &lt;code&gt;@RequstMapping&lt;/code&gt; processing was broken in 2.5 and is so in 3.0.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Let's check other points: &lt;code&gt;getParameter()&lt;/code&gt; for form-encoded PUT request body doesn't work in Spring 3.0 too, so all Spring autobinding feature and &lt;code&gt;@RequestParam&lt;/code&gt; will fail for PUT requests. That's really a pity. Next: automatic binding of request body to some method param, like &lt;code&gt;JSONObject&lt;/code&gt;, or JAXB binding object: not much progress here too, but fortunately we can use the &lt;code&gt;setCustomArgumentResolver()&lt;/code&gt; that I demonstrated earlier. Next: &lt;code&gt;HttpResponse&lt;/code&gt; View or something similar, to easily set response code or response header  - nothing at all. Arjen mentions also &lt;code&gt;JacksonJsonView&lt;/code&gt;, but it is not in Spring 3.0, but in Spring JavaScript - hello? What JavaScript? I'm building server-side web service here, so why on earth should I use Spring JavaScript module? This makes no sense. JSON is not JavaScript: it's data exchange format, which you can use for example to talk to .NET from Java, if you wish: no JavaScript is involved here.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;And one more issue. I said earlier that I don't use content negotation, because I serve only JSON. But suppose that I have need to serve also XML now, and use content negotiation, based on &lt;code&gt;Accept&lt;/code&gt; header from client. How to accomplish this? JAX-RS has &lt;a href="https://jsr311.dev.java.net/nonav/releases/1.0/index.html?javax/ws/rs/package-summary.html"&gt;@Produces&lt;/a&gt; annotation for this: simply by marking two methods or classes with this annotation with different value, we are sure that framework will pick up the valid method, according to user request. How to do it in Spring 3.0? From what I understood, I should use the new &lt;code&gt;ContentNegotiatingViewResolver&lt;/code&gt;. Is it better solution then JAX-WS? I haven't try it yet, so I can't say much about it. But I can think about different use cases. Let's assume that only one method of my controller is supposed to be content-negotiation aware. For example, GET method may return JSON if &lt;code&gt;Accept: application/json&lt;/code&gt; was passed, or the PDF document if &lt;code&gt;application/pdf&lt;/code&gt; was passed (as it's less likely that PUT method is going to use PDF document as input here). In such a case JAX-RS solution is a winner: I would simply have two methods for GET, first marked with &lt;code&gt;@Produces("application/json")&lt;/code&gt; - it could return my &lt;code&gt;JSONObjectResponse&lt;/code&gt; view, and second method marked with &lt;code&gt;@Produces("application/pdf")&lt;/code&gt;, returning some PDF view (or model). On the other hand, if my service produces/accepts JSONs and XMLs, it's higly likely that each method will be doubled: one producing/accepting XML, and one for JSON. Then perhaps it would be better to have two controllers instead: e.g. &lt;code&gt;ProductEndpointXML&lt;/code&gt; and &lt;code&gt;ProductEndpointJSON&lt;/code&gt;. In such a case probably &lt;code&gt;@RequestMapping&lt;/code&gt; annotation should be enhanced to take also header values into account (currently it takes path, HTTP method, and request params, but no headers), to be able to route request to proper controller.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;As you see, the only real asset of Spring 3.0 for REST in my application is &lt;code&gt;@PathVariable&lt;/code&gt;. &lt;code&gt;@PathVariable&lt;/code&gt; is really nice, but it is very very small improvement for the major realease of Spring, having said for long time that REST support is one of the key additions in this release. (To be honest I have to mention here small improvements from 3.0 M1: new &lt;code&gt;@RequestHeader&lt;/code&gt; annotation and default value in &lt;code&gt;@RequestParam&lt;/code&gt; - this is really helpful in RESTful applications too.) Especially if you compare Spring Web Services for building SOAP-oriented web services against Spring 3 REST support for building REST-oriented web services, the latter seems very very poor. If I remember correctly, Arjen said some time ago that he considered building REST support based on Spring Web Services, but decided to go with Spring MVC instead. Looking at Spring 3.0 M2 I'm not really sure if this was the best decision. Also comparison with JAX-RS shows some Spring shortcomings. Look for example on &lt;a href="http://architects.dzone.com/articles/putting-java-rest"&gt;Bill Burke's JAX-RS intro atricle&lt;/a&gt;: it describes pretty much interesting stuff, many of which having no counterpart in Spring 3.0. On the other hand, it is still only M2 for Spring 3.0. I hope M3 will significantly improve support for real RESTful web services. If not, I will have to search for different solutions: some JAX-RS implementation with Spring integration, or perhaps Grails?&lt;br /&gt;&lt;/p&gt;&lt;h2&gt;Summary&lt;/h2&gt;&lt;br /&gt;So what should be done for REST support in Spring 3.0, to be fully functional and in line with JAX-RS and Spring Web Services? Spring 3.0 should meet in my opinion following requirements:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;One should be able to write single controller for single logical resource, with base URL mapping declared on class, and sub-URLs mapping declared on some methods (GET,PUT,DELETE); other methods without sub-URL mapping (GET,POST) refer to base URL. Note that controllers can create "nested" structure (e.g. one for project, other for project's tasks). Also trailing slashes in "virtual directory" URLs should be handled properly (trailing slashes should not influence the response).&lt;br/&gt;Some ideas here: first, all the method-level paths, if they are not absolute, should be treated as relative to class-level path. According to &lt;a href="http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/web/bind/annotation/RequestMapping.html"&gt;&lt;code&gt;@RequestMapping&lt;/code&gt; Javadoc in 2.5&lt;/a&gt;, it &lt;em&gt;should&lt;/em&gt; behave like this already in 2.5; but from my observations it did only if class-level path ended with wildcard; so in fact fixing it should not break backward compatibility, and should be treated rather as bug fix. &lt;code&gt;@PathVariable&lt;/code&gt; fixes already problem of &lt;code&gt;*&lt;/code&gt; character matching zero characters, that I mentioned earlier (I assume &lt;code&gt;@PathVariable&lt;/code&gt; matches one or more characters only). Problem of trailing slash can be solved this way: first the request URL is matched literally. It there is a match, then continue normally. If there is no match, then look at request URL: if ends with slash, remove it, if it doesn't, add it - and then try the whole matching again.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;@PathVariable with type conversion should give error 400, not 500, if conversion fails&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Proper handling of &lt;code&gt;Request.getParameter()&lt;/code&gt; for PUT (the same as for POST) - probably by wrapping PUT requests&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Getting easy access to request body, with automatic conversion/marshalling (e.g. to JSONObject, some XML representations, JAXB binding result, ...), preferably as method param, perhaps with some annotation&lt;/li&gt;&lt;br /&gt;&lt;li&gt;HttpResponse View implementation out of the box, allowing setting response code and headers, with different implementations for "body-full" responses (JSONObject, XML representations, marshalling, ...)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Simplified content-negotiation: for example by extending &lt;code&gt;@RequestMapping&lt;/code&gt; annotation to be able to match request headers too (at least &lt;code&gt;Accept&lt;/code&gt; header)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Move JSON support from Spring JavaScript project to Spring core&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;This is not exhaustive list obviously. It is based on my observations for specific service I'm building. But I believe in the future there will be more and more such applications and "real" REST services, so it would be really good to have Spring support them fully, not shallowly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8828114559044739709-50721160275371174?l=grzegorzborkowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grzegorzborkowski.blogspot.com/feeds/50721160275371174/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8828114559044739709&amp;postID=50721160275371174' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8828114559044739709/posts/default/50721160275371174'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8828114559044739709/posts/default/50721160275371174'/><link rel='alternate' type='text/html' href='http://grzegorzborkowski.blogspot.com/2009/03/test-drive-of-spring-30-m2-rest-support.html' title='Test drive of Spring 3.0 Milestone 2 REST support'/><author><name>Grzegorz Borkowski</name><uri>http://www.blogger.com/profile/16063009050017401077</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_Iu6FMYlWXN4/SeD5_rszBpI/AAAAAAAAAkQ/17qtFY-14Ag/S220/DSC_4313_1.jpg'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8828114559044739709.post-8904376268001033947</id><published>2008-12-15T06:15:00.000-08:00</published><updated>2008-12-15T12:12:10.103-08:00</updated><title type='text'>SpringSource Certified Professional exam passed!</title><content type='html'>Last week I passed the SpringSource Certified Professional exam. In previous years I passed some Sun's certification on Java: SCJP, SCBCD and I must say that Spring certificate was much more difficult. There is no mock certification accessible on the net. You don't know what kind of questions you can expect. The passing threshold is much higher (75 %). There is no much information about it on forums like JavaRanch. I was able to find only one post somewhere on the net from somebody who passed this exam. He said it was more difficult than he expected. I agree: it was much more difficult than I expected, so I was really happy (and proud of myself!) to see that I passed it with result 94%, which means only 3 wrong answers out of 50 questions. &lt;br /&gt;I can only guess that there are still not so many people around the world with this certificate, as this is relatively new exam, difficult one, and you cannot pass it "just like that": you have to go through Spring training first, or use the "grandfathered candidate" path. As there were no training in Poland yet (first one is scheduled in March or April next year) I had to ask for the "grandfathered" status. Fortunately, I was allowed to take the exam. &lt;br /&gt;Based on those observations, I'm pretty sure there are no many people in my country having this certificate. Perhaps I'm even the first one in Poland to hold it? Who knows.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8828114559044739709-8904376268001033947?l=grzegorzborkowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grzegorzborkowski.blogspot.com/feeds/8904376268001033947/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8828114559044739709&amp;postID=8904376268001033947' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8828114559044739709/posts/default/8904376268001033947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8828114559044739709/posts/default/8904376268001033947'/><link rel='alternate' type='text/html' href='http://grzegorzborkowski.blogspot.com/2008/12/springsource-certified-professional.html' title='SpringSource Certified Professional exam passed!'/><author><name>Grzegorz Borkowski</name><uri>http://www.blogger.com/profile/16063009050017401077</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_Iu6FMYlWXN4/SeD5_rszBpI/AAAAAAAAAkQ/17qtFY-14Ag/S220/DSC_4313_1.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8828114559044739709.post-6703613004446870079</id><published>2008-10-10T06:40:00.000-07:00</published><updated>2009-05-11T14:36:08.736-07:00</updated><title type='text'>Spring Security ACL - very basic tutorial</title><content type='html'>&lt;h2&gt;Introduction&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;I spent last few days digging into Spring Security User Guide documentation. I had not much experience with this product before, so I thought it is the right time to learn it.  I was motivated by the analysis I was doing recently for some project: one of the requirements was building the flexible access control module, allowing for granting fine-grained permissions on per-user, per-object and per-operation basis. This kind of authorization is not possible with standard role-base Java EE approach. I wanted to know how it is solved in real-world systems. As a Spring-addict, my first choice to look at was Spring Security. Spring Security solves the problem with its ACL package.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I read the user guide, and found it not clear enough. It gives some background, but many things are not explained good enough. I started analysing the sample application bundled with Spring Security realease, and JavaDocs, but the complexity of Spring Security was overwhelming. I wanted to implement some simple proof-of-concept application using Spring Source ACL. I believe Spring Security is powerful solution, but amount of interfaces, classes, dependencies, configuration required, makes it hard to learn. Just look at the sample contacs application: the authorization configuration (&lt;code&gt;applicationContext-common-authorization.xml&lt;/code&gt;) requires almost 20 spring beans in context, many of them are just infrastructure classes (and it doesn't contain the definitions of actual ACLs). Why there are no simply defaults for most settings? (Take for example the &lt;code&gt;aclService&lt;/code&gt; bean: why do I have to explicitely define the cache stategy and lookup strategy? Why there is no constructor assuming default values? as a result, I blindly copy the configuration from sample.)&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I was still lost, so I looked around for some tutorial, and found &lt;a href="http://server.denksoft.com/wordpress/?page_id=5"&gt;A Spring Security ACL tutorial for PostgreSQL&lt;/a&gt;. It looked promising, but it turned out to be not less complicated than contacts sample. After long fight, finally I managed to build my simple application, using Spring Security ACL concepts, but with simplified implementations. It took me long time, and I wasn't able to find any such example on the net - so I decided to publish my results. I hope you will find it helpful in learning Spring Security ACL.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Requirements&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;Imagine the following scenario. We have a company. Each employee in this company is obliged to provide some work reports to his manager. Manager is allowed to accept the report (or not - but this is not relevant here). Only employee can create report. Only manager can accept it. So far it's easy and can be solved with roles-based solution. The key point, however, is that manager can't accept all reports - only reports submitted by his subordinate employee. Let's say we have four employees and 2 managers. Employees empl1 and empl2 are assigned to manager1, and empl3 and empl4 are assigned to manager2. So manager1 can only accept reports of empl1 and empl2, but not those of empl3 and empl4. This cannot be easily solved with roles. Instead, we will use Spring Security ACLs.&lt;/p&gt;&lt;br /&gt;&lt;h2&gt;Implementation&lt;/h2&gt;&lt;br /&gt;&lt;h3&gt;Domain model&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;We have very simple object model here: the Report class with id, description, acceptation flag, and reference to the owner User; and the User class itself, containing only login name field (obviously, this is extremely simplified model when compared with any real applicaton - but this will help us focus on the main subject). Below is the code of our model classes:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package springacltutorial.model;&lt;br /&gt;&lt;br /&gt;public class User {&lt;br /&gt;&lt;br /&gt; public User(String login) {&lt;br /&gt;    this.login = login;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private String login;&lt;br /&gt;&lt;br /&gt; public String getLogin() {&lt;br /&gt;    return login;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package springacltutorial.model;&lt;br /&gt;&lt;br /&gt;public class Report {&lt;br /&gt;&lt;br /&gt;  private long id;&lt;br /&gt;  private String description;&lt;br /&gt;  private boolean accepted;&lt;br /&gt;  private User user;&lt;br /&gt;&lt;br /&gt;  public long getId() {&lt;br /&gt;      return id;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void setId(long id) {&lt;br /&gt;      this.id = id;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public String getDescription() {&lt;br /&gt;      return description;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void setDescription(String description) {&lt;br /&gt;      this.description = description;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public boolean isAccepted() {&lt;br /&gt;      return accepted;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void setAccepted(boolean accepted) {&lt;br /&gt;      this.accepted = accepted;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public User getUser() {&lt;br /&gt;      return user;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public void setUser(User user) {&lt;br /&gt;      this.user = user;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Service layer and data access&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;Let's implement our service class, named &lt;code&gt;ReportsServices&lt;/code&gt;. It has only two methods: one for creating new reports (by employees) and second one for accepting reports (by managers). We also use simple map-based DAO for accessing the reports. For simplification, we will not use separate interface and class implementation, but only concrete classes. Spring is able to handle it with help of CGLIB. Here is the code of the classes:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package springacltutorial.services;&lt;br /&gt;&lt;br /&gt;import org.springframework.beans.factory.annotation.Autowired;&lt;br /&gt;import org.springframework.security.Authentication;&lt;br /&gt;import org.springframework.security.annotation.Secured;&lt;br /&gt;import org.springframework.security.userdetails.UserDetails;&lt;br /&gt;import org.springframework.security.context.SecurityContextHolder;&lt;br /&gt;import org.springframework.stereotype.Service;&lt;br /&gt;&lt;br /&gt;import springacltutorial.dao.ReportsDao;&lt;br /&gt;import springacltutorial.model.Report;&lt;br /&gt;import springacltutorial.model.User;&lt;br /&gt;&lt;br /&gt;@Service&lt;br /&gt;public class ReportServices {&lt;br /&gt;&lt;br /&gt; @Autowired&lt;br /&gt; ReportsDao dao;&lt;br /&gt;&lt;br /&gt; // this method should be accessible only to users with role EMPLOYEE&lt;br /&gt; public long addReport(String description) {&lt;br /&gt;    Report report = new Report();&lt;br /&gt;    report.setDescription(description);&lt;br /&gt;    Authentication auth = SecurityContextHolder.getContext().getAuthentication();&lt;br /&gt;    if (auth != null) {&lt;br /&gt;       if (auth.getPrincipal() instanceof UserDetails) {&lt;br /&gt;          report.setUser(new User(((UserDetails) auth.getPrincipal()).getUsername()));&lt;br /&gt;       } else {&lt;br /&gt;          report.setUser(new User(auth.getPrincipal().toString()));&lt;br /&gt;       }&lt;br /&gt;    }&lt;br /&gt;    dao.saveReport(report);&lt;br /&gt;    return report.getId();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; // this method may be called only by user with role MANAGER, being manager&lt;br /&gt; // of user linked to the report&lt;br /&gt; public void acceptReport(Report report) {&lt;br /&gt;&lt;br /&gt;    report.setAccepted(true);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package springacltutorial.dao;&lt;br /&gt;&lt;br /&gt;import java.util.HashMap;&lt;br /&gt;import java.util.Map;&lt;br /&gt;&lt;br /&gt;import org.springframework.stereotype.Repository;&lt;br /&gt;&lt;br /&gt;import springacltutorial.model.Report;&lt;br /&gt;&lt;br /&gt;@Repository&lt;br /&gt;public class ReportsDao {&lt;br /&gt;&lt;br /&gt;  private long sequence;&lt;br /&gt;  private Map&amp;lt;Long, Report&amp;gt; reports = new HashMap&amp;lt;Long, Report&amp;gt;();&lt;br /&gt;&lt;br /&gt;  public void saveReport(Report report) {&lt;br /&gt;      if (report.getId() == 0) {&lt;br /&gt;          report.setId(++sequence);&lt;br /&gt;      }&lt;br /&gt;      reports.put(report.getId(), report);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public Report getReportById(long reportId) {&lt;br /&gt;      return reports.get(reportId);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The method &lt;code&gt;addReport&lt;/code&gt; must make sure that the owner of the new report is the currently logged-in user. Because of this, we had to add some Spring Security specific code to get the name of current user. This seems not the ideal solution, but I cannot find anything better than this. As you also see, I use Spring 2.5 stereotype annotations, so that I don't have to enlist my beans in Spring config file. Here is the Spring config file &lt;code&gt;applicationContext-business.xml&lt;/code&gt;:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;beans xmlns="http://www.springframework.org/schema/beans"&lt;br /&gt;     xmlns:context="http://www.springframework.org/schema/context"&lt;br /&gt;     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd&lt;br /&gt;     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;context:component-scan base-package="springacltutorial"/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/beans&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;At this moment, we have most of our application ready. We won't focus on client code calling the service in this tutorial, as this doesn't matter much. Instead, let's write some tests. First the test focusing only on functional site of the service class:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package springacltutorial.services;&lt;br /&gt;&lt;br /&gt;import org.junit.Before;&lt;br /&gt;import org.junit.Test;&lt;br /&gt;import org.springframework.beans.factory.BeanFactoryUtils;&lt;br /&gt;import org.springframework.context.ApplicationContext;&lt;br /&gt;import org.springframework.context.support.ClassPathXmlApplicationContext;&lt;br /&gt;&lt;br /&gt;import springacltutorial.dao.ReportsDao;&lt;br /&gt;&lt;br /&gt;import static org.junit.Assert.*;&lt;br /&gt;&lt;br /&gt;public class ServicesTest {&lt;br /&gt;&lt;br /&gt; @Before&lt;br /&gt; public void setup() {&lt;br /&gt;    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-business.xml");&lt;br /&gt;    reportServices = (ReportServices) BeanFactoryUtils.beanOfType(context, ReportServices.class);&lt;br /&gt;    dao = (ReportsDao) BeanFactoryUtils.beanOfType(context, ReportsDao.class);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; ReportServices reportServices;&lt;br /&gt; ReportsDao dao;&lt;br /&gt;&lt;br /&gt; @Test&lt;br /&gt; public void testAddReport() {&lt;br /&gt;    long id = reportServices.addReport("springacltutorial");&lt;br /&gt;    assertEquals("springacltutorial", dao.getReportById(id).getDescription());&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Test&lt;br /&gt; public void testAcceptReport() {&lt;br /&gt;    long id = reportServices.addReport("springacltutorial");&lt;br /&gt;    assertEquals(false, dao.getReportById(id).isAccepted());&lt;br /&gt;    reportServices.acceptReport(dao.getReportById(id));&lt;br /&gt;    assertEquals(true, dao.getReportById(id).isAccepted());&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;For building and running the application, following Maven &lt;code&gt;pom.xml&lt;/code&gt; file will be helpful:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt; xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"&amp;gt;&lt;br /&gt; &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;&lt;br /&gt; &amp;lt;groupId&amp;gt;springacltutorial&amp;lt;/groupId&amp;gt;&lt;br /&gt; &amp;lt;artifactId&amp;gt;springacltutorial&amp;lt;/artifactId&amp;gt;&lt;br /&gt; &amp;lt;packaging&amp;gt;jar&amp;lt;/packaging&amp;gt;&lt;br /&gt; &amp;lt;version&amp;gt;0.0.1-SNAPSHOT&amp;lt;/version&amp;gt;&lt;br /&gt; &amp;lt;name&amp;gt;springacltutorial&amp;lt;/name&amp;gt;&lt;br /&gt; &amp;lt;dependencies&amp;gt;&lt;br /&gt;  &amp;lt;dependency&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;spring&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;2.5.5&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt;&lt;br /&gt;  &amp;lt;dependency&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;org.springframework.security&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;spring-security-core&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;2.0.4&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt;&lt;br /&gt;  &amp;lt;dependency&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;org.springframework.security&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;spring-security-core-tiger&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;2.0.4&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt;&lt;br /&gt;        &amp;lt;dependency&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;org.springframework.security&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;spring-security-acl&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;2.0.4&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt;&lt;br /&gt;  &amp;lt;dependency&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;org.aspectj&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;aspectjrt&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;1.6.1&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt;&lt;br /&gt;  &amp;lt;dependency&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;cglib&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;cglib&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;2.1_3&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt;&lt;br /&gt;  &amp;lt;dependency&amp;gt;&lt;br /&gt;   &amp;lt;groupId&amp;gt;junit&amp;lt;/groupId&amp;gt;&lt;br /&gt;   &amp;lt;artifactId&amp;gt;junit&amp;lt;/artifactId&amp;gt;&lt;br /&gt;   &amp;lt;version&amp;gt;4.5&amp;lt;/version&amp;gt;&lt;br /&gt;   &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt;&lt;br /&gt; &amp;lt;/dependencies&amp;gt;&lt;br /&gt; &amp;lt;build&amp;gt;&lt;br /&gt;  &amp;lt;plugins&amp;gt;&lt;br /&gt;   &amp;lt;plugin&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;configuration&amp;gt;&lt;br /&gt;     &amp;lt;source&amp;gt;1.5&amp;lt;/source&amp;gt;&lt;br /&gt;     &amp;lt;target&amp;gt;1.5&amp;lt;/target&amp;gt;&lt;br /&gt;    &amp;lt;/configuration&amp;gt;&lt;br /&gt;   &amp;lt;/plugin&amp;gt;&lt;br /&gt;  &amp;lt;/plugins&amp;gt;&lt;br /&gt; &amp;lt;/build&amp;gt;&lt;br /&gt;&amp;lt;/project&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;If you run the test now, it should pass. So - we have the functional application, but without any security imposed on it. Let's add authorization now.&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;Authorization&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;Now we come to the main point of this tutorial: authorization. First we add the second spring context file, named &lt;code&gt;applicationContext-security.xml&lt;/code&gt;. Initially, it will contain definition of &lt;code&gt;UserService&lt;/code&gt; (logins, passwords and roles of users):&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;beans xmlns="http://www.springframework.org/schema/beans"&lt;br /&gt;xmlns:security="http://www.springframework.org/schema/security"&lt;br /&gt;xmlns:util="http://www.springframework.org/schema/util"&lt;br /&gt;xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd&lt;br /&gt;             http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd&lt;br /&gt;             http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.1.xsd"&amp;gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;security:authentication-provider &amp;gt;&lt;br /&gt;    &amp;lt;security:password-encoder hash="plaintext"/&amp;gt;&lt;br /&gt;    &amp;lt;security:user-service&amp;gt;&lt;br /&gt;       &amp;lt;security:user name="empl1" password="pass1" authorities="ROLE_EMPLOYEE" /&amp;gt;&lt;br /&gt;       &amp;lt;security:user name="empl2" password="pass2" authorities="ROLE_EMPLOYEE" /&amp;gt;&lt;br /&gt;       &amp;lt;security:user name="empl3" password="pass3" authorities="ROLE_EMPLOYEE" /&amp;gt;&lt;br /&gt;       &amp;lt;security:user name="empl4" password="pass4" authorities="ROLE_EMPLOYEE" /&amp;gt;&lt;br /&gt;       &amp;lt;security:user name="manager1" password="pass1" authorities="ROLE_MANAGER" /&amp;gt;&lt;br /&gt;       &amp;lt;security:user name="manager2" password="pass2" authorities="ROLE_MANAGER" /&amp;gt;&lt;br /&gt;       &amp;lt;security:user name="testUser" password="" authorities=""/&amp;gt;&lt;br /&gt;    &amp;lt;/security:user-service&amp;gt;&lt;br /&gt; &amp;lt;/security:authentication-provider&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/beans&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Now we can write a test:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package springacltutorial.services;&lt;br /&gt;&lt;br /&gt;import static org.junit.Assert.assertEquals;&lt;br /&gt;import static org.junit.Assert.fail;&lt;br /&gt;&lt;br /&gt;import org.junit.Before;&lt;br /&gt;import org.junit.Test;&lt;br /&gt;import org.springframework.beans.factory.BeanFactoryUtils;&lt;br /&gt;import org.springframework.context.ApplicationContext;&lt;br /&gt;import org.springframework.context.support.ClassPathXmlApplicationContext;&lt;br /&gt;import org.springframework.security.AccessDeniedException;&lt;br /&gt;import org.springframework.security.context.SecurityContextHolder;&lt;br /&gt;import org.springframework.security.providers.UsernamePasswordAuthenticationToken;&lt;br /&gt;&lt;br /&gt;import springacltutorial.dao.ReportsDao;&lt;br /&gt;import springacltutorial.model.Report;&lt;br /&gt;&lt;br /&gt;public class ServicesAuthorizationTest {&lt;br /&gt;&lt;br /&gt;  @Before&lt;br /&gt;  public void setup() {&lt;br /&gt;      SecurityContextHolder.getContext().setAuthentication(null);&lt;br /&gt;      ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "applicationContext-business.xml", "applicationContext-security.xml" });&lt;br /&gt;      reportServices = (ReportServices) BeanFactoryUtils.beanOfType(context, ReportServices.class);&lt;br /&gt;      dao = (ReportsDao) BeanFactoryUtils.beanOfType(context, ReportsDao.class);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  ReportServices reportServices;&lt;br /&gt;  ReportsDao dao;&lt;br /&gt;&lt;br /&gt;  @Test&lt;br /&gt;  public void testAddReport() {&lt;br /&gt;      SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("empl1", "pass1"));&lt;br /&gt;      reportServices.addReport("springacltutorial");&lt;br /&gt;      // now use user without EMPLOYEE role&lt;br /&gt;      SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("testUser", ""));&lt;br /&gt;      try {&lt;br /&gt;          reportServices.addReport("springacltutorial");&lt;br /&gt;          fail("should throw AccessDeniedException");&lt;br /&gt;      } catch (AccessDeniedException e) {&lt;br /&gt;          return; // ok&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Test&lt;br /&gt;  public void testAcceptReport() {&lt;br /&gt;      // empl1 creates report&lt;br /&gt;      SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("empl1", "pass1"));&lt;br /&gt;      Report reportEmpl1 = dao.getReportById(reportServices.addReport("springacltutorial"));&lt;br /&gt;&lt;br /&gt;      // empl3 creates report&lt;br /&gt;      SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("empl3", "pass3"));&lt;br /&gt;      Report reportEmpl3 = dao.getReportById(reportServices.addReport("springacltutorial"));&lt;br /&gt;&lt;br /&gt;      // manager1 accepts report of empl1 - ok&lt;br /&gt;      SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("manager1", "pass1"));&lt;br /&gt;      assertEquals(false, reportEmpl1.isAccepted());&lt;br /&gt;      reportServices.acceptReport(reportEmpl1);&lt;br /&gt;      assertEquals(true, reportEmpl1.isAccepted());&lt;br /&gt;&lt;br /&gt;      // manager1 tries to accept report of empl3 - access denied&lt;br /&gt;      assertEquals(false, reportEmpl3.isAccepted());&lt;br /&gt;      try {&lt;br /&gt;          reportServices.acceptReport(reportEmpl3);&lt;br /&gt;          fail("manager1 cannot accept reports of empl3");&lt;br /&gt;      } catch (AccessDeniedException e) {&lt;br /&gt;          // ok&lt;br /&gt;      }&lt;br /&gt;      assertEquals(false, reportEmpl3.isAccepted());&lt;br /&gt;&lt;br /&gt;      // manager2 accepts report of empl3 - ok&lt;br /&gt;      SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken("manager2", "pass2"));&lt;br /&gt;      reportServices.acceptReport(reportEmpl3);&lt;br /&gt;      assertEquals(true, reportEmpl3.isAccepted());&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;If you run the test, it will fail, because there is no access control imposed on methods. This is what we have to do now.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Protecting &lt;code&gt;addReport&lt;/code&gt; method is simple: each user with granted role EMPLOYEE can call it; user without this role can't. So we simply specify the role based authorization access for this method. We can do it from context configuration file, but it is simpler with annoation:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@Secured("ROLE_EMPLOYEE")&lt;br /&gt;public long addReport(String description) {&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Note that default Spring Security voter which deals with roles takes into account only those configuration attributes that match the pattern "ROLE_*", this is why we called the role ROLE_EMPLOYEE, not simply EMPLOYEE.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;In case of &lt;code&gt;acceptReport&lt;/code&gt; method by analogy we can use annoation &lt;code&gt;@Secured("ROLE_MANAGER")&lt;/code&gt;. This is ok, but not enough. We have following requirement: the user may call this method if he has manager role, &lt;em&gt;and&lt;/em&gt; is the manager of the user who created the report. So we put the second configuration attribute on the method, this time called freely, let it be ACL_REPORT_ACCEPT:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@Secured( { "ROLE_MANAGER", "ACL_REPORT_ACCEPT" })&lt;br /&gt;public void acceptReport(Report report) {&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;That's all we have to do in the &lt;code&gt;ReportServices&lt;/code&gt; class. Now we switch to the configuration file &lt;code&gt;applicationContext-security.xml&lt;/code&gt; and define the mechanism for processing role-based access (with standard &lt;code&gt;RoleVoter&lt;/code&gt; - easy part) and the mechanism for processing ACL-based access (Spring Security ACL - hard part).&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;ACL mechanism&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;I assume that you already at least scanned through Spring Security user guide, and you know some basic notions of ACL concept described there. I must say that I found the section in user guide describing ACLs not clear enough. It does not highlight the key interfaces and relationships betweent them, but instead it jumps fast into the JDBC-based implementation, desribing the 4 tables that must be set up for this implementation. This gives the impression that this is the only way of using ACLs, and that the model of those tables actually the model of ACLs. But this is not. The JDBC-based implementation is, as far as I understand, the production-ready implementation, and uses some optimisations, like efficient SQL queries, caches, lazy loading etc. The database model is not in 1:1 relationship to the core ACL model.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;I prefer approaching it in a different way: first learn the core model (interfaces). Than look at some extremely simple implementation, without any optimisation, persistence etc (if possible) and check if it works and if the model/API fits my expectations. Only then look at production-ready implementations, with all their complexity.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;So let's look at ACL model. The main interface is &lt;code&gt;Acl&lt;/code&gt;, representing access control list for given domain object. It contains list of &lt;code&gt;AccessControlEntry&lt;/code&gt; objects, and the &lt;code&gt;ObjectIdentity&lt;/code&gt;. Interface &lt;code&gt;ObjectIdentity&lt;/code&gt; provides indirect represention of domain object. &lt;code&gt;Acl&lt;/code&gt; doesn't keep direct reference to domain object for which this ACL was defined - instead it uses &lt;code&gt;ObjectIdentity&lt;/code&gt;. &lt;code&gt;ObjectIdentity&lt;/code&gt; knows the type of Java class of the domain object, and identifier of the specific instance of this class. How this identifier is defined and retrieved depends on implementation. Default implementation assumes that domain object has the method &lt;code&gt;getId()&lt;/code&gt;, returning type compatible with &lt;code&gt;long&lt;/code&gt;. &lt;code&gt;AccessControlEntry&lt;/code&gt; (ACE) represent individual permission assignment. It has unique &lt;code&gt;id&lt;/code&gt;, reference to &lt;code&gt;Acl&lt;/code&gt; itself (note: bidirectional relationship between ACL and each ACE), the &lt;code&gt;Permission&lt;/code&gt;, and the &lt;code&gt;Sid&lt;/code&gt;. Interface &lt;code&gt;Sid&lt;/code&gt; (stands for: Secure Identity) is a kind of common abstraction for user names (&lt;code&gt;PrincipalSid&lt;/code&gt; implementation) and user roles (&lt;code&gt;GrantedAuthoritySid&lt;/code&gt; implementation). So here &lt;code&gt;Sid&lt;/code&gt; represents user (or role) to whom the &lt;code&gt;Permission&lt;/code&gt; is granted (or revoked, depending on &lt;code&gt;granting&lt;/code&gt; flag). So each ACE means: the specific &lt;code&gt;Sid&lt;/code&gt; (user or role) is granted or revoked the specific &lt;code&gt;Permission&lt;/code&gt; (read, write, delete, accept, ...) on the domain object for which the ACL is defined.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Collection of ACEs and &lt;code&gt;ObjectIdentity&lt;/code&gt; are two main components of &lt;code&gt;Acl&lt;/code&gt;. Additionally &lt;code&gt;Acl&lt;/code&gt;s can build inheritance trees, so each &lt;code&gt;Acl&lt;/code&gt; can optionally reference its parent (if implementation supports it). Also optionally, &lt;code&gt;Acl&lt;/code&gt; can have the owner, represented by &lt;code&gt;Sid&lt;/code&gt; object, if implementation supports it. Each ACE must be immutable. ACL can be mutable (for this purpuse there is a specific subinterface: &lt;code&gt;MutableAcl&lt;/code&gt;, with methods like &lt;code&gt;insertAce&lt;/code&gt;, &lt;code&gt;deleteAce&lt;/code&gt;). &lt;code&gt;Acl&lt;/code&gt; contains one "real" method: &lt;code&gt;isGranted&lt;/code&gt;, containing actual authorization logic.&lt;/p&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Iu6FMYlWXN4/SPSkzGaRYqI/AAAAAAAAAVI/ivw1k4s-Kow/s1600-h/SpringSecurityAclModel.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_Iu6FMYlWXN4/SPSkzGaRYqI/AAAAAAAAAVI/ivw1k4s-Kow/s320/SpringSecurityAclModel.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5257007862849299106" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;ACL model interfaces constitute one side of the whole picture. The second side is ACL access API. The central interface here is &lt;code&gt;AclService&lt;/code&gt;, providing retrieval of ACLs for given &lt;code&gt;ObjectIdentity&lt;/code&gt;, through the set of overloaded &lt;code&gt;readAclById&lt;/code&gt; and &lt;code&gt;readAclsById&lt;/code&gt; methods. The whole picture is completed by the &lt;code&gt;AclEntryVoter&lt;/code&gt; class, which is an ACL-specific implementation of the standard Spring Security &lt;code&gt;AccessDecisionVoter&lt;/code&gt; interface. It is responsible for giving "opinions" (votes) about whether the current user should be granted access for protected resource or not (opinion may be of three types: "grant him access", "deny access", or "that's not my business, so I abstain from voting"). The final decision about granting user the access is taken by &lt;code&gt;AccessDecisionManager&lt;/code&gt;, which takes into account all the votes of all registered voters (depending on different implementations, the final decision may differ).&lt;/p&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_Iu6FMYlWXN4/SPSqZVIUN6I/AAAAAAAAAVQ/EPn94qu28B4/s1600-h/SpringSecurityModel2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_Iu6FMYlWXN4/SPSqZVIUN6I/AAAAAAAAAVQ/EPn94qu28B4/s320/SpringSecurityModel2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5257014017193686946" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;h3&gt;How does it all work?&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;Let's take the method &lt;code&gt;acceptReport&lt;/code&gt; from our tutorial application. The method itself is the protected resource, and we want to restrict access to it only to users with MANAGER role, and what's more only actual manager of the user who created the report should be able to accept it. As you remember, we put on the method the restriction annotation with two configuration attributes: &lt;code&gt;@Secured( { "ROLE_MANAGER", "ACL_REPORT_ACCEPT" })&lt;/code&gt;. For that to work, we have to define two voters. First is the standard &lt;code&gt;RoleVoter&lt;/code&gt;. When &lt;code&gt;AccessDesicionManager&lt;/code&gt; asks this voter about its opinion on the first configuration attribute (ROLE_MANAGER), this voter will see that the parameter starts with "ROLE_" prefix, so it will check if the currently operating user has the ROLE_MANAGER role. If it has this role, voter will vote for "grant him access". Otherwise, it will vote for "deny access". Then &lt;code&gt;AccessDesicionManager&lt;/code&gt; asks this voter about its opinion on the second configuration attribute (ACL_REPORT_ACCEPT), and the voter will abstain from voting, because it does not match the ROLE_* pattern. This way we have done with the role checking.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Now we have to define the second voter, this time of type &lt;code&gt;AclEntryVoter&lt;/code&gt;, with following configuration: reference to &lt;code&gt;AclService&lt;/code&gt;; the string with configuration attribute that should trigger the voter to actually vote ("ACL_REPORT_ACCEPT" in our case); the list of required permissions that must be found in ACL for this user to grant him access; and the Java type of the domain object, for which the ACL will be used. During method call, the voter analyses all the method parameters and searches for the one compatible with the specified Java type. Once found, the voter will ask the actual object passed under this parameter for the identificator (how? we said earlier: by deafult, it expects the object to have method &lt;code&gt;getId()&lt;/code&gt; returning type compatible with &lt;code&gt;long&lt;/code&gt;). Having Java type and id, the voter constructs &lt;code&gt;ObjectIdentification&lt;/code&gt; from them and then asks &lt;code&gt;AclService&lt;/code&gt; for the &lt;code&gt;Acl&lt;/code&gt; linked to this &lt;code&gt;ObjectIdentification&lt;/code&gt;. After obtaining &lt;code&gt;Acl&lt;/code&gt;, it calls its method &lt;code&gt;isGranted&lt;/code&gt;, passing the list of required permissions as configured for this voter, and array of &lt;code&gt;Sid&lt;/code&gt;s of current user. The outcome of this method (boolean value) decides on the voter outcome (grant or deny). If the configuration attribute passed to this voter during call from &lt;code&gt;AccessDesicionManager&lt;/code&gt; is different than the one for which this voter is configured, the voter will abstain from voting. In our example application the &lt;code&gt;AccessDesicionManager&lt;/code&gt; will ask the &lt;code&gt;AclEntryVoter&lt;/code&gt; first for ROLE_MANAGER, and voter will abstain, and then ask for ACL_REPORT_ACCEPT and this time voter will voter "grant" or "deny", depending on current user, the domain object passed as protected method argument, and the ACL configurations. After calling two voters for two configuration parameters, the &lt;code&gt;AccessDesicionManager&lt;/code&gt; will finally decide on granting access or not, based on collected votes.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;As you see, we have to configure following beans in Spring context: the &lt;code&gt;AccessDecisionManager&lt;/code&gt; implementation fed with two voters, namely &lt;code&gt;RolesVoter&lt;/code&gt; and &lt;code&gt;AclEntryVoter&lt;/code&gt;; and the &lt;code&gt;AclService&lt;/code&gt; implementation to be used by &lt;code&gt;AclEntryVoter&lt;/code&gt;. Additionally we can define our custom ACCEPT &lt;code&gt;Permission&lt;/code&gt; (there are five built-in permissions: READ, WRITE, CREATE, DELETE, ADMINISTRATION - we may use any of it, but neither fits perfectly our needs, so we can easily define our own).&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Spring security provides us with several &lt;code&gt;AccessDecisionManager&lt;/code&gt; implementations - we will use &lt;code&gt;UnanimousBased&lt;/code&gt;, as we require that &lt;em&gt;both&lt;/em&gt; voters vote for "yes" before we let the method call continue. Spring Securiry contains also one production-ready implementation of &lt;code&gt;AclService&lt;/code&gt;, namely &lt;code&gt;JdbcAclService&lt;/code&gt; and its subclass &lt;code&gt;JdbcMutableAclService&lt;/code&gt;. This class stores and retrieves ACLs to and from database. It requires the predefined structure of 4 tables - you may find details in Spring Security documentation. Configuration of this implementation is complex, too complex for simple prototyping solutions in my opinion. Because of this, we're going to implement this service on our own, to use in-memory stored ACLs. We will also write our own implementation of &lt;code&gt;Acl&lt;/code&gt;, beacue the built-in &lt;code&gt;AclImpl&lt;/code&gt; implements several other interfaces, which makes it unnecessarily complicated.&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;It's right time to implement it&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;First we code our ACCEPT permission, extending the built-in &lt;code&gt;BasePermission&lt;/code&gt; class:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package springacltutorial.infrastructure;&lt;br /&gt;&lt;br /&gt;import org.springframework.security.acls.Permission;&lt;br /&gt;import org.springframework.security.acls.domain.BasePermission;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* Adds ACCEPT permission to standard set of Spring Security permissions.&lt;br /&gt;* Based on BasePermission code.&lt;br /&gt;*/&lt;br /&gt;public class ExtendedPermission extends BasePermission {&lt;br /&gt;&lt;br /&gt;private static final long serialVersionUID = 1L;&lt;br /&gt;&lt;br /&gt;public static final Permission ACCEPT = new ExtendedPermission(1 &amp;lt;&amp;lt; 5, 'a'); // 32&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* Registers the public static permissions defined on this class. This is&lt;br /&gt;* mandatory so that the static methods will operate correctly. (copied from&lt;br /&gt;* super class)&lt;br /&gt;*/&lt;br /&gt;static {&lt;br /&gt;  registerPermissionsFor(ExtendedPermission.class);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private ExtendedPermission(int mask, char code) {&lt;br /&gt;  super(mask, code);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The char code is used only for textual-representation of the permission, and has no influence on any logic. &lt;code&gt;BasePermission&lt;/code&gt; uses capital letter 'A' for ADMINISTRATION, so I used 'a' for ACCEPT. As I said, it really doesn't matter. We used sixth bit (&lt;code&gt;1 &amp;lt;&amp;lt; 5&lt;/code&gt;) in the internal &lt;code&gt;Permission&lt;/code&gt; implementation (first five bits are used by built-in types). I will not dig into internals of &lt;code&gt;Permissions&lt;/code&gt; concept, as it is well described in Spring security documentation and not very difficult. Now we turn our attation to &lt;code&gt;Acl&lt;/code&gt; implementation:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package springacltutorial.infrastructure;&lt;br /&gt;&lt;br /&gt;import org.springframework.security.acls.AccessControlEntry;&lt;br /&gt;import org.springframework.security.acls.Acl;&lt;br /&gt;import org.springframework.security.acls.NotFoundException;&lt;br /&gt;import org.springframework.security.acls.Permission;&lt;br /&gt;import org.springframework.security.acls.domain.AuditLogger;&lt;br /&gt;import org.springframework.security.acls.domain.ConsoleAuditLogger;&lt;br /&gt;import org.springframework.security.acls.objectidentity.ObjectIdentity;&lt;br /&gt;import org.springframework.security.acls.sid.Sid;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* Very simple implementation of Acl interface, based on&lt;br /&gt;* org.springframework.security.acls.domain.AclImpl source (mainly the isGranted&lt;br /&gt;* method code). This implementation neither use owner concept nor parent&lt;br /&gt;* concept.&lt;br /&gt;*/&lt;br /&gt;public class SimpleAclImpl implements Acl {&lt;br /&gt;&lt;br /&gt;private static final long serialVersionUID = 1L;&lt;br /&gt;private ObjectIdentity oi;&lt;br /&gt;private AccessControlEntry[] aces;&lt;br /&gt;private transient AuditLogger auditLogger = new ConsoleAuditLogger();&lt;br /&gt;&lt;br /&gt;public SimpleAclImpl(ObjectIdentity oi, AccessControlEntry[] aces) {&lt;br /&gt;  this.oi = oi;&lt;br /&gt;  this.aces = aces;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public AccessControlEntry[] getEntries() {&lt;br /&gt;  return aces;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public ObjectIdentity getObjectIdentity() {&lt;br /&gt;  return oi;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public Sid getOwner() {&lt;br /&gt;  return null; // owner concept is optional, we don't use it&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public Acl getParentAcl() {&lt;br /&gt;  return null; // we don't use inheritance&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public boolean isEntriesInheriting() {&lt;br /&gt;  return false; // we don't use inheritance&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public boolean isGranted(Permission[] permission, Sid[] sids, boolean administrativeMode) throws NotFoundException {&lt;br /&gt;&lt;br /&gt;  AccessControlEntry firstRejection = null;&lt;br /&gt;&lt;br /&gt;  for (int i = 0; i &amp;lt; permission.length; i++) {&lt;br /&gt;      for (int x = 0; x &amp;lt; sids.length; x++) {&lt;br /&gt;          // Attempt to find exact match for this permission mask and SID&lt;br /&gt;          boolean scanNextSid = true;&lt;br /&gt;&lt;br /&gt;          for (int j = 0; j &amp;lt; aces.length; j++) {&lt;br /&gt;              AccessControlEntry ace = (AccessControlEntry) aces[j];&lt;br /&gt;&lt;br /&gt;              if ((ace.getPermission().getMask() == permission[i].getMask()) &amp;amp;&amp;amp; ace.getSid().equals(sids[x])) {&lt;br /&gt;                  // Found a matching ACE, so its authorization decision&lt;br /&gt;                  // will prevail&lt;br /&gt;                  if (ace.isGranting()) {&lt;br /&gt;                      // Success&lt;br /&gt;                      if (!administrativeMode) {&lt;br /&gt;                          auditLogger.logIfNeeded(true, ace);&lt;br /&gt;                      }&lt;br /&gt;&lt;br /&gt;                      return true;&lt;br /&gt;                  } else {&lt;br /&gt;                      // Failure for this permission, so stop search&lt;br /&gt;                      // We will see if they have a different permission&lt;br /&gt;                      // (this permission is 100% rejected for this SID)&lt;br /&gt;                      if (firstRejection == null) {&lt;br /&gt;                          // Store first rejection for auditing reasons&lt;br /&gt;                          firstRejection = ace;&lt;br /&gt;                      }&lt;br /&gt;&lt;br /&gt;                      scanNextSid = false; // helps break the loop&lt;br /&gt;&lt;br /&gt;                      break; // exit "aces" loop&lt;br /&gt;                  }&lt;br /&gt;              }&lt;br /&gt;          }&lt;br /&gt;&lt;br /&gt;          if (!scanNextSid) {&lt;br /&gt;              break; // exit SID for loop (now try next permission)&lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if (firstRejection != null) {&lt;br /&gt;      // We found an ACE to reject the request at this point, as no&lt;br /&gt;      // other ACEs were found that granted a different permission&lt;br /&gt;      if (!administrativeMode) {&lt;br /&gt;          auditLogger.logIfNeeded(false, firstRejection);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      return false;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  throw new NotFoundException("Unable to locate a matching ACE for passed permissions and SIDs");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public boolean isSidLoaded(Sid[] sids) {&lt;br /&gt;  // we use in-memory structure, not external DB, so all entries are&lt;br /&gt;  // always loaded&lt;br /&gt;  // (if I correctly understand meaning of this method)&lt;br /&gt;  return true;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;As you see, it is pretty straightforward. The only logic is contained in &lt;code&gt;isGranted&lt;/code&gt; method - which is a slightly simplified copy of the code from the standard Spring Security &lt;code&gt;AclImpl&lt;/code&gt; class. The usage of &lt;code&gt;AuditLogger&lt;/code&gt; is not necessary, but it was already there, so I decided to use it - it may be helpful to see on the console what's going on inside.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Finally, we need &lt;code&gt;AclService&lt;/code&gt; implementation:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package springacltutorial.infrastructure;&lt;br /&gt;&lt;br /&gt;import java.util.HashMap;&lt;br /&gt;import java.util.Map;&lt;br /&gt;&lt;br /&gt;import javax.annotation.PostConstruct;&lt;br /&gt;&lt;br /&gt;import org.springframework.security.acls.AccessControlEntry;&lt;br /&gt;import org.springframework.security.acls.Acl;&lt;br /&gt;import org.springframework.security.acls.AclService;&lt;br /&gt;import org.springframework.security.acls.NotFoundException;&lt;br /&gt;import org.springframework.security.acls.domain.AccessControlEntryImpl;&lt;br /&gt;import org.springframework.security.acls.objectidentity.ObjectIdentity;&lt;br /&gt;import org.springframework.security.acls.objectidentity.ObjectIdentityImpl;&lt;br /&gt;import org.springframework.security.acls.sid.PrincipalSid;&lt;br /&gt;import org.springframework.security.acls.sid.Sid;&lt;br /&gt;import org.springframework.stereotype.Service;&lt;br /&gt;import org.springframework.util.Assert;&lt;br /&gt;&lt;br /&gt;import springacltutorial.model.User;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* The simplest possible implementation of AclService interface. Uses in-memory&lt;br /&gt;* collection of ACLs, providing fast and easy access to them.&lt;br /&gt;*&lt;br /&gt;*/&lt;br /&gt;@Service&lt;br /&gt;public class InMemoryAclServiceImpl implements AclService {&lt;br /&gt;&lt;br /&gt;Map&amp;lt;ObjectIdentity, Acl&amp;gt; acls = new HashMap&amp;lt;ObjectIdentity, Acl&amp;gt;();&lt;br /&gt;&lt;br /&gt;@PostConstruct&lt;br /&gt;public void initializeACLs() {&lt;br /&gt;  // create ACLs according to requirements of tutorial application&lt;br /&gt;  ObjectIdentity user1 = new ObjectIdentityImpl(User.class, "empl1");&lt;br /&gt;  ObjectIdentity user2 = new ObjectIdentityImpl(User.class, "empl2");&lt;br /&gt;  ObjectIdentity user3 = new ObjectIdentityImpl(User.class, "empl3");&lt;br /&gt;  ObjectIdentity user4 = new ObjectIdentityImpl(User.class, "empl4");&lt;br /&gt;&lt;br /&gt;  Acl acl1 = new SimpleAclImpl(user1, new AccessControlEntry[1]);&lt;br /&gt;  acl1.getEntries()[0] = new AccessControlEntryImpl("ace1", acl1, new PrincipalSid("manager1"), ExtendedPermission.ACCEPT, true, true, true);&lt;br /&gt;  acls.put(acl1.getObjectIdentity(), acl1);&lt;br /&gt;  Acl acl2 = new SimpleAclImpl(user2, new AccessControlEntry[1]);&lt;br /&gt;  acl2.getEntries()[0] = new AccessControlEntryImpl("ace2", acl2, new PrincipalSid("manager1"), ExtendedPermission.ACCEPT, true, true, true);&lt;br /&gt;  acls.put(acl2.getObjectIdentity(), acl2);&lt;br /&gt;  Acl acl3 = new SimpleAclImpl(user3, new AccessControlEntry[1]);&lt;br /&gt;  acl3.getEntries()[0] = new AccessControlEntryImpl("ace3", acl3, new PrincipalSid("manager2"), ExtendedPermission.ACCEPT, true, true, true);&lt;br /&gt;  acls.put(acl3.getObjectIdentity(), acl3);&lt;br /&gt;  Acl acl4 = new SimpleAclImpl(user4, new AccessControlEntry[1]);&lt;br /&gt;  acl4.getEntries()[0] = new AccessControlEntryImpl("ace4", acl4, new PrincipalSid("manager2"), ExtendedPermission.ACCEPT, true, true, true);&lt;br /&gt;  acls.put(acl4.getObjectIdentity(), acl4);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public ObjectIdentity[] findChildren(ObjectIdentity parentIdentity) {&lt;br /&gt;  // I'm not really sure what this method should do...&lt;br /&gt;  throw new UnsupportedOperationException("Not implemented");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public Acl readAclById(ObjectIdentity object, Sid[] sids) throws NotFoundException {&lt;br /&gt;  Map&amp;lt;ObjectIdentity, Acl&amp;gt; map = readAclsById(new ObjectIdentity[] { object }, sids);&lt;br /&gt;  Assert.isTrue(map.containsKey(object), "There should have been an Acl entry for ObjectIdentity " + object);&lt;br /&gt;&lt;br /&gt;  return map.get(object);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public Acl readAclById(ObjectIdentity object) throws NotFoundException {&lt;br /&gt;  return readAclById(object, null);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public Map&amp;lt;ObjectIdentity, Acl&amp;gt; readAclsById(ObjectIdentity[] objects) throws NotFoundException {&lt;br /&gt;  return readAclsById(objects, null);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public Map&amp;lt;ObjectIdentity, Acl&amp;gt; readAclsById(ObjectIdentity[] objects, Sid[] sids) throws NotFoundException {&lt;br /&gt;  Map&amp;lt;ObjectIdentity, Acl&amp;gt; result = new HashMap&amp;lt;ObjectIdentity, Acl&amp;gt;();&lt;br /&gt;&lt;br /&gt;  for (ObjectIdentity object : objects) {&lt;br /&gt;      if (acls.containsKey(object)) {&lt;br /&gt;          result.put(object, acls.get(object));&lt;br /&gt;      } else {&lt;br /&gt;          throw new NotFoundException("Unable to find ACL information for object identity '" + object.toString() + "'");&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return result;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;As you see, I put the initialization method which populates the &lt;code&gt;acls&lt;/code&gt; map with data needed for this tutorial (in any real-life application such configuration wouldn't be hardcoded in Java class). We define four ACLs with single ACE each: Two for manager1 (accept reports of empl1 and empl2) and similar two for manager2 (accept reports of empl3 and empl4). Note that the requirement of bidirectional relationship between ACL and each ACE makes the initialization code more verbose (we cannot fully initilize ACL in one line).&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;We are almost done, but there are two problems left&lt;/h3&gt;&lt;br /&gt;&lt;p&gt;First problem: we don't want to define the ACL for each report, because reports will be created on the fly by system users, and we don't want to be forced to keep and maintain separate ACL for each report. On the other hand, users are not added and removed from the system too often, so &lt;code&gt;User&lt;/code&gt; object is perfect choice as a domain object for which ACLs will be defined - and this is what we did in the initialization method of our service. So now we will have to configure our &lt;code&gt;AclEntryVoter&lt;/code&gt; passing it &lt;code&gt;User.class&lt;/code&gt; as a configuration parameter. This means, that during secured method call the voter will scan all method parameters searching for &lt;code&gt;User&lt;/code&gt; type (I described this procedure earlier). You see the problem? Our method &lt;code&gt;acceptReport&lt;/code&gt; does not have &lt;code&gt;User&lt;/code&gt; parameter - it takes only &lt;code&gt;Report&lt;/code&gt;! Three solutions come to my mind. First: define ACLs for reports, not for users. But as I said earlier, this would be impractical. Second: add second parameter of type &lt;code&gt;User&lt;/code&gt; to the method. I don't like it too: I don't like the fact that I have to tweak service interface for security framwork needs, and besides this would be dangerous - what if the caller passes as argument the user not being really owner of the report? The method can obviously do the check that the user passed as argument is equal to the user stored in report as owner - but this is bad too. Third solution: overwrite the way the voter retrieves the domain object. This seems the best one, so we'll use it. Normally, the voter would take the Report object passed as the &lt;code&gt;acceptReport&lt;/code&gt; method argument. We don't want this Report object to be passed to &lt;code&gt;AclService&lt;/code&gt;: instead we would like to call the &lt;code&gt;getUser()&lt;/code&gt; method on this object and pass the User object returned from this method. Fortunately, the &lt;code&gt;AclEntryVoter&lt;/code&gt; contains property &lt;code&gt;internalMethod&lt;/code&gt;, which does exactly that: it keeps the name of the method that must be called on domain object to retrieve actual object to be passed to the service. So we set this property to the value "getUser".&lt;/p&gt;&lt;p&gt;&lt;br /&gt;This solves the first problem. The second problem we have to deal with is following: as you remeber, the default implementation of &lt;code&gt;AclEntryVoter&lt;/code&gt; expects that each domain object has a method &lt;code&gt;getId&lt;/code&gt; returning type compatible with long, for building the &lt;code&gt;ObjectIdentity&lt;/code&gt; and finding ACL bound to it. Our &lt;code&gt;User&lt;/code&gt; domain object does not have such method. It's ID is a login of String type (like "empl1"). Having it in mind, I declared the ACLs in the &lt;code&gt;InMemoryAclServiceImpl&lt;/code&gt; initilization method with those string-based identifiers. There are two possible solutions for the problem. First: refactor &lt;code&gt;User&lt;/code&gt; class and ACLs to use long-based identifiers. This is a good solution, and in production system I would problably go this way. Using artificial identifiers is in most cases the best way to go. Here though we'll use second solution: change the way Spring Security identifies the domain object. In this case it is easy, because &lt;code&gt;AclEntryVoter&lt;/code&gt; uses the &lt;code&gt;ObjectIdentityRetrievalStrategy&lt;/code&gt;, so we can simply implement this interface and plug it in into our voter using Spring context configuration.&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package springacltutorial.infrastructure;&lt;br /&gt;&lt;br /&gt;import org.springframework.security.acls.objectidentity.ObjectIdentity;&lt;br /&gt;import org.springframework.security.acls.objectidentity.ObjectIdentityImpl;&lt;br /&gt;import org.springframework.security.acls.objectidentity.ObjectIdentityRetrievalStrategy;&lt;br /&gt;import springacltutorial.model.User;&lt;br /&gt;&lt;br /&gt;/** overwrite the strategy: build ObjectIdentity based on user object login property,&lt;br /&gt; *  instead of Spring Security default getId() call&lt;br /&gt; */&lt;br /&gt;public class UserNameRetrievalStrategy implements ObjectIdentityRetrievalStrategy {&lt;br /&gt;&lt;br /&gt;    public ObjectIdentity getObjectIdentity(Object domainObject) {&lt;br /&gt;        User user = (User) domainObject;&lt;br /&gt;        return new ObjectIdentityImpl(User.class, user.getLogin());&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;The last thing to do is Spring context configuration:&lt;/p&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;beans xmlns="http://www.springframework.org/schema/beans"&lt;br /&gt;xmlns:security="http://www.springframework.org/schema/security"&lt;br /&gt;xmlns:util="http://www.springframework.org/schema/util"&lt;br /&gt;xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&lt;br /&gt;xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd&lt;br /&gt;             http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd&lt;br /&gt;             http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.1.xsd"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;security:authentication-provider &amp;gt;&lt;br /&gt;   &amp;lt;security:password-encoder hash="plaintext"/&amp;gt;&lt;br /&gt;   &amp;lt;security:user-service&amp;gt;&lt;br /&gt;       &amp;lt;security:user name="empl1" password="pass1" authorities="ROLE_EMPLOYEE" /&amp;gt;&lt;br /&gt;       &amp;lt;security:user name="empl2" password="pass2" authorities="ROLE_EMPLOYEE" /&amp;gt;&lt;br /&gt;       &amp;lt;security:user name="empl3" password="pass3" authorities="ROLE_EMPLOYEE" /&amp;gt;&lt;br /&gt;       &amp;lt;security:user name="empl4" password="pass4" authorities="ROLE_EMPLOYEE" /&amp;gt;&lt;br /&gt;       &amp;lt;security:user name="manager1" password="pass1" authorities="ROLE_MANAGER" /&amp;gt;&lt;br /&gt;       &amp;lt;security:user name="manager2" password="pass2" authorities="ROLE_MANAGER" /&amp;gt;&lt;br /&gt;       &amp;lt;security:user name="testUser" password="" authorities=""/&amp;gt;&lt;br /&gt;    &amp;lt;/security:user-service&amp;gt;&lt;br /&gt;&amp;lt;/security:authentication-provider&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;security:global-method-security secured-annotations="enabled" access-decision-manager-ref="businessAccessDecisionManager"/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- Decision manager uses two voters: one is role-based, another is ACL-based --&amp;gt;&lt;br /&gt;&amp;lt;bean id="businessAccessDecisionManager" class="org.springframework.security.vote.UnanimousBased"&amp;gt;&lt;br /&gt;   &amp;lt;property name="allowIfAllAbstainDecisions" value="true"/&amp;gt;&lt;br /&gt;   &amp;lt;property name="decisionVoters"&amp;gt;&lt;br /&gt;       &amp;lt;list&amp;gt;&lt;br /&gt;           &amp;lt;bean id="roleVoter" class="org.springframework.security.vote.RoleVoter"/&amp;gt;&lt;br /&gt;           &amp;lt;ref local="aclReportAcceptVoter"/&amp;gt;        &lt;br /&gt;       &amp;lt;/list&amp;gt;&lt;br /&gt;   &amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;/bean&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- An access decision voter that reads ACL_REPORT_ACCEPT configuration settings --&amp;gt;&lt;br /&gt;&amp;lt;bean id="aclReportAcceptVoter" class="org.springframework.security.vote.AclEntryVoter"&amp;gt;&lt;br /&gt;&amp;lt;constructor-arg ref="aclService"/&amp;gt;&lt;br /&gt;&amp;lt;constructor-arg value="ACL_REPORT_ACCEPT"/&amp;gt;&lt;br /&gt;&amp;lt;constructor-arg&amp;gt;&lt;br /&gt; &amp;lt;list&amp;gt;&lt;br /&gt;   &amp;lt;util:constant id="acceptPermission" static-field="springacltutorial.infrastructure.ExtendedPermission.ACCEPT"/&amp;gt;&lt;br /&gt; &amp;lt;/list&amp;gt;&lt;br /&gt;&amp;lt;/constructor-arg&amp;gt;&lt;br /&gt;&amp;lt;property name="internalMethod" value="getUser"/&amp;gt;&lt;br /&gt;&amp;lt;property name="objectIdentityRetrievalStrategy"&amp;gt;&lt;br /&gt;    &amp;lt;bean class="springacltutorial.infrastructure.UserNameRetrievalStrategy"/&amp;gt;&lt;br /&gt;&amp;lt;/property&amp;gt;&lt;br /&gt;&amp;lt;!-- this is tricky! We have to use Report here, so that voter find it in protected method parameters; "internalMethod" will convert it to User  --&amp;gt;&lt;br /&gt;&amp;lt;property name="processDomainObjectClass" value="springacltutorial.model.Report"/&amp;gt;&lt;br /&gt;&amp;lt;/bean&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;bean id="aclService" class="springacltutorial.infrastructure.InMemoryAclServiceImpl"/&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/beans&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;You can run again the &lt;code&gt;ServicesAuthorizationTest&lt;/code&gt; now: it should pass, meaning that Spring Security properly controls the access to methods based on ACL. Well done!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8828114559044739709-6703613004446870079?l=grzegorzborkowski.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://grzegorzborkowski.blogspot.com/feeds/6703613004446870079/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8828114559044739709&amp;postID=6703613004446870079' title='45 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8828114559044739709/posts/default/6703613004446870079'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8828114559044739709/posts/default/6703613004446870079'/><link rel='alternate' type='text/html' href='http://grzegorzborkowski.blogspot.com/2008/10/spring-security-acl-very-basic-tutorial.html' title='Spring Security ACL - very basic tutorial'/><author><name>Grzegorz Borkowski</name><uri>http://www.blogger.com/profile/16063009050017401077</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='23' src='http://4.bp.blogspot.com/_Iu6FMYlWXN4/SeD5_rszBpI/AAAAAAAAAkQ/17qtFY-14Ag/S220/DSC_4313_1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_Iu6FMYlWXN4/SPSkzGaRYqI/AAAAAAAAAVI/ivw1k4s-Kow/s72-c/SpringSecurityAclModel.png' height='72' width='72'/><thr:total>45</thr:total></entry></feed>
