Question

I have an Apache Wicket 1.5 application that uses Shiro for security, and Guice for dependency injection. Most of its pages are stateless, but some of my model objects (user data, current menu state, ...) need to be consistent across all requests in the same session. All of these objects have both logic (mostly simple finder methods using remote EJB3 interfaces to access a database) and state, and all of them implement Serializable.

Here's a short excerpt that should convey the idea:

@SessionScoped
public class UsersImpl implements Users, Serializable {

    private static final long serialVersionUID = 8841809043461673585L;
    private final Logger log = LoggerFactory.getLogger( UsersImpl.class );

    @Inject
    public UserService users;

    @Inject
    public RoleService roles;

    private UserDTO currentUser;

    public UserVO findUserByUser( UserVO user ) {
        UserDTO userDto = null;
        try {
            userDto = users.findUserByUser( user.toUserDTO() );
        } catch( Exception e ) {
            log.error( "Error finding user:"+user.id, e );
        }
        return userDto != null ? new UserVO( userDto ) : null;
    }

(...)

}

I developed and unit tested the classes using @Singleton (for simplicity), and everything works fine this way, but I get frequent errors like this, now that I have switched to @SessionScoped for production:

Guice provision errors:
1) Error in custom provider, org.apache.shiro.session.InvalidSessionException:
   java.lang.IllegalArgumentException: 
   HttpSession based implementations of the Shiro Session interface requires attribute keys to be String objects.  The HttpSession class does not support anything other than String keys.

Obviously, Guice seems to use some custom Key object to store the objects in the session, and the Shiro HttpSession implementation can't handle that. Strangely enough, though, this exception does not occur for all of the @SessionScoped classes, but certainly for more than one.

I have been searching the web like crazy, looking for an idea what I could do - some way to force Guice to use Strings for keys, some other way to make the HttpSession more compatible, anything - but I can't seem to find any helpful information. Also, judging from my search results for the error message, I seem to be the only person on the planet who even has this problem at all...

Is there any way to make this work? Or am I doing something wrong here?

Was it helpful?

Solution

Well, this question is hard to answer, but i try to give you some options...

You error is from upfront checking... so, i assume your application did not even start, right? Then you are very likely using Production stage or there is some binding eagerly created and that object refers to another in Session scope, which is problem. So, now you should change all your SessionScope direct injection to Providers injection as in this example:

Could you change

@Inject
public UserService users;

to

@Inject
public Provider<UserService> userProvider; //and call userProvider.get() when you will need it?

Why so?

  1. SessionScoped objects are accessible only whitin GuiceFilter.doFilter() so if you mixing scopes it could end up in some runtime exceptions. Especially, when you change Stage to Production or set some Singletons to eagerly loaded. You can learn more here. It is good practice to use Providers when mixing Scopes

  2. The problem could be that the Subject is bind only inside ShiroFilter.doFilter() check my post. Then, if you are outside let say GuiceFilter the could be no Subject bound at that time. Again, try to use Providers.

Hope, will help a little.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top