views:

79

answers:

5

Hey everyone!

I've been working on a project in Eclipse and everything's been going smooth except for some Ant issues along the way.

My code compiles perfectly and does exactly what I want it to do, but, when it's in a jar, I get the error:

Exception in thread "main" java.lang.NoSuchMethodError: main

Main definitely exists in the file, so my guess is that it has to do with the way the file is constructed. I've been using SuperCSV to read some excel sheets I have and have constructed my main class around the example from the website: http://supercsv.sourceforge.net/codeExamples_general.html. Here's my adaptation:

ExcelFile.java

package jab.jm.main;

import jab.jm.readers.FileManager;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;

import junit.framework.Test;

import org.supercsv.cellprocessor.constraint.StrMinMax;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.io.CsvBeanReader;
import org.supercsv.io.ICsvBeanReader;
import org.supercsv.prefs.CsvPreference;

class ReadingObjects {

    static final CellProcessor[] userProcessors = { null,
            new StrMinMax(0, 100), null, new StrMinMax(0, 100), null,
            new StrMinMax(0, 100), null, null, null, null, null, null, null,
            null, null, null, null, null, null, null, null, null, null, null,
            null, null, null, null, null, new StrMinMax(0, 100), null,
            new StrMinMax(0, 100), null, null, null, null, null, null, null,
            null, null, null, null, null, null, null, null, null, null, null,
            null, null, null, null, null, null, null, null, null };


    public static void main(String[] args) throws Exception {
        ICsvBeanReader inFile = new CsvBeanReader(
                new FileReader(
                        "C:\\Users\\Justian\\workspaces\\LNConnectionCompiler\\src\\jab\\jm\\main\\Fred_Jewell.csv"),
                CsvPreference.EXCEL_PREFERENCE);
        try {
            final String[] header = { "title", "firstName", "middleName",
                    "lastName", "suffix", "email", "email2", "email3",
                    "businessStreet", "businessStreet2", "businessStreet3",
                    "businessCity", "businessState", "businessPostalCode",
                    "businessCountry", "homeStreet", "homeStreet2",
                    "homeStreet3", "homeCity", "homeState", "homePostalCode",
                    "homeCountry", "otherStreet", "otherStreet2",
                    "otherStreet3", "otherCity", "otherState",
                    "otherPostalCode", "otherCountry", "company", "department",
                    "jobTitle", "assistantPhone", "businessFax",
                    "businessPhone", "businessPhone2", "callback", "carPhone",
                    "companyMainPhone", "homeFax", "homePhone", "homePhone2",
                    "isdn", "mobilePhone", "otherFax", "otherPhone", "pager",
                    "primaryPhone", "radioPhone", "TTYTTDPhone", "telex",
                    "assistantName", "birthday", "managerName", "notes",
                    "otherPOBox", "spouse", "webPage", "personalWebPage" };
            ExcelFile file;
            while ((file = inFile.read(ExcelFile.class, header, userProcessors)) != null) {
                if (file.getCompany().indexOf("Jabian") >= 0)
                    System.out.println(file.getFirstName() + " " + file.getLastName());
            }
        } finally {
            inFile.close();
        }

        URL location = ExcelFile.class.getProtectionDomain().getCodeSource().getLocation();
        System.out.println(location.getFile());

    }
}

public class ExcelFile {
    private String title, firstName, middleName, lastName, suffix, email,
            email2, email3, businessStreet, businessStreet2, businessStreet3,
            businessCity, businessState, businessPostalCode, businessCountry,
            homeStreet, homeStreet2, homeStreet3, homeCity, homeState,
            homePostalCode, homeCountry, otherStreet, otherStreet2,
            otherStreet3, otherCity, otherState, otherPostalCode, otherCountry,
            company, department, jobTitle, assistantPhone, businessFax,
            businessPhone, businessPhone2, callback, carPhone,
            companyMainPhone, homeFax, homePhone, homePhone2, isdn,
            mobilePhone, otherFax, otherPhone, pager, primaryPhone, radioPhone,
            TTYTTDPhone, telex, assistantName, birthday, managerName, notes,
            otherPOBox, spouse, webPage, personalWebPage;

