6

I'm working on a Java project which uses Maven to build it. The bit of functionality I'm developing would be quite cumbersome in Java, but straightforward in Clojure, so I'd like to implement it in Clojure and have Java use the resulting generated classes seamlessly.

Here's the unit test I need to pass (src/test/java/com/foo/weather/DataProcessorTest.java):

package com.foo.weather;

import static org.junit.Assert.*;
import org.junit.Test;
import java.util.*;

public class DataProcessorCljTest {
   @Test
   public void processWithTotalsAndSubTotals() throws Exception {
      assertEquals(2, DataProcessor.process(createRawData()).size());
   }

   private List<List<String>> createRawData() {
      List<List<String>> data = new ArrayList<List<String>>();
      data.add(new ArrayList<String>(Arrays.asList("2011-11-01", "Temperature", "19.2")));
      data.add(new ArrayList<String>(Arrays.asList("2011-11-01", "Pressure", "1.1")));
      return data;
   }
}

And here is the Clojure code (src/main/clojure/com/foo/weather/data-processor.clj):

(ns com.foo.weather.DataProcessor
  (:gen-class
    :methods [#^{:static true} [process [java.util.List] java.util.List]]))

(defn process [raw-data]
  (java.util.ArrayList. []))

I've added the following to my pom.xml to build the Clojure code:

<project>
   <!-- lots of stuff omitted -->
   <build>
      <plugins>
         <!-- ... -->
         <plugin>
            <groupId>com.theoryinpractise</groupId>
            <artifactId>clojure-maven-plugin</artifactId>
            <version>1.3.6</version>
            <executions>
               <execution>
                 <id>compile</id>
                 <phase>compile</phase>
                 <goals>
                   <goal>compile</goal>
                 </goals>
               </execution>
            </executions>
         </plugin>
      </plugins>
   </build>
   <repositories>
      <!-- ... -->
      <repository>
         <id>clojure-releases</id>
         <url>http://build.clojure.org/releases</url>
       </repository>
   </repositories>
   <dependencies>
      <!-- ... -->
      <dependency>
         <groupId>org.clojure</groupId>
         <artifactId>clojure</artifactId>
         <version>1.2.1</version>
       </dependency>
   </dependencies>
</project>

However, when trying to run my unit test, the compiler complains "cannot find symbol variable DataProcessor", so it seems that my Clojure code is not being compiled properly.

One thing that I've noticed is my src/main/clojure directory doesn't seem to be treated like a source directory in my IDE (IntelliJ). I right-click on src/main/clojure in the project view and choose "Mark directory as > Source root", but after reimporting Maven dependencies (i.e. "Update dependencies" in Eclipse), the directory is no longer marked as a source root.

This leads me to believe that my problem is in my Maven configuration.

Can anyone help?

Josh Glover
  • 25,142
  • 27
  • 92
  • 129
  • Another option for Java + Clojure projects using Maven is [Zi](https://github.com/pallet/zi) – noahlz Oct 10 '12 at 14:41

1 Answers1

2

I use the following in my pom.xml which seems to work:

        <plugin>
            <groupId>com.theoryinpractise</groupId>
            <artifactId>clojure-maven-plugin</artifactId>
            <version>1.3.8</version>

            <executions>
                <!-- ... -->
                <execution>
                    <id>test-clojure</id>
                    <phase>test</phase>
                    <goals>
                        <goal>test</goal>
                    </goals>
                </execution>
            </executions>

            <configuration>
                <sourceDirectories>
                    <sourceDirectory>src/main/clojure</sourceDirectory>
                </sourceDirectories>
                <testSourceDirectories>
                    <testSourceDirectory>src/test/clojure</testSourceDirectory>
                </testSourceDirectories>
            </configuration>
        </plugin>

Also, I've found that Clojure works fine if you include the Clojure source files in a resource directory (you'll obviously need to load them from the Java code of course).

You might also find this question helpful: Calling clojure from java

Community
  • 1
  • 1
mikera
  • 105,238
  • 25
  • 256
  • 415
  • This does not seem to work for me; my JUnit test still doesn't see the Clojure-generated class. The [Calling clojure from java](http://stackoverflow.com/questions/2181774/calling-clojure-from-java) was in fact my starting point for figuring out how to do this. :) – Josh Glover Mar 05 '12 at 09:14