policeman-tools / forbidden-apis

Policeman's Forbidden API Checker
Apache License 2.0
324 stars 34 forks source link

"Check for forbidden API calls failed: java.lang.ClassNotFoundException" #43

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Add forbiddenapis 1.7 plugin to junixsocket pom 
(https://github.com/kohlschuetter/junixsocket)
2. Run "mvn clean install"
3. Get error message "[ERROR] Failed to execute goal 
de.thetaphi:forbiddenapis:1.7:check (default) on project junixsocket-demo: 
Check for forbidden API calls failed: java.lang.ClassNotFoundException: Class 
'com.mysql.jdbc.SocketFactory' not found on classpath -> [Help 1]"

What is the expected output? What do you see instead?
The execution should succeed (or at least show code errors found by 
forbiddenapis)

What version of the product are you using? On what operating system?
1.7 on OS X.

Please provide any additional information below.
forbiddenapis fails the build because some of the inspected classes refer other 
classes (com.mysql.jdbc.SocketFactory in this case, provided by 
"mysql-connector-java") that are not available in the "compile" scope, but in 
"runtime" only.

Suggested fix:
In CheckMojo, use runtimeClasspath instead of compileClasspath. Patch provided.

Original issue reported on code.google.com by ckkohl79 on 2 Dec 2014 at 7:38

Attachments:

GoogleCodeExporter commented 9 years ago
Hallo Christian,
a quick fix for you would be to use:

<configuration>
  <failOnMissingClasses>false<failOnMissingClasses>
</configuration>

The problem here is indeed a referenced class that is checked (in most cases 
this is because it is a superclass or interface). The question is, why does 
this fail? Runtime classpath is not really correct, because the check should 
pass also with the compile classpath as the checks are doing more or less the 
same as the java compiler.

There might be only differences at which time forbidden apis looks into 
superclasses and interfaces (it needs to do this to fail, if a class 
implemented in your code subclasses or implements a forbidden class). To check 
this, it has to follow up the inheritance tree. In addition, it uses this to 
lookup all method parameters or type declarationns in the bytecode to check 
them for classes that are forbidden.

How does the junixsocketdemo refer to mysql in your code (where it fails). It 
might be hard to find the position, because the checker does may not report the 
line number from bytecode on this error.

If you have a patch or evelopment branch of junixsocket ready, where I can 
quickly look into this, I might be able to help.

In any case, using the runtime classpath may be a solution. For checking test 
classes this is not an issue, becaus ethe test classpath always contains the 
runtime classpath:

http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism
.html#Dependency_Scope

Uwe

Original comment by uwe.h.schindler on 3 Dec 2014 at 8:07

GoogleCodeExporter commented 9 years ago
Hi,
your patch is breaking the plugin, because the runtime classpath in Maven does 
not contain "provided" and "system" depedencies (test fails, elasticsearch 
analysis also fails). In fact, the bug is, like noted before, on your side:

If the classes in your test package depend directly or indirectly on the 
"runtime" dependencies, those should better be "compile" dependencies. I 
analyzed your project and dont understand the reason, why the mysql libraries 
are runtime-only dependencies?

In Maven there is no prossibility to get the union of compile and runtime 
classpath. Maven 3 fixes this partially by an additional resolutionScope, but 
its still a hack.

What do you think?

Original comment by uwe.h.schindler on 24 Dec 2014 at 1:11

GoogleCodeExporter commented 9 years ago
See also:
http://blog.sonatype.com/2010/11/whats-in-maven-3-0-for-plugin-authors/#.VJq7vAA
A

Original comment by uwe.h.schindler on 24 Dec 2014 at 1:12

GoogleCodeExporter commented 9 years ago
The whole exercise of excluding the mysql library from junixsocket's compile 
classpath was to not have the mysql code as a direct dependency. From a 
licensing aspect, this may not be strictly necessary, but if it works that way, 
I think it's cleaner to only have it as a runtime dependency.

As a workaround, I think I could add mysql as a "compile" dependency for the 
scope of checking my code with forbidden-apis.

Alternatively, what about using the "test" scope instead of "runtime"? I think 
that would work.

Original comment by ckkohl79 on 11 Jan 2015 at 7:07

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Hi,
why not make the dependency "optional" in "compile" classpath? In that case its 
used while compiling, but any stuff using your package as dependency does not 
automatically get mysql. See: 
http://maven.apache.org/guides/introduction/introduction-to-optional-and-exclude
s-dependencies.html

"test" scope is just incorrect and is a special case for your project.

Original comment by uwe.h.schindler on 11 Jan 2015 at 7:16