    public String getTitle() {
        return title;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getMiddleName() {
        return middleName;
    }

    public String getLastName() {
        return lastName;
    }

    public String getSuffix() {
        return suffix;
    }

    public String getEmail() {
        return email;
    }

    public String getEmail2() {
        return email2;
    }

    public String getEmail3() {
        return email3;
    }

    public String getBusinessStreet() {
        return businessStreet;
    }

    public String getBusinessStreet2() {
        return businessStreet2;
    }

    public String getBusinessStreet3() {
        return businessStreet3;
    }

    public String getBusinessCity() {
        return businessCity;
    }

    public String getBusinessState() {
        return businessState;
    }

    public String getBusinessPostalCode() {
        return businessPostalCode;
    }

    public String getBusinessCountry() {
        return businessCountry;
    }

    public String getHomeStreet() {
        return homeStreet;
    }

    public String getHomeStreet2() {
        return homeStreet2;
    }

    public String getHomeStreet3() {
        return homeStreet3;
    }

    public String getHomeCity() {
        return homeCity;
    }

    public String getHomeState() {
        return homeState;
    }

    public String getHomePostalCode() {
        return homePostalCode;
    }

    public String getHomeCountry() {
        return homeCountry;
    }

    public String getOtherStreet() {
        return otherStreet;
    }

    public String getOtherStreet2() {
        return otherStreet2;
    }

    public String getOtherStreet3() {
        return otherStreet3;
    }

    public String getOtherCity() {
        return otherCity;
    }

    public String getOtherState() {
        return otherState;
    }

    public String getOtherPostalCode() {
        return otherPostalCode;
    }

    public String getOtherCountry() {
        return otherCountry;
    }

    public String getCompany() {
        return company;
    }

    public String getDepartment() {
        return department;
    }

    public String getJobTitle() {
        return jobTitle;
    }

    public String getAssistantPhone() {
        return assistantPhone;
    }

    public String getBusinessFax() {
        return businessFax;
    }

    public String getBusinessPhone() {
        return businessPhone;
    }

    public String getBusinessPhone2() {
        return businessPhone2;
    }

    public String getCallBack() {
        return callback;
    }

    public String getCarPhone() {
        return carPhone;
    }

    public String getCompanyMainPhone() {
        return companyMainPhone;
    }

    public String getHomeFax() {
        return homeFax;
    }

    public String getHomePhone() {
        return homePhone;
    }

    public String getHomePhone2() {
        return homePhone2;
    }

    public String getISDN() {
        return isdn;
    }

    public String getMobilePhone() {
        return mobilePhone;
    }

    public String getOtherFax() {
        return otherFax;
    }

    public String getOtherPhone() {
        return otherPhone;
    }

    public String getPager() {
        return pager;
    }

    public String getPrimaryPhone() {
        return primaryPhone;
    }

    public String getRadioPhone() {
        return radioPhone;
    }

    public String getTTYTTDPhone() {
        return TTYTTDPhone;
    }

    public String getTelex() {
        return telex;
    }

    public String getAssistantName() {
        return assistantName;
    }

    public String getBirthday() {
        return birthday;
    }

    public String getManagerName() {
        return managerName;
    }

    public String getNotes() {
        return notes;
    }

    public String getOtherPOBox() {
        return otherPOBox;
    }

    public String getSpouse() {
        return spouse;
    }

    public String getWebPage() {
        return webPage;
    }

    public String getPersonalWebPage() {
        return personalWebPage;
    }

    public void setTitle(final String title) {
        this.title = title;
    }

    public void setFirstName(final String firstName) {
        this.firstName = firstName;
    }

    public void setMiddleName(final String middleName) {
        this.middleName = middleName;
    }

    public void setLastName(final String lastName) {
        this.lastName = lastName;
    }

    public void setSuffix(final String suffix) {
        this.suffix = suffix;
    }

    public void setEmail(final String email) {
        this.email = email;
    }

    public void setEmail2(final String email2) {
        this.email2 = email2;
    }

    public void setEmail3(final String email3) {
        this.email3 = email3;
    }

    public void setBusinessStreet(final String businessStreet) {
        this.businessStreet = businessStreet;
    }

    public void setBusinessStreet2(final String businessStreet2) {
        this.businessStreet2 = businessStreet2;
    }

    public void setBusinessStreet3(final String businessStreet3) {
        this.businessStreet3 = businessStreet3;
    }

    public void setBusinessCity(final String businessCity) {
        this.businessCity = businessCity;
    }

    public void setBusinessState(final String businessState) {
        this.businessState = businessState;
    }

    public void setBusinessPostalCode(final String businessPostalCode) {
        this.businessPostalCode = businessPostalCode;
    }

    public void setBusinessCountry(final String businessCountry) {
        this.businessCountry = businessCountry;
    }

    public void setHomeStreet(final String homeStreet) {
        this.homeStreet = homeStreet;
    }

    public void setHomeStreet2(final String homeStreet2) {
        this.homeStreet2 = homeStreet2;
    }

    public void setHomeStreet3(final String homeStreet3) {
        this.homeStreet3 = homeStreet3;
    }

    public void setHomeCity(final String homeCity) {
        this.homeCity = homeCity;
    }

    public void setHomeState(final String homeState) {
        this.homeState = homeState;
    }

    public void setHomePostalCode(final String homePostalCode) {
        this.homePostalCode = homePostalCode;
    }

    public void setHomeCountry(final String homeCountry) {
        this.homeCountry = homeCountry;
    }

    public void setOtherStreet(final String otherStreet) {
        this.otherStreet = otherStreet;
    }

    public void setOtherStreet2(final String otherStreet2) {
        this.otherStreet2 = otherStreet2;
    }

    public void setOtherStreet3(final String otherStreet3) {
        this.otherStreet3 = otherStreet3;
    }

    public void setOtherCity(final String otherCity) {
        this.otherCity = otherCity;
    }

    public void setOtherState(final String otherState) {
        this.otherState = otherState;
    }

    public void setOtherPostalCode(final String otherPostalCode) {
        this.otherPostalCode = otherPostalCode;
    }

    public void setOtherCountry(final String otherCountry) {
        this.otherCountry = otherCountry;
    }

    public void setCompany(final String company) {
        this.company = company;
    }

    public void setDepartment(final String department) {
        this.department = department;
    }

    public void setJobTitle(final String jobTitle) {
        this.jobTitle = jobTitle;
    }

    public void setAssistantPhone(final String assistantPhone) {
        this.assistantPhone = assistantPhone;
    }

    public void setBusinessFax(final String businessFax) {
        this.businessFax = businessFax;
    }

    public void setBusinessPhone(final String businessPhone) {
        this.businessPhone = businessPhone;
    }

    public void setBusinessPhone2(final String businessPhone2) {
        this.businessPhone2 = businessPhone2;
    }

    public void setCallback(final String callback) {
        this.callback = callback;
    }

    public void setCarPhone(final String carPhone) {
        this.carPhone = carPhone;
    }

    public void setCompanyMainPhone(final String companyMainPhone) {
        this.companyMainPhone = companyMainPhone;
    }

    public void setHomeFax(final String homeFax) {
        this.homeFax = homeFax;
    }

    public void setHomePhone(final String homePhone) {
        this.homePhone = homePhone;
    }

    public void setHomePhone2(final String homePhone2) {
        this.homePhone2 = homePhone2;
    }

    public void setIsdn(final String isdn) {
        this.isdn = isdn;
    }

    public void setMobilePhone(final String mobilePhone) {
        this.mobilePhone = mobilePhone;
    }

    public void setOtherFax(final String otherFax) {
        this.otherFax = otherFax;
    }

    public void setOtherPhone(final String otherPhone) {
        this.otherPhone = otherPhone;
    }

    public void setPager(final String pager) {
        this.pager = pager;
    }

    public void setPrimaryPhone(final String primaryPhone) {
        this.primaryPhone = primaryPhone;
    }

    public void setRadioPhone(final String radioPhone) {
        this.radioPhone = radioPhone;
    }

    public void setTTYTTDPhone(final String TTYTTDPhone) {
        this.TTYTTDPhone = TTYTTDPhone;
    }

    public void setTelex(final String telex) {
        this.telex = telex;
    }

    public void setAssistantName(final String assistantName) {
        this.assistantName = assistantName;
    }

    public void setBirthday(final String birthday) {
        this.birthday = birthday;
    }

    public void setManagerName(final String managerName) {
        this.managerName = managerName;
    }

    public void setNotes(final String notes) {
        this.notes = notes;
    }

    public void setOtherPOBox(final String otherPOBox) {
        this.otherPOBox = otherPOBox;
    }

    public void setSpouse(final String spouse) {
        this.spouse = spouse;
    }

    public void setWebPage(final String webPage) {
        this.webPage = webPage;
    }

    public void setPersonalWebPage(final String personalWebPage) {
        this.personalWebPage = personalWebPage;
    }

}

This, in my mind, is a poor construction, but it is entirely possible and that's why I don't run into any issues compiling. Of course, because it's such an unusual construction, Ant may be having trouble trying to access it.

Note that ExcelFile.Java contains the non-public class ReadingObjects, which contains the main method. My theory is that, because ExcelFile.java isn't necessarily THE class that contains the main method, I'm running into issues

Let me know what you guys think. I'm willing to give things a shot.

Many thanks in advance!

-Justian

EDIT: Here is my build file:

<?xml version="1.0" ?>

<project name="ServerJar" default="dist" basedir=".">
    <description>
        Builds client files into .jar
    </description>
    <!-- [build variables] -->
    <property name="src" location="src" />
    <property name="build" location="build" />
    <property name="dist" location="dist" />
    <property name="lib" location="lib" />
    <!-- [path to packages] -->
    <path id="master-classpath">
        <fileset dir="${lib}">
            <include name="*.jar"/>
        </fileset>
    </path>


