# Deployment - wie am Besten vorgehen?



## jf (2. Jul 2010)

Hallo, ich möchte ein Projekt exportieren, was ja nicht ganz einfach ist...

Zunächst muss ja eine Manifest.mf erstellt werden. - Gibt es dazu ein gutes Tutorial?

Am liebsten wäre mir die Auslieferung von nur einer jar-Datei - ich verwende aber Bibliotheken (jars) von Dritten, was die ganze Sache etwas verkompliziert. 
Ich habe mir schon mal One-JAR angeschaut, sehe da allerdings noch nicht klar. Wie läuft das mit dem Ant-Skript? Geht das auch unter Windows?
Kennt jemand auch hierzu ein gutes Tutorial, oder eine bessere Alternative?

Gruß!


----------



## L-ectron-X (3. Jul 2010)

Praktisch jede große IDE nimmt dir das ab. Du brauchst dich da nicht abstrampeln.
Welche IDE benutzt du denn?


----------



## jf (3. Jul 2010)

L-ectron-X hat gesagt.:


> Praktisch jede große IDE nimmt dir das ab. Du brauchst dich da nicht abstrampeln.
> Welche IDE benutzt du denn?


Das klingt ja mal richtig gut!
Habe mir die Export-Funktion (Eclispe 3.6) nochmal etwas genauer angesehen und es dann auch hinbekommen. 

Was leider noch nicht geht, ist die Anzeige von ein paar Ikons... hättest du hierfür auch einen Tipp?


----------



## Wildcard (3. Jul 2010)

Single Jar ist oft nicht die ideale Verteilungsform. Prinzipell gibt es 2 Varianten für Single Jar Anwendungen:
1. Alle jars werden entpackt und dann in ein einziges Jar gepackt.
Das ist aus zwei Gründen problematisch:
-Resourcen können mehrfach vorhanden sein und sich dadurch überschreiben (zB Property Files).
-Es ist nicht mehr klar welche Resourcen von dir sind und welche aus welcher externen Bibliothek stammen. Das kann Lizenzprobleme verurachen und du solltest die Lizenztexte deiner jars genau durchlesen bevor du daran denkst das zu tun

2. Die third party jars werden als nested jars in deinem jar verpackt (Eclipse und Netbeans können das, ich weiß nicht welche anderen Tools es noch können). Da die Java Classloader nested jars nicht unterstützen injeziert Eclipse einen Custom Classloader in deine Applikation um die nested jars dennoch laden zu können. Damit gehst du dem Lizenzproblem aus dem Weg, allerdings würde ich mich bei halbwegs komplexen Programmen nicht darauf verlassen das der Classloader Trick nich an anderer Stelle Probleme verursachen kann.

Wenn es eine ernsthafte Anwendung ist und du sie veröffentlichen willst, würde ich nicht versuchen alles in ein Jar zu stecken. Liefer die Anwendung einfach als Zip oder zB per Webstart aus.


----------



## Wildcard (3. Jul 2010)

jf hat gesagt.:


> Was leider noch nicht geht, ist die Anzeige von ein paar Ikons... hättest du hierfür auch einen Tipp?


Icons musst du über denn Classloader laden, die File API funktioniert nicht für Resourcen in Archiven.
_getClass().getResource_ und _getClass().getResourceAsStream_ sind deine Freunde.


----------



## jf (3. Jul 2010)

Wildcard hat gesagt.:


> _getClass().getResource_ und _getClass().getResourceAsStream_ sind deine Freunde.


Ja, darüber bin ich hier schon mehrmals gestolpert...

Aber soweit ich es verstanden habe, muss die Klasse, in welcher mal this.getClass() aufruft, im gleichen Verzeichnis liegen, wie die Ressource. Ich habe aber einen Ordner "res" in der Wurzel meines Projektes liegen, welcher zudem noch weitere Unterverzeichnisse enthält. - Muss ich diesen res-Ordner nun zu einem Quelltext-Ordner machen und eine Klasse zum Laden der Ressourcen darin erstellen?
Wie geht man hier am besten vor?

Müssen die Ressourcen dann auch noch in den Classpath, damit sie mit in die Jar gepackt werden?
Gibt es hierfür auch wieder einen Hilfe durch die IDE?


----------



## Wildcard (3. Jul 2010)

> Aber soweit ich es verstanden habe, muss die Klasse, in welcher mal this.getClass() aufruft, im gleichen Verzeichnis liegen, wie die Ressource.


Nein, muss nicht im gleichen Verzeichnis liegen, du musst nur den Pfad richtig angeben.



> Müssen die Ressourcen dann auch noch in den Classpath, damit sie mit in die Jar gepackt werden?
> Gibt es hierfür auch wieder einen Hilfe durch die IDE?


Deklariere 'res' als zusätzlich Source Folder, der Rest passiert dann automatisch.


----------



## jf (4. Jul 2010)

Wildcard hat gesagt.:


> Nein, muss nicht im gleichen Verzeichnis liegen, du musst nur den Pfad richtig angeben.
> Deklariere 'res' als zusätzlich Source Folder, der Rest passiert dann automatisch.


Hmm, dies habe ich getan - der Pfad, welchen ich erhalte, sieht auch in Ordunug aus (".../bin/res/...").
Allerdings funktioniert es weder bei der exportierten jar, als auch beim Auführen in der IDE... :bahnhof:

