Java overloaded method in library fails when not run in web server
I am trying to write a small library that can either be used in a standard java app or as part of a servlet.
I have defined a couple of overloaded methods as follows:
// imports etc.
public ExampleLibrary {
/**
* This one is meant to be used by a J2SE app
*/
public String processData(Map headers) throws MyException {
// process
// return result
}
/**
* This one is meant to be used by a servlet
*/
public String processData(HttpServletRequest request) throws MyException {
// extract headers from request
开发者_如何学JAVA // process
// return result
}
// other methods.....
}
This works great when used as part of a Servlet, however it does not work when used as part of a J2SE app.
In my J2SE app I did the following:
ExampleLibrary example = ExampleLibrary.getInstance();
Map headers = new HashMap();
headers.put("someheader1", "someheaderval1");
headers.put("someheader2", "someheaderval2");
String res = example.processData(headers);
I get this at compile time: "cannot access javax.servlet.http.HttpServletRequest class file for javax.servlet.http.HttpServletRequest not found"
I was expecting the compiler to choose the correct processData() method and ignore the other one as obviously there is no Servlet class file in a J2SE app. Any ideas how to solve this?
You can solve your problem by including servlet.jar
on your classpath when compiling.
Here's the catch though:
If a user of your library calls one of the two methods, the compiler needs to figure out which of the two methods to actually call. If you have different method names, everything is fine and, the compiler does not need access to the HttpServletRequest
. If you have the same name however, the compiler needs to access HttpServletRequest
in order to decide which of the two methods best fit the call and argument.
Thus, The user of your lib will not need servlet.jar
to run his program, but if you use method overloading, he will need it to be able to compile his program.
Here's a dummy example that illustrates this:
Dummy test-thirdparty lib:
First, let's create a dummy third party library jar (and throw away the source):
# libtest$ mkdir thirdpartylib
# libtest$ cat -> thirdpartylib/ThirdPartyClass.java
package thirdpartylib;
public class ThirdPartyClass {
public void thirdPartyMethod() {
System.out.println("Third party method");
}
}
# libtest$ javac thirdpartylib/ThirdPartyClass.java
# libtest$ jar cf thirdpartylib.jar thirdpartylib/ThirdPartyClass.class
# libtest$ rm -rf thirdpartylib
Dummy test your lib:
# libtest$ mkdir mylib
# libtest$ cat -> mylib/LibClass.java
package mylib;
import thirdpartylib.ThirdPartyClass;
public class LibClass {
public void method(String str) {
System.out.println("method 1");
}
// Overloaded method taking third party class as argument.
public void method(ThirdPartyClass tpc) {
tpc.thirdPartyMethod();
}
}
# libtest$ javac -cp .:thirdpartylib.jar mylib/LibClass.java
# libtest$ jar cf mylib.jar mylib/LibClass.class
# libtest$ rm -rf mylib
Testing to use your lib without thirdpartylib.jar
# libtest$ cat -> LibUser.java
import mylib.LibClass;
public class LibUser {
public static void main(String[] args) {
new LibClass().method("Hej");
}
}
# libtest$ javac -cp .:mylib.jar LibUser.java
LibUser.java:5: cannot access thirdpartylib.ThirdPartyClass
class file for thirdpartylib.ThirdPartyClass not found
new LibClass().method("Hej");
^
1 error
# libtest$ javac -cp .:mylib.jar:thirdpartylib.jar LibUser.java
# libtest$ java -cp .:mylib.jar LibUser
method 1
Since your class is dependent on javax.servlet.http.HttpServletRequest
, you must provide the class definition of the latter in order to load your class. The simplest way would be to bundle servlet.jar with your app.
Note however, that altogether it is not a good idea to make a JavaSE app dependent on a JavaEE library.
A better solution would be to hide the servlet specific parts behind your own interface(s), which can be safely supplied with your core app. Then implement the interface(s) in the JavaEE specific part of your app as simple wrappers around the corresponding servlet class.
Try using different names instead of overloading.
public String processData(Map headers) throws MyException { ... }
public String processServletData(HttpServletRequest request) throws MyException { ... }
Now it works.
Edit: Alternatively you can put servlet.jar on the classpath while compiling. You won't need it to run the program, just to compile it. The java compiler needs the class info to decide which overloaded method to choose.
I get this at compile time: "cannot access javax.servlet.http.HttpServletRequest class file for javax.servlet.http.HttpServletRequest not found"
Get servlet.jar from Tomcat. It contains the servlet API. That should suppress that error.
put rt.jar and servlet.jar (or webApp library in eclipse) in class path
I suspect your error has nothing to do with overloaded methods. You simply cannot compile your class without having servlet-api.jar on the classpath.
精彩评论