    <target name="init">
        <!-- makes time stamp to be used in jar name -->
        <tstamp />
        <!-- creates build directory structure -->
        <mkdir dir="${build}" />
    </target>

    <target name="compile" depends="init" description="Compiles the source">
        <!-- compiles the java code from ${src} into ${build} -->
        <!-- <javac srcdir="${src}" destdir="${build}" /> -->
        <javac destdir= "${build}">
            <src path="${src}"/>
            <classpath refid="master-classpath"/>
        </javac>
    </target>

    <target name="dist" depends="compile" description="Generates distributable">
    <!-- creates the distribution directory -->
        <mkdir dir="${dist}/lib" />

        <!-- puts everything in ${build} into the jar file -->
        <jar jarfile="${dist}/lib/CC-${DSTAMP}.jar" basedir="${build}">
            <manifest>
                <attribute name="Main-Class" value="jab.jm.main.ExcelFile" />
            </manifest>
        </jar>

        <!-- makes a jar file for quick test execution -->
        <jar jarfile="${dist}/lib/CC.jar" basedir="${build}">
            <manifest>
                <attribute name="Main-Class" value="jab.jm.main.ExcelFile" />
            </manifest>
        </jar>
    </target>

    <target name="clean" description="Cleans up the extra build files">
        <!-- deletes the ${build} and ${dist} directories -->
        <delete dir="${build}" />
        <delete dir="${dist}" />
    </target>
</project>

EDIT: No Luck on anything. Maybe we can look into reorganizing my one file into two?

I'm a little nervous about that because I don't know what kind of format SuperCSV requires.

+1  A: 

Make sure you have the following entry in your Manifest file:

Main-Class: com.yourcompany.ReadingObjects

After that, you will need to run you program like this:

$ java -jar nameofyourjar.jar

Other possibility includes running your program like this (with no need of Manifest change):

$ java -cp nameofyourjar.jar com.yourcompany.ReadingObjects

Regards.

Pablo Santa Cruz
Manifest-Version: 1.0Ant-Version: Apache Ant 1.7.1Created-By: 16.3-b01 (Sun Microsystems Inc.)Main-Class: jab.jm.main.ExcelFile
Justian Meyer
That's your problem. Make sure your manifest points to the class you want to run (ReadingObjects in your case, I think).
Pablo Santa Cruz
ReadingObjects is not my main class. ExcelFile is. ReadingObjects was just an example. I can post ExcelFile if you'd like, but it's almost exactly the same, just a helluva lot longer.
Justian Meyer
The ExcelFile class you posted doesn't have a main method
fuzzy lollipop
A: 

However you are building, you will end up with a META-INF/MANIFEST.MF in your JAR. That file – extract it to see what it contains – needs to have a Main-Class entry in it for the JAR to be executable (so java can know what class to start executing from, of course). The class that is marked as a main class can have any visibility – I tend to prefer to make them public – and the method must be both public and static.

Now for the other, important gotcha. You need to package all your dependencies in your executable JAR file as you can't put things located outside the JAR on the classpath. (You could use another class-loader and dynamic loading tricks, but that's an entirely different level of hairiness.) It's when you start to get into this sort of thing that Maven starts to look a little less overwhelming…