Gibt es hier im Forum ein Beispiel für das Laden von Ressourcen?
Ideal wäre es, wenn es sowohl beim Ausfürhen in der IDE, als auch beim Starten der exportierten jar funktionieren würde.


----------



## Wildcard (4. Jul 2010)

Wenn deine Resource a.gif heißt und direkt in 'res' liegt, lautet der Pfad "/a.gif"


----------



## jf (4. Jul 2010)

Wildcard hat gesagt.:


> Wenn deine Resource a.gif heißt und direkt in 'res' liegt, lautet der Pfad "/a.gif"


Es funktioniert bei mir leider nur, wenn die Datei im Ordner 'bin' liegt... 
Als Pfad konnte ich "/a.gif" bzw. "a.gif" verwenden - alle Versuche wie "../res/a.gif" usw. schlugen leider fehl! ???:L


----------



## jf (4. Jul 2010)

Um die Sache etwas einfacher zu machen, habe ich folgende Test-Anwendung geschrieben:


```
import java.awt.*;
import java.net.*;

import javax.swing.JFrame;


@SuppressWarnings("serial")
public class ResourceTest extends JFrame {

	Image img = null;

	public ResourceTest() throws Exception {
		this.setVisible(true);
		this.setSize(320, 320);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		
		URL myurl = this.getClass().getResource("/test.png");
		this.setTitle(myurl.toString());

		Toolkit tk = this.getToolkit();
		img = tk.getImage(myurl);	
	} // ResourceTest()

	public void paint(Graphics g) {
		g.drawImage(img, 100, 100, this);
	} // paint(Graphics g)

	public static void main(String[] argv) {
		try {
			new ResourceTest();
		} catch (Exception e) {
			e.printStackTrace();
		}
	} // main(String[] argv)

} // class ResourceTest()
```

Wenn die Ressource _test.png_ im Ordner _bin_ liegt, dann wird sie angezeigt - nicht aber wenn sie im Quelltext-Ordner _res_ liegt. Außrdem funtioniert das Ganze nur, wenn man die Anwendung über die _Run_-Schaltfläche von Eclipse startet - nicht aber wenn man die runnable jar ausführt... ;(

Wildcard, wärest du bitte so nett und änderst mein Beispiel, so dass es funktioniert?
Ich wäre dir echt dankbar! :applaus:

Gruß, jf


----------



## Wildcard (4. Jul 2010)

Wenn 'res' ein Source Folder ist, dann wird der Inhalt von res ganz automatisch nach bin kopiert.
Vorsicht mit dem Toolkit, das lädt asynchron. Besser du nimmst ImageIO oder ImageIcon. Falls du beim Toolkit bleiben willst brauchst du mindestens noch einen Media Tracker.


----------



## jf (4. Jul 2010)

Wildcard hat gesagt.:


> Wenn 'res' ein Source Folder ist, dann wird der Inhalt von res ganz automatisch nach bin kopiert.


_res_ ist ein Quelltext-Ordner, aber im Archiv (runnable jar) findet sich kein _res_-Ordner, als auch keine einzige Ressource. ???:L



Wildcard hat gesagt.:


> Vorsicht mit dem Toolkit, das lädt asynchron. Besser du nimmst ImageIO oder ImageIcon. Falls du beim Toolkit bleiben willst brauchst du mindestens noch einen Media Tracker.


Da ich nicht weiß, was ein Media Tracker ist, habe ich die ImageIcon-Variante gewählt... 

Ich habe mein Beispiel jetzt dahingehend angepasst, dass man es sowohl in der IDE über die _Run_-Schaltfläche, als auch über das ausführbare Archiv starten kann:


```
import java.awt.*;
import java.net.URL;

import javax.swing.ImageIcon;
import javax.swing.JFrame;


@SuppressWarnings("serial")
public class ResourceTest extends JFrame {

	ImageIcon imgIco = null;

	public ResourceTest() throws Exception {
		this.setVisible(true);
		this.setSize(320, 320);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		
		URL url = this.getClass().getResource("/test.png");
		imgIco = new ImageIcon(url);
		this.setTitle(url.toString());
		this.paint(this.getGraphics());
	} // ResourceTest()

	public void paint(Graphics g) {
		if(imgIco != null) {
			g.drawImage(imgIco.getImage(), 100, 100, this);
		}
	} // paint(Graphics g)

	public static void main(String[] argv) {
		try {
			new ResourceTest();
		} catch (Exception e) {
			e.printStackTrace();
		}
	} // main(String[] argv)

} // class ResourceTest()
```

Leider funktioniert es über das ausführbare Archiv immer noch nicht, da wie erwähnt, dieses die Ressource gar nicht enthält... ;(
Verdammt, es muss doch im großen weiten Netz für diesen Standard-Fall irgendein sinnvolles Beispiel geben! - Und da sage noch einer, Java wäre einfach... ueh:


----------



## jf (5. Jul 2010)

jf hat gesagt.:


> Leider funktioniert es über das ausführbare Archiv immer noch nicht, da wie erwähnt, dieses die Ressource gar nicht enthält...


Habe die Ursache hierfür gefunden: ich hatte die Datei über den Dateimanager in den _res_-Ordner kopiert und vergessen, den Ordner in Eclipse zu aktualisieren... 

Jetzt funktioniert es wunderbar!


----------

