Lyifan (and anyone else considering page extention for access control),

First off, in my opinion centralizing access logic in a base page and forcing protected pages to extend it is an anti-pattern (http://en.wikipedia.org/wiki/Anti-pattern), and should therefore be avoided.

Regarding the dispatcher article (which I wrote), your problem is that you are attempting to use @ApplicationState in a service, and this is not possible, at least in this case. Why? Because state is based on the request, and services are by default singletons. This means you have one instance of your access controller servicing 1 or 10 or 100 simultaneous requests at once. As such, its not possible to use @ApplicationState.

However it is possible to access request specific data in your service. I have implemented this, but after reading your message and looking at my article, I see I didn't touch this important issue. I will update it soon.

Here's what you need to do.
First remove the @ApplicationState from your service - you can't use it from a singleton service. Next, get friendly with the ApplicationStateManager (http://tapestry.apache.org/tapestry5/apidocs/org/apache/tapestry/services/ApplicationStateManager.html). This is a service that can access state objects on for the current request. Finally, implement your access controller so that it receives an instance of the ASM in its constructor, and cache that reference as a member:

...snip

   public SingletonAccessControllerImpl(ApplicationStateManager asm) {
       this.asm = asm;
   }

...snip


Assuming you used auto binding for the service as shown in the article, T IoC will handle creating your access controller and providing the needed ASM. Now you can use the ASM to check for state information on a per-request basis.

I'll update the wiki.

chris


lyifan wrote:
Thanks a lot everyone. Finally the BasePase way works

But the dispatcher way still doesn't work.



lyifan wrote:
I am a 100% new user for tapestry. Currently I'm working on 5.0.5, but I
got stuck from the just beginning.

I want to implement a kind of user access controller. All the pages,
excepts for the login page, can be accessed by authenticated users only.
users who hasn't passed the authentication will be redirected to the login
page to input their user name and password, and then, if the user name and
password are correct, they will see the page they want

I think this is a very very simple thing to do.But after a few days
working, I am very frustrated.

Firstly, I've tried the onActivate method. My code looks like below:

class BasePage {
    @ApplicationState
     private UserIdentity _userIdentity;
     private boolean _userIdentityExists;

    Object onActivate() {
if( !_userIdentityExists)
             return "Login"; //Login is my login page

         return null;
    }
}

And the I visited http://localhost:8080/myapp(default page is start), I
got a blank empty page. There is nothing at all on the browser. But I can
see the login page when I went to http://localhost:8080/myapp/login

After that I found an article at
http://wiki.apache.org/tapestry/Tapestry5HowToCreateADispatcher. According
to this, I created my dispatcher. But I found ASO doesn't work in my
dispatcher class.
boolean _myIdentityExists always be false.

And if I contribute it use "before:PageRender", the dispatch method would
not be invoked then I visit the default start page. I had to use
"before:RootPath". Following it my dispatcher class code:

public class SessionController implements Dispatcher {

        @ApplicationState
        private MyIdentity _myIdentity;
        private boolean _myIdentityExists;
        
        public SessionController() {
                System.out.println("SessionController: SessionController 
created.");
        }

        public boolean dispatch(Request request, Response response) throws
IOException {
                System.out.println("Requesting " + request.getPath());

                if (! _myIdentityExists ) { // _myIdentityExists always be false
                        if( _myIdentity == null ) { // here MyIdentity won't be 
created
                                _myIdentity = new MyIdentity(); // I have to 
create it by myself.
                                System.out.println("SessionController: Identity does 
not exist.");
response.sendRedirect("login"); return true; // this works, I can see the
login page correctly.
                        }else
                                System.out.println("SessionController: Identity 
exists.");
                }
                
                return false;
        }
}

and here is the code in AppModule:
    public void
contributeMasterDispatcher(OrderedConfiguration<Dispatcher> configuration,
                @InjectService("SessionController") Dispatcher
sessionController) {
                configuration.add("SessionController", sessionController,
"before:PageRender");
        }


before:PageRender and before:Asset do not call dispatch method,
before:RootPath does

I set the session timeout to 1 min in the web.xml. <session-config>
                <session-timeout>1</session-timeout>
        </session-config>

After 1 min, I came to the start page.supposedly, I would be redirected to
the login page because session is timeout. But I could still visit the
start page, which meas _myIdentity is still in the Session after the
timeout. Is it a bug or I shouldn't create it by myself?



Reply via email to