Announcement Announcement Module
Collapse
No announcement yet.
ClassNotFoundException via org.springframework.security.oauth_1.0.0.RC3 Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • ClassNotFoundException via org.springframework.security.oauth_1.0.0.RC3

    I am migrating a medium-sized Spring deployment from Tomcat 7 to Virgo (Tomcat of course). I added Manifest.MF data (OSGi information) to our projects and most of my API is working fine. However, I am encountering an error during Oauth2 authentication. From what I can tell, the "oauth_access_token" table in our database is storing a couple of blobs ("token" and "authentication") that reference our custom org.springframework.security.core.userdetails.User extension (referred to here as "CustomUser").

    I am curious why this exception is arising and I can only see a few general possibilities:

    1) We had a flawed configuration beforehand that only worked because Tomcat is not as rigorous about its configuration as Virgo.

    2) Virgo requires extra information regarding this module that Tomcat does not.

    3) I futzed up a configuration file or resource location while converting my API to OSGi bundles.

    Here is the primary exception:

    Code:
    [2012-12-20 14:28:07.495] ERROR http-bio-8080-exec-4         o.a.c.c.C.[Catalina].[localhost].[/api-0.0.1-SNAPSHOT].[api]      Servlet.service() for servlet [api] in context with path [/api-0.0.1-SNAPSHOT] threw exception java.lang.IllegalArgumentException: org.eclipse.virgo.kernel.osgi.framework.ExtendedClassNotFoundException: com.c.security.user.CustomUser in KernelBundleClassLoader: [bundle=org.springframework.security.oauth_1.0.0.RC3]
    	at org.springframework.security.oauth2.common.util.SerializationUtils.deserialize(SerializationUtils.java:43)
    	at org.springframework.security.oauth2.provider.token.JdbcTokenStore.deserializeAuthentication(JdbcTokenStore.java:312)
    	at org.springframework.security.oauth2.provider.token.JdbcTokenStore$3.mapRow(JdbcTokenStore.java:173)
    	at org.springframework.security.oauth2.provider.token.JdbcTokenStore$3.mapRow(JdbcTokenStore.java:171)
    	at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:92)
    	at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:1)
    	at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:649)
    	at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:587)
    	at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:637)
    	at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:666)
    	at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:674)
    	at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:734)
    	at org.springframework.security.oauth2.provider.token.JdbcTokenStore.readAuthentication(JdbcTokenStore.java:170)
    	at org.springframework.security.oauth2.provider.token.JdbcTokenStore.readAuthentication(JdbcTokenStore.java:163)
    	at org.springframework.security.oauth2.provider.token.DefaultTokenServices.loadAuthentication(DefaultTokenServices.java:200)
    	at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager.authenticate(OAuth2AuthenticationManager.java:70)
    	at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter.doFilter(OAuth2AuthenticationProcessingFilter.java:108)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
    	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
    	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
    	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
    	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:173)
    	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
    	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
    	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    	at org.eclipse.virgo.web.tomcat.support.ApplicationNameTrackingValve.invoke(ApplicationNameTrackingValve.java:33)
    	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
    	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
    	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
    	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    	at java.lang.Thread.run(Thread.java:662)
    Caused by: org.eclipse.virgo.kernel.osgi.framework.ExtendedClassNotFoundException: com.c.security.user.CustomUser in KernelBundleClassLoader: [bundle=org.springframework.security.oauth_1.0.0.RC3]
    	at org.eclipse.virgo.kernel.userregion.internal.equinox.KernelBundleClassLoader.loadClass(KernelBundleClassLoader.java:139)
    	at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    	at java.lang.Class.forName0(Native Method)
    	at java.lang.Class.forName(Class.java:247)
    	at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:603)
    	at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1574)
    	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495)
    	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
    	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
    	at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
    	at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
    	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
    	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
    	at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1946)
    	at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1870)
    	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
    	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
    	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
    	at org.springframework.security.oauth2.common.util.SerializationUtils.deserialize(SerializationUtils.java:36)
    	... 43 common frames omitted
    Caused by: java.lang.ClassNotFoundException: com.c.security.user.CustomUser
    	at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:501)
    	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:421)
    	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:412)
    	at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
    	at org.eclipse.virgo.kernel.userregion.internal.equinox.KernelBundleClassLoader.loadClass(KernelBundleClassLoader.java:135)
    	... 61 common frames omitted
    The only really significant change that I can think of is that I've migrated our MyBatis data mappers from one project into another. I've been trying to dig up other cases of this but there is very little intersection on Google between Virgo and OAuth2 =(

    I can supplement this data if needed. Any thoughts?
    Last edited by bberry; Dec 20th, 2012, 03:12 PM.

  • #2
    Just for the record, I've worked with OSGi for years and I have a fairly good understanding of bundles. I get that the oauth bundle doesn't see ours, but I'm not sure whether that is supposed to be solved by Spring beans or if we are putting data into the authentication tables that simply does not belong.

    Comment


    • #3
      I'm a bit rusty on this stuff, but isn't it likely that the oauth *needs* to see your custom user if it's using that to do authentication, and the only solution is in the OSGi domain (it works in Tomcat because all the classes are in the same loader)? I'm not really sure if Virgo has any any features that make this easy (you'd have to ask in that mailing list). It is interesting that the error occurs on deserialization, which suggests that the bundle that originally stored the data had access to the user details (or is this a legacy database from the Tomcat deployment where the class loaders weren't as granular - how else can you explain it)?

      Comment


      • #4
        I had come to the same conclusion regarding Tomcat's classpath. The OSGi world requires a bundle to explicitly declare dependencies either as packages or bundles that it imports. Assuming that the classpath is the root of the problem (as opposed to configuration files that I inadvertently altered) then I think that the next question is indeed "why does the deserialization process require that class when the serialization doesn't?"

        Also, is there an elegant way to expose my class to the Oauth bundle?

        Comment


        • #5
          Well, after tooling around with this problem for a while I finally just resorted to brute-force: I modified the Oauth2 bundle's manifest to explicitly import my domain stuff and then repackaged it. Ultimately I think the long term solution will have to involve some sort of bean factory for User, unless that is already in the oauth2 schema and I just missed it. I would put one together right now but I'm already a little behind on my project, so that will have to wait.

          Comment


          • #6
            The more elegant solution, of course, turned out to be just contributing a fragment with that dependency. I happened upon this thread because I had the same problem with another bundle and had forgotten about this. I still feel like I must be doing something wrong though; this really comes down to Spring trying to deserialize a user from the database; I sort of figured that the user details service bean would insulate the framework from the specifics of my object, but that doesn't seem to be the case here.

            Comment

            Working...
            X