Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

No Format
    java.lang.UnsatisfiedLinkError: Native Library WEB-INF/lib/libfoo.so already loaded in another classloader 
        at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1525) 

...

How can I access members of a custom Realm or Principal? When you create a custom subclass of RealmBase or GenericPrincipal and attempt to use those classes in your webapp code, you'll probably have problems with ClassCastException. This is because the instance returned by request.getUserPrincipal() is of a class loaded by the server's ClassLoader, and you are trying to access it through you webapp's ClassLoader. While the classes maybe otherwise exactly the same, different (sibling) ClassLoaders makes them different classes.

This assumes you created a MyPrincipal class, and put in Tomcat's server/classes (or lib) directory, as well as in your webapp's webinf/classes (or lib) directory. Normally, you would put custom Realm and Principal classes in the server directory because they depend on other classes there.

Here's what you would like to do, but it throws ClassCastException:
MyPrincipal p = request.getUserPrincipal; String emailAddress = p.getEmailAddress();

Here are 4 ways you might get around the ClassLoader boundary:

1) "Reflection"? Principal p = request.getUserPrincipal; String emailAddress = p.getClass().getMethod("getEmailAddress", null).invoke(p, null);

2) "Move classes to a common ClassLoader"? You could put your custom classes in a ClassLoader that is common to both the server and your webapp - e.g., either the "common" or bootstrap ClassLoaders. To do this, however, you would also need to move the classes that your custom classes depend on up to the common ClassLoader, and that seems like a bad idea, because there a many of them and they a core server classes.

3) "Common Interfaces"? Rather than move the implementing custom classes up, you could define Interfaces for your customs classes, and put the interfaces in the common directory. You're code would look like this:

public interface MyPrincipalInterface extends java.security.Principal {
public String getEmailAddress();
}

public class MyPrincipal implements MyPrincipalInterface {
...
public String getEmailAddress() {
return emailAddress;
}
}

public class MyServlet implements Servlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
MyPrincipalInterface p = (MyPrincipalInterface)request.getUserPrincipal();
String emailAddress = p.getEmailAddress(); ...
}

"""Notice that this method gives you pretty much the webapp code you wanted in the first place"""

Wiki Markup
4) "Serializing / Deserializing" You might want to try serializing the response of request.getUserPrincipal() and deserialize it to an instance of \[webapp\]MyPrincipal.

...

Setting up SSL - from the tomcat user list archives

...

Wiki Markup
But do not add questions without answers to this page. If you have a question about how to do something in tomcat which has not been addressed yet, ask the tomcat-user list: \[http://jakarta.apache.org/tomcat/faq/tomcatuser.html \] Once you've figured out how to fix your problem, come back and update the Wiki to allow the rest of us to benefit from what you've learned!

How can I access members of a custom Realm or Principal? When you create a custom subclass of RealmBase or GenericPrincipal and attempt to use those classes in your webapp code, you'll probably have problems with ClassCastException. This is because the instance returned by request.getUserPrincipal() is of a class loaded by the server's ClassLoader, and you are trying to access it through you webapp's ClassLoader. While the classes maybe otherwise exactly the same, different (sibling) ClassLoaders makes them different classes.

This assumes you created a MyUserPrincipal class, and put in Tomcat's server\classes directory, as well as in your webapp's webinf\classes directory.