| Uutiset | Koodikirjasto | Wiki | Keskustelut | FAQ | Info |
Keskustelut - Java - Eclipse: jar:n lisääminen jar:iineditoitu: 14:57 24.2.08 Esko 13:48 24.2.08 Otsikkokin kuulostaa jo kauhealta, mutta tilanne on siis tämä: Samainen ohjelma jota edellisessäkin kysymyksessäni tein käyttää tietokantaa tietolähteenä. Tietokantana toimii MySQL, jolle minulla on tietenkin oikea jdbc .jar käytössä. Kun exporttaan projektin .jarriksi, kyseinen jdbc .jar katoaa kuin pieru Saharaan ja varsinainen softa ei sitten tee tietokannalla yhtikäs mitään. Kuinka saan siis jdbc-ajurini mukaan exportattuun jarriin Eclipsessä? lisäedit: Kyseinen .jar on siis alikansiossa /lib/ ja huomasin juuri, ettei kansiossa /languages/ oleva default.properties myöskään työnny .jarriin exportissa. Hurmh. Tukki 13:58 24.2.08 Kai valitset sen mukaan Eclipsen export jar-dialogin toisella välilehdellä kohdassa "select resources to export:"? Esko 14:12 24.2.08 Totta kai, ei vain tartu mukaan vaikka kuinka yrittäisi. editoitu: 15:35 24.2.08 Nipsu 15:32 24.2.08 Jar-paketti ei voi sisältää jar-paketteja (zippi zipin sisässä). Koskapa jarrit kuitenkin ovat tavallisia zip yhteensopivia paketteja niin voit purkaa Eclipsen tuottaman jarrin ja myslin jarrin saman juuren alle ja pakata sitten koko roskan uudestaan vaikka winzipillä, tms. En kuitenkaan suosittele tuollaisen tempun tekemistä sillä: a) JConnector on GPL3 version alainen ja mikäli siitä tulisi noin kiinteä osa ohjelmaasi niin senkin täytyisi olla sitten GPL3:sta. b) JConnectorin bugikorjauspäivitykset vaatisivat taas uudelleenpaketointia pelkän JConnectorin vaihtamisen sijaan (ja päinvastoin). c) Tuohon on parempiakin tapoja. Tässä yksi: http://www.jroller.com/ssourcery/entry/get_rid_of_the_classpath Ideana on ladata kaikki lib-alikansiossa olevat jarrit main metodissa URLClassLoaderiin. Sovellus käynnistetään muodostamalla uusi säie josta kutsutaan varsinaista aloitusmetodia (se voi olla mikä tahansa). Koska luotu säie on tavallaan main:in 'alisäie' saa se käyttöönsä main:ssa muodostetun URLClassLoaderin resurssit. Eihän tuossa montaa riviä tärväänny, mutta ihme ettei tämän tapaista rakennetta ole javassa vakiona. Mikäli käyttis on konfattu ajamaan *.jar tiedostot suoraan (Wintoosan File Types konffi: "C:\Program Files\Java\jre6\bin\javaw.exe" -jar "%1" %*) niin tuolla bootstrapilla varustettuna pelkkä doubleclick käynnistää softan ja lataa automaattisesti kaikki *.jar tiedostot haluamastasi alihakemistosta. P.S. Teknisesti jar-paketti kyllä voi sisältää alijarreja, mutta koska java kääntäjä ei osaa niitä sieltä purkaa (ellet tee sellaista CustomClassLoaderia joka tuohon pystyy) niin hyöty jää laihaksi. Esko 15:48 24.2.08 Jaha, Nipsu pelastaa jälleen. Lienet kuullut näitä ongelmia aiemminkin :) editoitu: 18:47 24.2.08 Esko 18:02 24.2.08 Yritin sisäistää tuota, muttei onnistunut. Enkä saanut toimimaankaan. Tarvitsisin siis hieman enemmän kädestä pitämistä/toisen ratkaisun ongelmaan. Ongelmaksi tuon ymmärtämisessä muodostui se, etten saanut yksinkertaisesti mokomaa toimimaan vaikka erikseen lähdinkin jarria rakentelemaan komentoriviltä. Ongelman tuottanee tuon sisäistämisessä minulla threadit sekä rakenteiden ymmärtämättömyys, olisi kiva saada ratkaisu jonka voin heittää jo olemassa olevaan UIwrapperini (käytännössä vain käynnistää toisen luokan, jossa itse GUI+tauhkat on) main-metodiin ja ihailla kun se toimii. Tai jos ei suoraa ratkaisua niin opastusta runsaasti, k-tos :) EDIT: Tällä hetkellä toimii .bat:lla jonka sisältönä seuraava: @echo off java -cp "./lib/mysql-connector-java-5.1.5-bin.jar;Worklists.jar" controllers.UIwrapper Henk.koht. en tästä kuitenkaan pidä, mieluummin olisin ilman .battia ja tekisin mahdollisimman siististi ulospäin tämän. editoitu: 20:41 24.2.08 Nipsu 20:27 24.2.08 Targetti on tosiaan tämä: java -jar Worklists.jar Että tuohon pääsee niin: 1) Worklists.jar paketin pitää sisältää Manifest.MF tiedosto jossa on kerrottu mistä main:sta ohjelma käynnistyy. 2) Tässä esimerkissä ohjelma käynnistyy Bootloader luokan mainista. (En tunne Eclipseä, mutta oletan että saat sillä tehtyä Manifestin jarriisi?) Avataanpas koodia vielä. (Kaikki ylimääräinen poistettu..) Java import java.io.File; import java.io.FilenameFilter; import java.lang.reflect.Constructor; import java.net.URL; import java.net.URLClassLoader; public class Bootloader { public static void main(final String[] args) throws Exception { // File 'viittaus' kirjastokansioon. Osoittaa siis työhakemiston alla olevaan lib kansioon File libRoot = new File("lib"); // // luetaan taulukkoon kaikki jar filut // File[] libs = libRoot.listFiles(new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith("jar"); } }); URL[] urls = new URL[libs.length]; // // Muutetaan filenamet URLeiksi. // for (int i = 0; i < libs.length; i++) urls[i] = new URL("file", null, libs[i].getAbsolutePath()); // // Tehdään oma ClassLoader jolle em. URLit annetaan. // ClassLoader cl = new URLClassLoader(urls, Thread.currentThread().getContextClassLoader()); // // Haetaan LuokkaY:n sellainen muodostin joka ottaa parametrina merkkijonotaulukon. Koska tässä esimerkissä // halutaan välittää komentoriviparametrit LuokkaY:lle asti niin LuokkaY:lle on tehty tuollainen // merkkijonotaulukon vastaanottava muodostin. (Constructor) // final Constructor ctor = cl.loadClass("com.omafirma.LuokkaY").getConstructor(String[].class); // // Koska LuokkaY:n muodostin käynnistää myös GUI:n (ja itse pääsovelluksen), niin kutsutaan sitä tässä omassa // säikeessään. // // Säikeessä ajettava koodi: Runnable r = new Runnable() { public void run() { try { ctor.newInstance(args); } catch (Exception e) { throw new RuntimeException(e); } } }; // Tehdään uusi säie, annetaan sille Runnable toteutus ja käynnistetään(). new Thread(r).start(); } } Java 1. Aloita siitä että saat Worklists.jar:n käynnistymään ilman että kerrot komentorivillä käynnistävää luokkaa (controllers.UIWrapper?) 2. Sitten kun se on kunnossa niin koitat saada saman onnistumaan tuolla ClassLoader hässäkällä. Nipsu 21:02 24.2.08 Toinen (väkivaltaisempi) tapa jossa uutta säiettä ei tarvita: Java public static void main(final String[] args) throws Exception { File dir = new File("lib"); File[] libs = dir.listFiles(new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith("jar"); } }); URL[] urls = new URL[libs.length]; for (int i = 0; i < libs.length; i++) urls[i] = new URL("file", null, libs[i].getAbsolutePath()); // // system classloader:lla on metodi addURL jolla voisi lisätä kirjastoja sovelluksen käyttöön jos ko. metodi // vain olisi julkinen.. // URLClassLoader systemClassLoader = (URLClassLoader) Thread.currentThread().getContextClassLoader(); // Kaivetaan viittaus ko. metodiin.. Method m = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class}); // ..ja asetetaan se julkiseksi. m.setAccessible(true); // luupataan URLimme läpi ja kutsutaan tuota addURL(URL) metodia jokaiselle for (URL url : urls) m.invoke(systemClassLoader, url); // Haetaan 'oikea' main metodin sisältävä luokka Class clazz = systemClassLoader.loadClass("com.omasovellus.OmaMain"); // ja siitä perinteinen main, siis se joka ottaa String[] args parametrin. Method mainMethod = clazz.getMethod("main", new Class[]{String[].class}); // ja kutsutaan sitä. mainMethod.invoke(null, new Object[]{args}); } |
![]() Haku
|