4

I've got an unusual problem (well, I think that it is unusual). I need to be able to upload an uncompiled Java source file via a web interface and have the receiving controller compile it and execute a method on that compiled class.

I have come some way with it - I can upload the file, and compile it successfully. However, no matter what I try I can not load the (new) class definition and instantiate it. I keep getting java.lang.ClassNotFoundException exceptions thrown.

Here is my code;

        String fileName = patchFile.getFileItem().getName();
    String fullName = "<package name>" + fileName.substring(0, fileName.indexOf("."));

    // instantiate the Java compiler
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    JavaFileManager fileManager = new ClassFileManager(compiler.getStandardFileManager(null, null, null));

    // load the uploaded files into the compiler
    List<JavaFileObject> files = new ArrayList<JavaFileObject>();
    files.add(new ByteArrayJavaFileObject(fullName, patchFile.getBytes()));

    // set the classpath
    List<String> options = new ArrayList<String>();

    options.add("-classpath");
    StringBuilder sb = new StringBuilder();
    URLClassLoader urlClassLoader = (URLClassLoader) Thread.currentThread().getContextClassLoader();
    for (URL url : urlClassLoader.getURLs()) {
        sb.append(url.getFile()).append(File.pathSeparator);            
    }
    options.add(sb.toString());

    // execute the compiler
    compiler.getTask(null, fileManager, null, options, null, files).call();

    // instantiate the class (FAILS HERE)
    Object instance = fileManager.getClassLoader(null).loadClass(fullName).newInstance();

    // close the file manager
    fileManager.close();

I have also tried;

urlClassLoader.loadClass(fullName).newInstance();

But with no luck...

Could anyone shed some light on this?

Thanks in advance, Ben

As requested, here is the stacktrace;

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.ClassNotFoundException: com.sifourteen.papyrus.fabricators.patches.TestFormFabricator
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:656)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)
javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:343)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:119)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:177)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:109)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:149)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
root cause

java.lang.ClassNotFoundException: com.sifourteen.papyrus.fabricators.patches.TestFormFabricator
    org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1680)
    org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1526)
    java.lang.Class.forName0(Native Method)
    java.lang.Class.forName(Class.java:247)
    com.sifourteen.papyrus.controllers.AdminController.patch(AdminController.java:152)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    java.lang.reflect.Method.invoke(Method.java:597)
    org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:343)
    org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
    org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:119)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:177)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:109)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
    org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:149)
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
    org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
7
  • 1
    Do you have a stack trace of the class loader failure you can attach? Commented Jun 16, 2011 at 4:11
  • "I keep getting java.lang.ClassNotFoundException exceptions thrown." Posting the exception stack traces would help. Commented Jun 16, 2011 at 4:13
  • Posted stacktrace. Should have thought of that myself. Thanks. :) Commented Jun 16, 2011 at 4:15
  • 1
    You seem to be implying that it works fine in a non-webapp environment. E.g. just a plain Java client application with a main() method. Is this true? If not, did you test it as such? After all this is definitely a classpath issue. In any way, you may find the example in this question useful as starting point: stackoverflow.com/questions/2946338/… Commented Jun 16, 2011 at 4:18
  • No, I have not tested it as a client application. That will have to be my next step if I can not find a resolution here. The reason that I have shied away from that is that class-loading issues can be a bit tricky in managed web environments and wanted to make sure that I was testing "like for like". Is this kind of thing even possible in a web app context? I thought that I might be running up against security issues at one point... Commented Jun 16, 2011 at 4:23

2 Answers 2

1

the class file needs to be in the classpath. (e.g. -d WEB-INF/classes)

Sign up to request clarification or add additional context in comments.

4 Comments

Nope sorry that didn't work either. While it is true that the loaded class must be in the classpath (obviously) this is an 'in-memory' compilation. I am not even sure where the compiled class is "going". I just assumed that my custom file manager would be able to find it.
so you copied something from internet and it didn't work. I had to google that thing to understand what you are saying, and it's ... not for serious use. its toy class loader is only good for one simple class without ANY dependency on ANY other class.
Yes, you've caught me - how embarrassing. Serves me right for getting too liberal with the copy and paste! I had just traced this exact problem when I came back in here to check if there where any updates. So now the question is - how do I get my FileManager to use a classloader that has my 'standard' URL classloader as it's parent? Just working on that now...
I just fixed this - set the URLClassLoader as the parent of the classloader that was created by my FileManager - voila fixed! Serves me right for copying and pasting and then asking a stupid question on SO. I will award you the points for the answer. Thanks for much for taking the time to reply.
0

Not sure if it will work, but worth a try anyway. Try this:

Object instance = fileManager.getClassLoader(javax.tools.StandardLocation.CLASS_PATH).loadClass(fullName).newInstance();

2 Comments

Ok just tried this and got this error 'Handler processing failed; nested exception is java.lang.NoClassDefFoundError: com/sifourteen/papyrus/fabricators/AbstractFabricator (wrong name: com/sifourteen/papyrus/fabricators/patches/TestFormFabricator)'. So sorry that didn't work... definitely worth a shot though.
Is com.sifourteen.papyrus.fabricators.AbstractFabricator the name of the class you are trying to compile?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.