Woohoo! I just tried the following change based on your suggestion that I explicitly look at the current thread's context class loader: #old version: #Java.java.lang.Class.forName(dep.class).asSubclass(Java.java.lang.Class.forName(dep.subclass))
#new version: Java.java.lang.Class.forName(dep.class, true, Java.java.lang.Thread.currentThread().getContextClassLoader()).asSubclass(Java.java.lang.Class.forName(dep.subclass)) And the ugly little guy works just great. (whiskey tango foxtrot, but hey) --Ed On Tue, Nov 30, 2010 at 1:32 PM, Ed Smiley <[email protected]> wrote: > No I haven't. I'll give it a whirl. > > > On Tue, Nov 30, 2010 at 1:24 PM, Alex Boisvert <[email protected]>wrote: > >> Have you tried this? >> >> Class.forName("com.mypackage.SomeImpl", true, >> Thread.currentThread().getContextClassLoader()) >> >> alex >> >> On Tue, Nov 30, 2010 at 11:51 AM, Ed Smiley <[email protected]> wrote: >> >> > First I will explain what I am doing. (And which used to work.) >> > If this confuses you, you can skip down below to read the details of the >> > problem. That's in section 2. >> > >> > I include this information only because it is an order of complexity >> more >> > complicated than most of the build programs that I have heard discussed. >> > So >> > the answer "no problem, just rewrite everything" makes me, well, a bit >> > nervous. :) >> > >> > 1.The background is that I have a main application consisting of a >> number >> > of >> > jars and wars with its own build system, and jar classloader. I then >> have >> > a >> > build system that uses Buildr to create one or more jars which contain >> > configurations and/or Java code and which are deployed to the main >> > application. The main application knows how to introspect all the jar >> files >> > at startup, so this is highly extensible. >> > >> > If they contain only configurations, they have a variety of references >> to >> > either main application classes or standard library classes in the main >> > application. The main application dependencies are resolved by Buildr >> by >> > using a toolkit of Ruby code (libraries it uses for construction of the >> > configurations) and jar files that is deployed as a Maven repo. If they >> > also contain Java code tehmselves, they need to have the references to >> that >> > code in their configuration files. The main application has its own >> > dependency injection mechanism that looks at these configuration files >> and >> > uses its classloader to load these classes. To make it more >> interesting, I >> > also have written a buildr code generator to build the build system. >> (Sort >> > of like a Rails generator.) >> > >> > Despite the inherent complexity, this works end to end fine. The only >> real >> > issue is *not* in building or deploying, it is in the built in tests >> that >> > the build system manufactures. By default two basic kinds of tests are >> > run: >> > first, the presence of every required configuration file is checked >> inside >> > the product jars with rspec; second, every class referenced in the >> > configuration files is checked using Java.java.lang.Class.forName(). >> > >> > 2. The problem is the second test, Class.forName(), it can no longer >> see >> > the classes the build system creates. This is a GREAT feature, and I >> put a >> > lot of effort into it, so it would be nice to make it work. However, I >> can >> > function by "turning it off". :(( >> > >> > Here's a simple example: >> > >> > To avoid the readonly nature of the CLASSPATH, very early on I set the >> > CLASSPATH to INCLUDE the target jars that do no yet exist. And this >> used >> > to >> > work like a champ.... >> > FileList[LIBS].each do |lib| >> > Java.classpath << lib >> > end >> > # package products: explicit, they DO NOT EXIST YET >> > Java.classpath << "#{RELEASE}/ext-lib/common.jar" >> > Java.classpath << "#{RELEASE}/lib/#{GROUP}-#{VERSION_NUMBER}.jar" >> > Java.classpath << >> > "#{RELEASE}/lib/#{GROUP}-#{vertical}-#{VERSION_NUMBER}.jar" >> > >> > RELEASE is just a directory that reassembles the jar products with >> possibly >> > designated other jars. This is a build option. >> > >> > I then do tests that come down to the equivalent of >> > >> > >> > >> Java.java.lang.Class.forName("com.mypackage.SomeImpl").asSubclass(Java.java.lang.Class.forName("com.mypackage.SomeIfc") >> > >> > That's the problem in a nutshell! >> > >> > Pretty obvious if I specify a type of component, it must both exist, and >> be >> > the correct type for the component. It also means that I will know that >> > there is a typo in the configuration I will catch it before I deploy my >> > jars >> > in the main application. Unfortunately, now I cannot do that. >> > >> > So to test it, all you need to do it have buildr build you a project, >> add >> > one class to the source directory, add in the target package jar to the >> > classpath in a location that it will eventually be in. Then make a task >> > that depends on packaging (or packaging and copying to the location you >> > designate) and that runs the Class.forName check. My prediction is >> that, >> > if >> > properly constructed, this will work on Linux, on Windows, and on a Mac >> > with >> > an earlier JVM, but NOT with the latest Mac JVM (with the header files >> > restored). >> > >> > >> > >> > >> > >> > >> > >> > On Mon, Nov 29, 2010 at 6:45 PM, Alex Boisvert <[email protected] >> > >wrote: >> > >> > > Can you post a simple example of what you're trying to do? >> > > >> > > On Monday, November 29, 2010, Ed Smiley <[email protected]> wrote: >> > > > Couldn't get that to work.... >> > > > >> > > > On Wed, Nov 17, 2010 at 3:54 PM, Ed Smiley <[email protected]> >> wrote: >> > > > >> > > >> Interesting. >> > > >> >> > > >> I saw a post by "Arton", the guy mentioned in the release notes, >> > > indicating >> > > >> that the proper way to add a jar to the classpath is using the new >> > > dynamic >> > > >> functionality >> > > >> >> > > >> Rjb::add_classpath, rather than setting it really early on though >> > > >> Java.classpath. I am messing with that approach, currently. >> > > >> >> > > >> On Wed, Nov 17, 2010 at 9:50 AM, Alex Boisvert < >> > [email protected] >> > > >wrote: >> > > >> >> > > >>> There were some changes in RJB between 1.2.5 and 1.3.3 related to >> > > >>> classloading. In particular, RJB now uses a URLClassLoader >> instead >> > of >> > > the >> > > >>> JVM's system classloader. >> > > >>> >> > > >>> https://github.com/arton/rjb/blob/master/ChangeLog >> > > >>> >> > > >>> <https://github.com/arton/rjb/blob/master/ChangeLog>Not sure it >> > causes >> > > >>> the >> > > >>> issue you're seeing but I thought it worth mentioning. >> > > >>> >> > > >>> alex >> > > >>> >> > > >>> >> > > >>> On Wed, Nov 17, 2010 at 8:59 AM, Ed Smiley <[email protected]> >> > wrote: >> > > >>> >> > > >>> > In the aftermath of changing over to getting Buildr to work with >> > the >> > > new >> > > >>> > JVM, I am seeing yet another issue, this one a tad obscure. >> > > >>> > It's a little complicated to explain so bear with me. >> > > >>> > >> > > >>> > In code (that is essentially the same and was working before) I >> had >> > a >> > > >>> step >> > > >>> > where I set up a Java classpath early on in the build process >> which >> > > >>> > included >> > > >>> > my (not yet existing) package jar file products. I calculate >> where >> > > they >> > > >>> > would end up and what they would be called to avoid a circular >> > > >>> dependency >> > > >>> > on >> > > >>> > package object, and also to set the classpath for RJB early on >> (as >> > it >> > > >>> lets >> > > >>> > you set it later, but does not honor the new value). I then >> have a >> > > >>> > validation step where a list of Java classes and their expected >> > > >>> subclasses >> > > >>> > are instantiated (using >> > > >>> > >> > > >>> > >> > > >>> >> > > >> > >> Java.java.lang.Class.forName(dep.class).asSubclass(Java.java.lang.Class.forName(dep.subclass))). >> > > >>> > As odd as it sounds this worked correctly, and have been using >> > this >> > > for >> > > >>> > the >> > > >>> > last six weeks until I hit this snag. >> > > >>> > >> > > >>> > Now (and I put in debugging to ensure that that classpath is as >> I >> > > think >> > > >>> it >> > > >>> > is and that the jar file exists before running this check) >> classes >> > > that >> > > >>> are >> > > >>> > built in my jars are unable to be instantiated by the RJB Java >> > object >> > > >>> and I >> > > >>> > get spurious errors. >> > > >>> > >> > > >>> > Any insights? Has this environment done something to unhinge >> the >> > RJB >> > > >>> > "classpath lifecycle"? Perhaps something now creating the JVM >> > > earlier? >> > > >>> > >> > > >>> >> > > >> >> > > >> >> > > > >> > > >> > >> > >
