I've got a problem running a batch job on my server, whereas it runs fine from Eclipse on my development workstation.
I've got my Spring environment set up using Roo, made an entity, and make a batch that does some work, and test it well on my develompent box. I initialize my context and do the work, but when I run my batch on the server, the context isn't initialized properly. Here's the code:
public class TestBatch {
private static ApplicationContext context;
#SuppressWarnings("unchecked")
public static void main(final String[] args) {
context = new ClassPathXmlApplicationContext("/META-INF/spring/applicationContext.xml");
try {
#SuppressWarnings("unused")
TestBatch app = new TestBatch();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void TestBatch() { /** Do Something using the context **/ }
}
And here's the log and exception:
2010-02-16 11:54:16,072 [main] INFO org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext#6037fb1e: startup date [Tue Feb 16 11:54:16 CET 2010]; root of context hierarchy
Exception in thread "main" java.lang.ExceptionInInitializerError
at org.springframework.context.support.AbstractRefreshableApplicationContext.createBeanFactory(AbstractRefreshableApplicationContext.java:194)
at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:127)
at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:458)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:388)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at tld.mydomain.myproject.batch.TestBatch.main(TestBatch.java:51)
Caused by: java.lang.NullPointerException
at org.springframework.beans.factory.support.DefaultListableBeanFactory.<clinit>(DefaultListableBeanFactory.java:103)
... 7 more
Any idea or hints as to what's going on? My classpath is set to $PROJECTHOME/target/classes, and all my dependencies are in $PROJECTHOME/target/lib, and I execute using "export CLASSPATH=$PROJECTHOME/target/classes; java -Djava.endorsed.dirs=$PROJECTHOME/target/lib tld.mydomain.myproject.batch.TestBatch"
Is there anything in my setup that looks very wrong? When I run this from Eclipse, no problems, but when I deploy it on the server where I want to run it and run it as described above, I get this problem. Because it runs from Eclipse, I believe my config files are all right, but how can I debug what's causing this? Perhaps I have some config errors or a mismatch between the server and the development workstation after all? Or is this a really weird way of saying file not found, and if so, how do I make sure it finds the correct file??
I'm really looking forward to hearing your suggestions as to how to tackle this problem.
Cheers
Nik
The cause of problem is -Djava.endorsed.dirs=$PROJECTHOME/target/lib
org.springframework.beans.factory.support.DefaultListableBeanFactory contains the following code:
static {
ClassLoader cl = DefaultListableBeanFactory.class.getClassLoader();
try {
javaxInjectProviderClass = cl.loadClass("javax.inject.Provider"); //Line 103
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - Provider interface simply not supported then.
}
}
It causes a NullPointerException, because getClassLoader() returns null when class is loaded via -Djava.endorsed.dirs. From javadoc:
Some implementations may use null to represent the bootstrap class loader.
So, use -classpath (with explicit specification of all jars) instead of -Djava.endorsed.dirs
Exception in thread "main" java.lang.ExceptionInInitializerError is occurs while adding User Library. I faced same problem in Hibernate and Spring as well. So i removed User Library say "Spring" then i add jars manually it work perfectly.
In Eclipse:
If you are using the spring jars as user library(Say SpringLib), see if the user library for spring is added(or checked) as System Library(added to the boot class path). If yes, remove the check mark.`
Just add the jars to referenced libraries and not to user library. It worked for me!
Related
I am updating a web app from Spring Boot 2.2.4 to 2.5.6 and have used Open Rewrite to handle the tedium. The run configuration in IntelliJ has spring-boot:run -Dspring.profiles.active=local -f pom.xml in the command line (this has been working with 2.2.4). After adding a try/catch to main, to actually learn why I kept getting exit code 1 with no additional info, I found java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.profiles.active' in value "classpath:application-${spring.profiles.active}.properties" to be the root issue.
Apparently passing local on the command line for spring.profiles.active is now ignored… So, I added it to application.yml which gives me a message about how it is invalid to use spring.profiles.active. I found that the currently active profile should now be in config.activate.on-profile.active so I switched to that and then did a project wide search for spring.profiles.active and replaced every single instance with config.activate.on-profile.active.
I ran the project again and again got the message that it could resolve the placeholder spring.profiles.active! I can't for the life of me figure out where that placeholder is coming from since it doesn't exist anywhere in the project now according to IntelliJ, not even in the ReadMe file!
Is there some secret place I need to look to purge this old placeholder from existence?
I ran into the same issue and found a link to a github issue where a workaround was provided.
Create a class:
public class JunitProfileResolver implements ActiveProfilesResolver {
private static final String PROFILE_JUNIT = "test";
#Override
public String[] resolve(Class<?> testClass) {
System.setProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, PROFILE_JUNIT);
return new String[] { PROFILE_JUNIT };
}
}
And use it like:
#ActiveProfiles(profiles = "test", resolver = JunitProfileResolver.class)
public class MyTest {
For me this solves the problem.
I am attempting to run a tomcat application, but when I try to go to the application I get:
java.lang.NoClassDefFoundError: Could not initialize class ysl.util.Utils
ysl.util.Utils.executeQuery(Utils.java:186)
ysl.util.Utils.getProperty(Utils.java:395)
ysl.util.Utils.getProperty(Utils.java:383)
ysl.util.YslMachineProperties.init(YslMachineProperties.java:76)
ysl.util.YslMachineProperties.getTomcatImagesDirectory(YslMachineProperties.java:109)
org.apache.jsp.YSLLogin_jsp._jspService(YSLLogin_jsp.java:70)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:98)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:328)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:315)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
I have found many references to this problem on the web - most say there was a class available when the application was compiled that is not available at run time and that I need to add something to the java classpath to find it. But how can I determine what class is missing?
The error message says that the Utils class could not be initialized, yet the stacktrace shows that we are into the second method in the class, so I would think that the class was already initialized. And certainly that is not the class whose definition can't be found, since we have line number information in the stacktrace.
The method which is triggering the error looks like this:
static public ResultSet executeQuery(String queryString) throws SQLException {
return dbConnPool.executeQuery(queryString);
Any suggestions?
Most likely the Utils class is trying to use another class that is unavailable during static initialization (that would be the root cause that #BalusC pointed out). The failure to load that class causes Utils to fail as well, so even though Utils is defined, its dependencies are not.
If you are using oracle (ex Sun) java, try running:
java -verbose:class
more options under http://download.oracle.com/javase/6/docs/technotes/tools/windows/java.html
You will see what classes were loaded.
I am getting an exception and I can't find the reason of it.
The exception I get is :
java.lang.IllegalAccessError: tried to access method Connected.getData(Ljava/lang/String;)Ljava/sql/ResultSet; from class B
The method is public.
public class B
{
public void myMethod()
{
Connected conn = new Connected(); // create a connected class in order to connect to The DB
ResultSet rs = null; // create a result set to get the query result
rs = conn.getData(sql); // do sql query
}
}
public class Connected
{
public ResultSet getData(String sql)
{
ResultSet rs = null;
try
{
prepareConnection();
stmt = conn.createStatement();
stmt.execute(sql);
rs = stmt.getResultSet();
}
catch (SQLException E)
{
System.out.println("Content.getData Error");
E.printStackTrace();
}
return rs;
}
i am using apache tomcat 5.5.12
and JAVA 1.6
This happens when accessing a package scoped method of a class that is in the same package but is in a different jar and classloader.
This was my source, but the link is now broken. Following is full text from google cache:
Packages (as in package access) are scoped per ClassLoader.
You state that the parent ClassLoader loads the interface and the child
ClassLoader loads the implementation. This won't work because of the
ClassLoader-specific nature of package scoping. The interface isn't visible to
the implementation class because, even though it's the same package name,
they're in different ClassLoaders.
I only skimmed the posts in this thread, but I think you've already discovered
that this will work if you declare the interface to be public. It would also
work to have both interface and implementation loaded by the same ClassLoader.
Really, if you expect arbitrary folks to implement the interface (which you
apparently do if the implementation is being loaded by a different
ClassLoader), then you should make the interface public.
The ClassLoader-scoping of package scope (which applies to accessing package
methods, variables, etc.) is similar to the general ClassLoader-scoping of
class names. For example, I can define two classes, both named com.foo.Bar,
with entirely different implementation code if I define them in separate
ClassLoaders.
Joel
You are almost certainly using a different version of the class at runtime to the one you expect. In particular, the runtime class would be different to the one you've compiled against (else this would have caused a compile-time error) - has that method ever been private? Do you have old versions of the classes/jars on your system anywhere?
As the javadocs for IllegalAccessError state,
Normally, this error is caught by the compiler; this error can only occur at run time if the definition of a class has incompatibly changed.
I'd definitely look at your classpath and check whether it holds any surprises.
This happened to me when I had a class in one jar trying to access a private method in a class from another jar. I simply changed the private method to public, recompiled and deployed, and it worked ok afterwards.
I was getting this error on a Spring Boot application where a #RestController ApplicationInfoResource had a nested class ApplicationInfo.
It seems the Spring Boot Dev Tools was using a different class loader.
The exception I was getting
2017-05-01 17:47:39.588 WARN 1516 --- [nio-8080-exec-9]
.m.m.a.ExceptionHandlerExceptionResolver : Resolved exception caused
by Handler execution:
org.springframework.web.util.NestedServletException: Handler dispatch
failed; nested exception is java.lang.IllegalAccessError: tried to
access class com.gt.web.rest.ApplicationInfo from class
com.gt.web.rest.ApplicationInfoResource$$EnhancerBySpringCGLIB$$59ce500c
Solution
I moved the nested class ApplicationInfo to a separate .java file and got rid of the problem.
If getData is protected then try making it public. The problem could exist in JAVA 1.6 and be absent in 1.5x
I got this for your problem. Illegal access error
I was getting same error because of configuration issue in intellij.
As shown in screenshot.
Main and test module was pointing to two different JDK. (Press F12 on the intellij project to open module settings)
Also all my dto's were using #lombok.Builder which I changed it to #Data.
From Android perspective:
Method not available in api version
I was getting this Issue primarily because i was using some thing that is not available/deprecated in that Android version
Wrong way:
Notification.Builder nBuilder = new Notification.Builder(mContext);
nBuilder.addAction(new Notification.Action(android.R.drawable.ic_menu_view,"PAUSE",pendingIntent));
Right way:
Notification.Builder nBuilder = new Notification.Builder(mContext);
nBuilder.addAction(android.R.drawable.ic_media_pause,"PAUSE",pendingIntent);
here Notification.Action is not available prior to API 20 and my min version was API 16
Just an addition to the solved answer:
This COULD be a problem with Android Studio's Instant Run feature, for example, if you realized you forgot to add the line of code: finish() to your activity after opening another one, and you already re-opened the activity you shouldn't have reopened (which the finish() solved), then you add finish() and Instant Run occurs, then the app will crash since the logic has been broken.
TL:DR;
This is not necessarily a code problem, just an Instant Run problem
In my case the problem was that a method was defined in some Interface A as default, while its sub-class overrode it as private. Then when the method was called, the java Runtime realized it was calling a private method.
I am still puzzled as to why the compiler didn't complain about the private override..
public interface A {
default void doStuff() {
// doing stuff
}
}
public class B {
private void doStuff() {
// do other stuff instead
}
}
public static final main(String... args) {
A someB = new B();
someB.doStuff();
}
In my case I was getting this error running my app in wildfly with the .ear deployed from eclipse. Because it was deployed from eclipse, the deployment folder did not contain an .ear file, but a folder representing it, and inside of it all the jars that would have been contained in the .ear file; like if the ear was unzipped.
So I had in on jar:
class MySuperClass {
protected void mySuperMethod {}
}
And in another jar:
class MyExtendingClass extends MySuperClass {
class MyChildrenClass {
public void doSomething{
mySuperMethod();
}
}
}
The solution for this was adding a new method to MyExtendingClass:
class MyExtendingClass extends MySuperClass {
class MyChildrenClass {
public void doSomething{
mySuperMethod();
}
}
#Override
protected void mySuperMethod() {
super.mySuperMethod();
}
}
I was getting similar exception but at class level
e.g. Caused by: java.lang.IllegalAccessError: tried to access class ....
I fixed this by making my class public.
I'm using java.util.logging to log in my Java application. I'm also using javax.xml.ws.Endpoint to publish a SOAP-interface.
Over the time I added more and more exceptions which all turn up at startup with a log-entry like this:
Jan 24, 2011 12:29:27 PM com.sun.xml.internal.ws.model.RuntimeModeler getExceptionBeanClass
INFO: Dynamically creating exception bean Class de.wi08e.myhome.frontend.jaxws.NotLoggedInBean
I tried following filter to block them, but I'm not sure which class to get with getLogger:
/* Filter ExceptionBeanClass logs */
Logger loggerInfo = Logger.getLogger("javax.xml.ws.Endpoint");
loggerInfo.setFilter(new Filter() {
#Override
public boolean isLoggable(LogRecord l) {
System.out.println(l.getMessage());
if (l.getMessage().startsWith("Dynamically creating exception bean Class"))
return false;
return true;
}
});
Does anyone know how to find out which class creates this log-entries? Is there another way to filter out this nerving messages?
EDIT: I also tried Logger.getLogger("com.sun.xml.internal.ws.model.RuntimeModeler"), but it's still not working...
You should be able to just run the java program with the following flag: -Djava.util.logging.config.file=<mylogging.properties> where mylogging.properties is a file with the following contents instead of doing it in code.
javax.enterprise.resource.webservices.jaxws.server.level = WARN
From http://www.docjar.com/html/api/com/sun/xml/internal/ws/model/RuntimeModeler.java.html
186 private static final Logger logger =
187 Logger.getLogger(
188 com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".server");
and from Constants
public static final java.lang.String LoggingDomain = "javax.enterprise.resource.webservices.jaxws";
Edit: Clement P answered this question right long before me; all thumbs-up should go to him!
I keep my answer here because it uses a slightly other way.
I've now solved it myself. In short, this is the solution:
Logger.getLogger("javax.enterprise.resource.webservices.jaxws.server").setLevel(Level.WARNING);
If anyone's interested, this is how I found it:
The method getExceptionBeanClass in com.sun.xml.internal.ws.model.RuntimeModeler is responsible for the messages. It uses a static Logger instanciated with the function
Logger.getLogger(com.sun.xml.ws.util.Constants.LoggingDomain + ".server");
Google-ing for com.sun.xml.ws.util.Constants leads here where you can copy-and-past the LoggingDomain constant.
But keep in mind: This solution won't work on every JRE, because it depends on Sun's 'private' namespace and implementation.
The log entry seems to indicate that it's the com.sun.xml.internal.ws.model.RuntimeModeler class which generates this log message. You should be able to filter it out by raisong the level for this logger.
Alternatively, you could just create the missing class.
Actually, that's the standard procedure that I follow when creating webservices.
If you create this class (i.e. de.wi08e.myhome.frontend.jaxws.NotLoggedInBean),
then it will just use the existing class, without trying to create it at runtime.
Actually, you don't even have to create these classes yourself. You can generate them using the wsgen tool. The wsgen.exe is part of the java jdk. So, you can just run this from the commandline.
wsgen.exe -verbose -keep -cp . de.wi08e.myhome.frontend.WebService -d source
Next move the created files to the correct project source folder.
When I launch an SWT application (via an Eclipse launch profile), I receive the following stack trace:
Exception in thread "main" java.lang.NoClassDefFoundError: org/eclipse/jface/resource/FontRegistry
at org.eclipse.jface.resource.JFaceResources.getFontRegistry(JFaceResources.java:338)
at org.eclipse.jface.window.Window.close(Window.java:313)
at org.eclipse.jface.dialogs.Dialog.close(Dialog.java:971)
at org.eclipse.jface.dialogs.ProgressMonitorDialog.close(ProgressMonitorDialog.java:348)
at org.eclipse.jface.dialogs.ProgressMonitorDialog.finishedRun(ProgressMonitorDialog.java:582)
at org.eclipse.jface.dialogs.ProgressMonitorDialog.run(ProgressMonitorDialog.java:498)
at com.blah.si.workflow.SWTApplication.main(SWTApplication.java:135)
Now, the things that make this odd:
When I change the project build path and replace jface.jar with the source project (same version - 3.3.1), the error goes away.
Other applications I have that use the same jar, and a copy of the same launch profile and project, all works fine.
This is NOT a ClassNotFoundException. The class is on the classpath. If I attach source to the jar, I can debug into the getFontRegistry method. The method will execute successfully several times before eventually throwing a NoClassDefFoundError on line 338. Line 337 is a "if variable == null" statement checking to see if a static variable has been initialized. Line 338 is initializing it if it is not already initialized. The first time through, the null check fails, and the initialization is performed. On subsequent passes through the method, the null check passes, and thus the already-initialized static value is returned. On the final pass (the one that fails,) the null check fails again (even though the static variable has already been initialized) and when it tries to re-initialize the static variable, the NoClassDefFoundError is thrown. Here is the relevant source (starting with line 336, note that fontRegistry is a private static variable that is set in no other place):
.
public static FontRegistry getFontRegistry() {
if (fontRegistry == null) {
fontRegistry = new FontRegistry(
"org.eclipse.jface.resource.jfacefonts");
}
return fontRegistry;
}
.
I have already gotten a fresh copy of the jar (to ensure it isn't corrupted,) deleted my .classpath and .project files and started a fresh project, and recreated the launch profile. No change.
Because of the peculiarities in #3 above, I'm suspecting some kind of wierd classloader behavior - it seems as if that final pass through the method is in another classloader?
Ideas?
Update: The answer provided by Pourquoi Litytestdata prompted me to pay attention to what happens in the try block just above line 458 of ProgressMonitorDialog. Indeed, that code was throwing an exception, which was being gobbled by the finally block. The root cause was ANOTHER missing class (the missing class was not JFontRegistry or any of its directly related classes, but another that was spider-web dependencied in an edge case.) I'm upvoting all answers pointing me to pay attention to the classpath, and accepting Pourquoi's, because it was the breakthrough. Thanks to all.
It sounds like you are missing a JAR file that holds a dependency, as mentioned in this blog entry from July 2006, written by Sanjiv JIVAN:
Difference between ClassNotFoundException and NoClassDefFoundError
A ClassNotFoundException is thrown when the reported class is not found by the ClassLoader.
This typically means that the class is missing from the CLASSPATH.
It could also mean that the class in question is trying to be loaded from another class which was loaded in a parent ClassLoader and hence the class from the child ClassLoader is not visible.
This is sometimes the case when working in more complex environments like an App Server (WebSphere is infamous for such ClassLoader issues).
People often tend to confuse java.lang.NoClassDefFoundError with java.lang.ClassNotFoundException. However there's an important distinction.
For example an exception (an error really since java.lang.NoClassDefFoundError is a subclass of java.lang.Error) like
java.lang.NoClassDefFoundError:
org/apache/activemq/ActiveMQConnectionFactory
does not mean that the ActiveMQConnectionFactory class is not in the CLASSPATH.
In fact, its quite the opposite.
It means that the class ActiveMQConnectionFactory was found by the ClassLoader however when trying to load the class, it ran into an error reading the class definition.
This typically happens when the class in question has static blocks or members which use a Class that's not found by the ClassLoader.
So to find the culprit, view the source of the class in question (ActiveMQConnectionFactory in this case) and look for code using static blocks or static members.
If you don't have access the the source, then simply decompile it using JAD.
On examining the code, say you find a line of code like below, make sure that the class SomeClass in in your CLASSPATH.
private static SomeClass foo = new SomeClass();
Tip : To find out which jar a class belongs to, you can use the web site jarFinder. This allows you to specify a class name using wildcards and it searches for the class in its database of jars.
jarhoo allows you to do the same thing but its no longer free to use.
If you would like to locate the which jar a class belongs to in a local path, you can use a utility like jarscan. You just specify the class you'd like to locate and the root directory path where you'd like it to start searching for the class in jars and zip files.
I think the stacktrace presented above is concealing the real problem here. Below is the code in the method run within
org.eclipse.jface.dialogs.ProgressMonitorDialog (with a comment added by me):
public void run(boolean fork, boolean cancelable,
IRunnableWithProgress runnable) throws InvocationTargetException,
InterruptedException {
setCancelable(cancelable);
try {
aboutToRun();
// Let the progress monitor know if they need to update in UI Thread
progressMonitor.forked = fork;
ModalContext.run(runnable, fork, getProgressMonitor(), getShell()
.getDisplay());
} finally {
finishedRun(); // this is line 498
}
}
The second-from-bottom line in Jared's stacktrace is line 498 of this class, which is the call to finishedRun() within the finally block. I suspect that the real cause is an exception being thrown in the try block. Since the code in the finally block also throws an exception, the original exception is lost.
To get a better handle on if it is a class loader issue go through the code where it works and add:
try
{
final Class clazz;
final ClassLoader loader;
clazz = Class.forName("org/eclipse/jface/resource/FontRegistry");
loader = clazz.getClassLoader();
System.out.println("The classloader at step 1 is: " + loader);
}
catch(final Throwable ex)
{
ex.printStackTrace();
}
And then do the same thing where you are getting the NoClassDefFoundError and see if the class loaders are different.
Then you will be able to ensure that it is the ClassLoader that is different. Can you report back with what happens with this? Depending on what the result is I might have more ideas.
To add to the excellent TofuBeer's answer, since NoClassDefFoundError indicates that:
class org.eclipse.jface.resource.FontRegistry was found by the ClassLoader,
but can not been loaded without triggering an error, like having static blocks or members which use a Class that's not found by the ClassLoader.
Let's look at org.eclipse.jface.resource.FontRegistry source code:
It does not have any static variable initialization (nor does its superclasses).
Let's look at org.eclipse.jface.resource.JFaceResources source code
The getFontRegistry() function in which the Error is triggered is using the static variable fontRegistry:
/**
* The JFace font registry; <code>null</code> until lazily initialized or
* explicitly set.
*/
private static FontRegistry fontRegistry = null;
Thus, it begs raises the question: why a static initialized variable would suddenly be considered null again ?
Because somehow FontRegistry or JFaceResources get unloaded by the gc ?!
If a field is declared static, there exists exactly one incarnation of the field, no matter how many instances (possibly zero) of the class may eventually be created. A static field, sometimes called a class variable, is incarnated when the class is initialized (§12.4).
So it doesn't matter whether instances of the class exist at any time, the field will exist as long as the Class itself has been loaded.
If this were a eclipse Plugin, this could have been related to this FAQ entry
Here is a typical scenario for a new user:
You are writing a plug-in that extends plug-in XYZ.
To get it to compile, you add a reference to the JAR file for plug-in XYZ to your project’s build path either from the Java Build Path property page or by editing the .classpath file.
When you launch a runtime workbench, the following surprising error is reported: java.lang.NoClassDefFoundError: XYZ.SomeClass.
Do not start looking in the Plug-ins and Fragments tab in the launch configuration for the runtime workbench.
That tab influences only which plug-ins are used for your runtime workbench and whether they are loaded from the workspace or from the Eclipse install directory.
Instead, start looking in the plug-in manifest.
Edit the plugin.xml file and ensure that XYZ is mentioned as a required plug-in.
Then, save the plugin.xml file.
This will update the project’s build path automatically.
Never manually edit the .classpath file when you are writing a plug-in.
The plug-in Manifest Editor simply overwrites any changes you make to it. Not very civilized, but that is the way it works.
If you try to load the class FontRegistry on your own (like TofoBeer described), you will find out that classes of the following JAR are dependent classes if using FontRegistry.
org.eclipse.core.commands_xxxxx.jar
You must add this JAR to your build path.