2012-02-29 28 views
18

Me encuentro con un error en el compilador de Java donde el orden de los archivos enviados para su compilación puede hacer que el código no se compile. He profundizado el código para aislar la menor cantidad de código posible para reproducir el problema, lo que resulta en three source files (1 clase cada uno).Solución para el error de orden de compilación javac en maven

public interface ActionSpec { 
    public abstract int run(String param); 
} 


public enum Actions implements ActionSpec { 
    SKIP { 
     public int run(String d) { 
      return 0; 
     } 
    }; 
} 

public class Program { 

    public static void main(String[] args) { 
     Actions.SKIP.run("hello"); 
    } 
} 

El problema se puede reproducir al tener argumentos javac en un orden particular. En resumen, con el fin de tener éxito, la clase de acciones debe siempre ser compilado antes de la clase del Programa que lo utiliza, de lo contrario javac simplemente no puede tratar con él de una manera sana:

# this case fails 
echo "Trying order: javac Program.java Actions.java ActionSpec.java" 
rm *class 
javac -verbose Program.java Actions.java ActionSpec.java 

# this case fails 
#rm *class 
#javac Program.java Actions.java ActionSpec.java 

# this case fails 
#rm *class 
#javac ActionSpec.java Program.java Actions.java 

# this case succeeds 
#rm *class 
#javac ActionSpec.java Actions.java Program.java 

# this case succeeds 
#rm *class 
#javac Actions.java ActionSpec.java Program.java 

# this case succeeds 
#rm *class 
#javac Actions.java Program.java ActionSpec.java 

El error de compilación, cuando ocurre , siempre es el mismo: no se puede encontrar el método de ejecución en las instancias de enumeración Acciones, aunque todas implementan una interfaz que tiene ese método de ejecución.

Program.java:6: cannot find symbol 
symbol : method run(java.lang.String) 
location: class problem.Actions 
     Actions.SKIP.run("hello"); 

El error parece relacionado con this one reported on Oracle's site. Estoy usando javac 1.6.0_29, en mac os x 10.7.2 x86_64, pero también lo he reproducido en Linux.

Este problema se hizo aparente ya que estoy usando Maven para compilar, y no parece tener ningún control sobre el orden de compilación. Así que estoy buscando una solución para forzar maven a compilar archivos en un orden tal que se evite este error del compilador, o que se toquen los indicadores del compilador (o algo así) para evitarlo. El problema surge en las estaciones de trabajo y en entornos de integración continua, por lo que debería funcionar en todos los ámbitos. ¿Alguna sugerencia?

EDIT: Acabo de probar la siguiente solución, que a pesar de simplemente asignar la enumeración en cuestión a una variable con el tipo de interfaz que implementa, sorprendentemente hace que el error desaparezca.

public class Program { 

    public static void main(String[] args) { 
     ActionSpec a = Actions.SKIP; 
     a.run("hello"); 
    } 
} 

Todavía estoy interesado en otras opiniones.

+0

No es sorprendente que con la introducción de 'ActionSpec' empiece a funcionar. Tal vez el error está limitado a enum y lo que implementa. Una 'importación' podría ayudar también. –

+0

¿Ha intentado agregar un método 'public abstract int run (String d);' a la enumeración? –

+0

No debería ser necesario ya que la clase enum implementa la interfaz, y todas las instancias de esta contienen implementaciones del método (o de lo contrario la enumeración no se compilaría). –

Respuesta

5

He jugado un poco, y se encontró que la adición de yeso simple:

public static void main(String[] args) { 
    ((ActionSpec)Actions.SKIP).run("hello"); 
} 

resuelve este problema. Pasar este enum como parámetro de método como interfaz también haría el truco

+0

De acuerdo, esto es similar a la solución alternativa que descubrí, y es la solución más simple en general. –

0

Así es como yo lo haría:

  • mover la interfaz ActionSpec a otro proyecto Maven. Generalmente tenemos interfaces y clases de dominio común en su propio proyecto, p. foo-service-specs.
  • Mantenga las otras clases en el proyecto de implementación, p. foo-service-impl.
  • Incluya el proyecto foo-service-specs como una dependencia en foo-service-impl.

Al hacer esto, puede asegurarse de que la orden de compilación funciona, y también debe funcionar para la integración continua.

+0

Todavía no hay garantía de que Acciones compile antes del Programa, que es el meollo del problema. –

0

Pruebe varias ejecuciones del complemento del compilador. El uso de default-compile como primer ID de ejecución agrega la nueva configuración a la ejecución del compilador por defecto de Maven. Use los elementos de configuración <includes/> en la ejecución predeterminada para compilar las enumeraciones primero. Para la segunda ejecución usaría una combinación de <includes> y <excludes>, donde <includes> sería todo su código y excluiría las enumeraciones ya compiladas.

Creo que esto funcionará para su programa de ejemplo pero no lo probé. He probado algo similar antes con Maven 3 y funcionó bien.

<plugin> 
    <groupId>org.apache.maven.plugins</groupId> 
    <artifactId>maven-compiler-plugin</artifactId> 
    <version>2.3.2</version> 
    <configuration> 
     <source>1.6</source> 
     <target>1.6</target> 
    </configuration> 
    <executions> 
     <execution> 
      <id>default-compile</id> 
      <goals><goal>compile</goal></goals> 
      <configuration> 
       <includes> 
        <include>**/Actions.*</include> 
       </includes> 
      </configuration> 
     </execution> 
     <execution> 
      <id>second</id> 
      <goals><goal>compile</goal></goals> 
      <configuration> 
       <includes> 
        <include>**/*</include> 
       </includes> 
       <excludes> 
        <exclude>**/Actions.*</exclude> 
       </excludes> 
      </configuration> 
     </execution> 
    </executions> 
</plugin> 
0

Tuvimos el mismo problema. Múltiples ejecuciones de la maven compiler complemento trabajaron para nosotros ...

Cuestiones relacionadas