Donal Fellows
How can I crack open my .jar file?
Justian Meyer
Manifest-Version: 1.0Ant-Version: Apache Ant 1.7.1Created-By: 16.3-b01 (Sun Microsystems Inc.)Main-Class: jab.jm.main.ExcelFile
Justian Meyer
It needs to refer to `jab.jm.main.ReadingObjects` instead, on the basis of the evidence presented above. Remember, it's not the name of the source file, it's the name of the class; the runtime's going to do (the equivalent of) `Class.forName` on that value to get the class object to get `main(...)` from.
Donal Fellows
I get what you're saying and it makes total sense, but it still doesn't work even when I route it to ReadingObjects.
Justian Meyer
@Justian - it doesn't work, but is it the same error message?
Carlos Heuberger
@Justian: It might be that the class that contains `main` has to be `public`. I can't remember whether that's the case or not, but I've *always* done it that way (ever since Java 1.0) and never had a problem as a result. :-)
Donal Fellows
I totally agree, but I'm not sure if SuperCSV requires that format or not. Any suggestions how I might break this down. In response to your first message to me: yes. It was the same error.
Justian Meyer
A: 

your main method is actually on the ReadingObjects class, and that class needs to be public as well. the manifest line should be:

Main-Class: package jab.jm.main.ReadingObjects

Here are detailed instructions and a working ANT file to do just what you are trying to do. Build an Executable .jar file

After studying your code again, I think the source file should be called ReadingObjects.java, ReadingObjects Class should be public and everything will work as you want it.

fuzzy lollipop
I switched it to ReadingObjects and recompiled everything with no luck. I can't make ReadingObjects public because that's not the name of the java/class file. I receive an error when I do that. See the dilemma?
Justian Meyer
there is no dilemma, you can just rename the .java file to the appropriate class or move the main method to the appropriate class. the class that has the main needs to be public and the same name as the source .java file. There is no reason that ReadingObjects can't be public, it probably shouldn't have the main method either way. But all this is a red herring, the main method should be on ExcelFile the way you have things now.
fuzzy lollipop
I think nowadays there is no need for the main class to be public; actually, the main class can be private (nested static class) and the VM will be able to find the main method.
Carlos Heuberger
+1  A: 

The -cp (and -classpath) arguments are ignored when using -jar argument. You need to specify it in the Class-Path attribute of JAR's MANIFEST.MF file.

My ant is a bit rusty, but it's something like those lines:

<attribute name="Class-Path" value="${dist.classpath}"/>

Update as per your comments you'd like to know how to do this directly with Eclipse instead of hassling with Ant. First, you need to run the proposed main() method using Ctrl+F11 and then rightclick the project, choose Export > Runnable JAR file (note "Runnable" part, this is important!). Then, in the Wizard you have to choose the same Launch configuration from the list (and if necessary choose library handling) and then click Finish. This way Eclipse will take the buildpath details automagically into account when generating the MANIFEST file.

