Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>You are quite right to be concerned - static method calls are particularly problematic for unit testing as you cannot easily mock your dependencies. What I am going to show you is how to let the Spring IoC container do the dirty work for you, leaving you with neat, testable code. SecurityContextHolder is a framework class and while it may be ok for your low-level security code to be tied to it, you probably want to expose a neater interface to your UI components (i.e. controllers).</p> <p>cliff.meyers mentioned one way around it - create your own "principal" type and inject an instance into consumers. The Spring &lt;<a href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-factory-scopes-other-injection" rel="nofollow noreferrer">aop:scoped-proxy</a>/> tag introduced in 2.x combined with a request scope bean definition, and the factory-method support may be the ticket to the most readable code.</p> <p>It could work like following:</p> <pre><code>public class MyUserDetails implements UserDetails { // this is your custom UserDetails implementation to serve as a principal // implement the Spring methods and add your own methods as appropriate } public class MyUserHolder { public static MyUserDetails getUserDetails() { Authentication a = SecurityContextHolder.getContext().getAuthentication(); if (a == null) { return null; } else { return (MyUserDetails) a.getPrincipal(); } } } public class MyUserAwareController { MyUserDetails currentUser; public void setCurrentUser(MyUserDetails currentUser) { this.currentUser = currentUser; } // controller code } </code></pre> <p>Nothing complicated so far, right? In fact you probably had to do most of this already. Next, in your bean context define a request-scoped bean to hold the principal:</p> <pre><code>&lt;bean id="userDetails" class="MyUserHolder" factory-method="getUserDetails" scope="request"&gt; &lt;aop:scoped-proxy/&gt; &lt;/bean&gt; &lt;bean id="controller" class="MyUserAwareController"&gt; &lt;property name="currentUser" ref="userDetails"/&gt; &lt;!-- other props --&gt; &lt;/bean&gt; </code></pre> <p>Thanks to the magic of the aop:scoped-proxy tag, the static method getUserDetails will be called every time a new HTTP request comes in and any references to the currentUser property will be resolved correctly. Now unit testing becomes trivial:</p> <pre><code>protected void setUp() { // existing init code MyUserDetails user = new MyUserDetails(); // set up user as you wish controller.setCurrentUser(user); } </code></pre> <p>Hope this helps!</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload