eclipse-archived/ceylon

maven dependencies and assemblies

Opened this issue · 5 comments

Currently you can run an assembly with Maven dependencies using ceylon run --assembly, which is great. Thanks, @quintesse!

But if you try to run the same assembly using java -jar, you get errors like this:

ceylon.modules.CeylonRuntimeException: Could not find module: maven:com.google.inject:guice/4.0 (invalid version?)

It looks like there is simply no maven repository in the RepositoryManager in this case.

I wouldn't even really care about this issue at all except that the IDEs are now using this approach to run assemblies. (It allowed me to reuse code already written for fat-jar and swarm, instead of having to start from scratch with something new based on ceylon run.)

So I can make the errors go away by including com.redhat.ceylon.module-resolver-aether in the .cas. But that probably means it's resolving the maven: dependencies from the cloud instead of straight out of the .cas. Which isn't correct.

But that probably means it's resolving the maven: dependencies from the cloud instead of straight out of the .cas. Which isn't correct.

Oh, well, after some testing, it turns out this is always the case, even for ceylon run --assembly. That is: if I disconnect from the internet, and nuke .m2/repository, I get this error:

ceylon run: Could not find module: maven:com.google.inject:guice/4.0 (invalid version?)

So, in fact, the stuff in the maven/ dir of the .cas is always simply ignored :-(

@quintesse @FroMage That's a pretty bad bug, any ideas?

What I would expect to happen is that there's some sort of fake maven resolver that pulls shit from the maven/ dir.

Well, I've just spent an extremely frustrating evening trying to convince aether to read stuff from the temp dir we create from the assembly contents. I'm convinced that the following code should work, in AetherResolverImpl.configureSession():

        String jarPath = getClass().getProtectionDomain().getCodeSource().getLocation().toString();
        if (jarPath.startsWith("jar:file:")) {
            int index = jarPath.indexOf("/modules/com/redhat/ceylon/module-resolver-aether");
            if (index>0) {
                String tempDirPath = jarPath.substring(9, index) + "/maven/";

                RemoteRepository.Builder assemblyRepo = 
                        new RemoteRepository.Builder("assembly", "default", "file://" + tempDirPath);
                RepositoryPolicy policy = new RepositoryPolicy(true, 
                        RepositoryPolicy.UPDATE_POLICY_NEVER, 
                        RepositoryPolicy.CHECKSUM_POLICY_WARN);
                assemblyRepo.setPolicy(policy);
                assemblyRepo.setSnapshotPolicy(policy);
                assemblyRepo.setReleasePolicy(policy);
                repos.add(assemblyRepo.build());
            }
        }

But it doesn't; even though I can see aether looking at those files and warning about the missing checksum!

Out of desperation I even tried this:

        String jarPath = getClass().getProtectionDomain().getCodeSource().getLocation().toString();
        if (jarPath.startsWith("jar:file:")) {
            int index = jarPath.indexOf("/modules/com/redhat/ceylon/module-resolver-aether");
            if (index>0) {
                String tempDirPath = jarPath.substring(9, index) + "/maven/";
                localRepo = new LocalRepository( tempDirPath );
            }
        }

But that didn't work either.

This just seems crazy to me.

I'm giving up for now.

I suppose it should work, but I'm not sure we create the repo as needs be, since it's more than just poms and jars, there's checksums and metadata xml files too, to make a local repo for Maven. And we'd have to set the resolver to offline too. But it should work. Won't be easy, though.