BalusC
I'm already doing that aren't I? oO
Justian Meyer
I only see a `Main-Class` entry. Is the final `MANIFEST.MF` also actually populated with a `Class-Path` entry? If so, what does it look like? It's your key to the solution.
BalusC
I get what you're saying. I could have sworn I saw Main-Class instead of Class-Path. It looks like ${dist.classpath} doesn't actually get me the classpath, since it translates to Manifest-Version: 1.0Ant-Version: Apache Ant 1.7.1Created-By: 16.3-b01 (Sun Microsystems Inc.)Main-Class: jab.jm.main.ExcelFileClass-Path: ${dist.classpath} in the Manifest file.
Justian Meyer
You may get some hints out of [those questions](http://www.google.com/search?q=ant+jar+manifest+class-path+attribute+site%3Astackoverflow.com) and [this document](http://ant.apache.org/manual/Tasks/manifestclasspath.html).
BalusC
Should my ClassPath look more like: "Class-Path: ../../lib/SuperCSV-with_src-1.52.jar ../../lib/commons-io- 1.4.jar ../../lib/spiffy-with_source-all-0.05.jar" or "Class-Path: CC-20100701.jar CC-20100630.jar CC.jar" or neither? Either way, none of the first two worked. Maybe I should really consider making ReadingObjects public, but I don't think that worked the last time I tried it.
Justian Meyer
It should be space-separated and relative to the root path where the "main" JAR is sitting in. The `../../` doesn't look good. You usually put the "main" JAR file in at least the same root as the `/lib` folder is sitting. The entry should then look like `lib/dep1.jar lib/dep2.jar`. Your second approach requires that all of those JAR files (also the "main" JAR file) are sitting in the same folder. By the way, it's smart to also add `.` to the `Class-Path`. So: `. lib/dep1.jar lib/dep2.jar`. This adds the current path to the classpath so that you can access loose (CSV ;) ) files as resource.
BalusC
So... you're saying that the jar files that I import as well as the ones that I create should be in the same folder? How could I add "." to the class path? (as a side question: how do you highlight code in comments?). Thanks!
Justian Meyer
No I am not saying that. You're free to choose. I am just warning that going too much folders back isn't a good sign. The code shouldn't know anything about the parent folders, but only about the child folders. It's just a semantic showstopper, not a technical showstopper. It will work fine, it's only more sensitive for (future) problems. As to adding the `.`, well, just add it. Sorry, no idea how to do with ant. I use Eclipse. As to highlighting, read [Markdown guide](http://stackoverflow.com/editing-help). You can use backticks.
BalusC
How might I do this directly with Eclipse, then? Maybe it'll make my life a bit easier.
Justian Meyer
Well, I just rightclick and choose *Export* and then *Runnable JAR file*. It will take buildpath into account and ask you to extract or package or copy the dependency libraries.
BalusC
Hmm... I can't build a .jar because it can't find the main class in ReadingObjects. I really think this is an issue with how ExcelFile is set up. I feel like I should really split this up =/
Justian Meyer
Can you run the proposed JAR's main file `jab.jm.main.ExcelFile` in Eclipse? Open it and press `Ctrl+F11`.
BalusC
Yup. As I said: It compiles and runs correctly and is recognized in that respect, but I think JARs hate my construction.
Justian Meyer
Then you should choose THAT *Launch conifugration* during creating JAR, not the one when running `ReadingObjects` directly.
BalusC
This is weird. It didn't show up in the "Launch Configuration" dropdown last time, but now it's there. I'll let you know how this goes.
Justian Meyer
Likely you exported as *JAR file* instead of *Runnable JAR file*.
BalusC
Omg. It worked!!! Yes!!! Let me try something extra real quick... (I'm pretty sure I chose runnable before, tho oO)
Justian Meyer
Nope. Can't get anything working with Ant. Ah well. This will do. Much thanks! :)
Justian Meyer
You're welcome. I suppose that your subsequent question ( [accessing CSV files from classpath](http://stackoverflow.com/questions/3153337/how-do-i-get-my-current-working-directory-in-java) ) is also solved/answered with this? Just putting them in same folder as JAR file and using `ClassLoader#getResource()` should be the best way.
BalusC
A: 

You could also create a runnable jar in eclipse rather than an Ant build, it will ask you which file holds the main, it usually finds the correct one. You should then select, if I remember correctly, package contents into .jar file.

alJaree