Subject.execute* runs in the existing thread.  It does not dispatch to
another thread.

Per Peter's last suggestion (about Closures automatically implementing
Runnable), try this:

subject.execute { doBootstrap(); }

Nice and short.  Gotta love Groovy ;)

- Les

On Thu, Oct 29, 2009 at 12:57 PM, Scott Ryan <[email protected]> wrote:
> That process does not actually work.  When the bootstrap is called (not by
> me but by the framework)  the thread is already loaded with much of the
> grails stuff.  If I spin off a new thread as you suggest (In Grails/Groovy I
> have to use Thread.start) all of the grails loaded stuff on the thread is
> not there and none of my bootstrap stuff works.   I don't control the entry
> to the bootstrap and I need the stuff that is on the thread when I enter the
> bootstrap.    I was not able to use your Runnable strategy as groovy does
> not like the syntax.   Also if I try to clear the thread when i am done
> threadState.clear(); it also unloads the other security managers from the
> thread which were already there and I get some errors.  Most of the code
> works ok.
>
> I will try to use your subject.execute strategy but I need to figure out how
> to run on the existing thread so i can keep the grails stuff.
>
> If there a way to tie the subject to the existing thread?  I know i can't
> use the manual thread stuff and keep a clean system but this is only for
> development.
>
> I will continue to experiment with different strategies.
>
> I assume the thread I am on is destroyed after the bootstrap process anyway
> so the risk is pretty minimal and this is only used in development.
>
> Scott Ryan
> President/CTO
> Soaring Eagle L.L.C.
> [email protected]
> (303) 263-3044
>
> On Oct 29, 2009, at 10:46 AM, Les Hazlewood wrote:
>
>> Just a note - you should not use the ThreadState stuff as shown in
>> your code sample.  Instead use my example that executes a Runnable and
>> calls the 'doBootstrap' method (that you implement).
>>
>> As documented in the Subject wiki page, if you use ThreadState
>> objects, you _must_ ensure that a thread is cleaned up after use.
>> Just calling ThreadState.bind() is not good enough - you must also
>> clear() it at the end of the thread execution.
>>
>> The Subject.execute* methods perform this cleanup automatically and
>> you don't need to worry about ThreadState objects - a cleaner
>> approach, and easier to use.  For your case, you should the
>> Subject.execute methods instead.  Manual ThreadState manipulation is
>> really best left to lower-level framework programming.
>>
>> Best,
>>
>> Les
>>
>> On Thu, Oct 29, 2009 at 12:33 PM, Scott Ryan <[email protected]> wrote:
>>>
>>> SUCCESS!!!
>>>
>>> I had to attach to the current thread due to all the grailsy stuff going
>>> on
>>> in the bootstrap but here is my code that appears to work.  I will clean
>>> it
>>> up quite a lot and publish a solution on the mailing list and on my blog.
>>>
>>> import org.apache.shiro.subject.Subject
>>> import org.apache.shiro.subject.PrincipalCollection
>>> import org.apache.shiro.subject.SimplePrincipalCollection
>>> import org.apache.shiro.util.ThreadState
>>> import org.apache.shiro.subject.support.SubjectThreadState
>>> import org.apache.shiro.mgt.DefaultSecurityManager
>>> import org.apache.shiro.mgt.SecurityManager
>>>
>>> class BootStrap
>>> {
>>>
>>>   def shiroSecurityManager
>>>   def init =
>>>   {servletContext ->
>>>
>>> buildSubject()
>>> // RUN ALL your bootstrap code here
>>>
>>> void buildSubject()
>>>   {
>>> // TODO Clean this up and add all realms if requirred
>>>       Object userIdentity = "admin";
>>>       def realms = shiroSecurityManager.realms
>>>       println "ralsm cont" + realms?.size()
>>>       def realm
>>>       realms.each()
>>>       {
>>>           realm = it
>>>       }
>>>       //  Realm localizedRealm = shiroSecurityManager.realms
>>>       SecurityManager bootstrapSecurityManager = new
>>> DefaultSecurityManager(realm);
>>>       PrincipalCollection principals = new
>>> SimplePrincipalCollection(userIdentity, realm.getName());
>>>       Subject subject = new
>>>
>>> Subject.Builder(bootstrapSecurityManager).principals(principals).buildSubject();
>>>       ThreadState threadState = new SubjectThreadState(subject);
>>>       threadState.bind();
>>>   }
>>> }
>>>
>>> All of my domain objects extend the BaseDomain
>>>
>>> public abstract class BaseDomain
>>> {
>>>   static constraints =
>>>   {
>>>       // TODO Set some to be required
>>>       dateCreated(nullable: true)
>>>       createUser(nullable: true)
>>>       lastUpdated(nullable: true)
>>>       updateUser(nullable: true)
>>>   }
>>>   /** The date this entry was created */
>>>   Date dateCreated
>>>   /** The username that created this entry */
>>>   String createUser
>>>   /** The date this entry was last updated */
>>>   Date lastUpdated
>>>   /** The username that last updated this entry */
>>>   String updateUser
>>>   /** Before insert the database should populate the username
>>>    * on the createUser.  The timestamp will be taken care of by the
>>>    * grails framework automatically.
>>>    */
>>>   transient beforeInsert =
>>>   {
>>>       try
>>>       {
>>>           createUser =  SecurityUtils?.getSubject()?.getPrincipal()
>>>       }
>>>       catch (Exception ex)
>>>       {
>>>
>>>            log.fatal ("Exception in before Insert ", ex)
>>>
>>>       }
>>>   }
>>>   /** Before update the database should populate the username
>>>    * on the updateUser.  The timestamp will be taken care of by the
>>>    * framework automatically.
>>>    */
>>>   transient beforeUpdate =
>>>   {
>>>       try
>>>       {
>>>           updateUser = SecurityUtils?.getSubject()?.getPrincipal()
>>>       }
>>>       catch (Exception ex)
>>>       {
>>>
>>>           log.fatal ("Exception in before Update ", ex)
>>>
>>>       }
>>>   }
>>> }
>>>
>>>
>>> Thanks so much for all your assistance as I know a lot of people have
>>> been
>>> trying to get this to work.
>>>
>>>
>>> Scott Ryan
>>> President/CTO
>>> Soaring Eagle L.L.C.
>>> [email protected]
>>> (303) 263-3044
>>>
>>> On Oct 29, 2009, at 9:35 AM, Peter Ledbrook wrote:
>>>
>>>>> Yes I think it is not running in a request/response mode.  Just a dumb
>>>>> question as i implement your solution.  I tried this earlier but since
>>>>> Runnable is an interface it does not let me create one so I must be
>>>>> missing
>>>>> a parenthesis or something?
>>>>
>>>> Correct, BootStrap is executed during servlet context startup, so
>>>> there is not request or response.
>>>>
>>>>> I will try out your suggestions and offer feedback.  I think it would
>>>>> be
>>>>> nice to have access to both security managers from the plugin so you
>>>>> could
>>>>> use the same code during both processes.
>>>>
>>>> The BootStrap instances are auto-wired by Spring, so you have access
>>>> to the Spring application context. I would consider grabbing the
>>>> "shiroSecurityManager" bean and copying the realms from there into
>>>> your own temporary (non-web) security manager. I say copy the realms,
>>>> but I mean the references to them.
>>>>
>>>> That's if you even need the realms.
>>>>
>>>> Cheers,
>>>>
>>>> Peter
>>>
>>>
>
>

Reply via email to