Mensch und Maschine
Willkommen auf » Coder’s Corner

Ein entscheidender Nachteil von JAVA sei, so höre ich viele Entwickler-Kollegen lästern, dass es keine Mehrfachvererbung beherrsche.

Heute möchte ich das verständlich widerlegen, damit ich nur noch Links zu nennen brauche, auf die jeder dann mit seinem iPhone wandern, die Antwort durchlesen kann und ich meine Zeit nicht mit Wiederholungen verschwende ;)

Die beispielhaften Basisklassen A und B:

class A{
public void getA(){...}
}
class B{
public void getB(){...}
}

Will man nun eine Klasse C schreiben, die A und B erweitert,
erhält man eine Fehlermeldung vom Compiler.

class C extends A,B{
...
}

Klasse C würde in C++ so aussehen:

class C extends A,B{
public void getA(){...}
public void getB(){...}
}

Der Grund, warum JAVA Mehrfachvererbung verbietet, liegt darin, dass eine Mehrdeutigkeit entsteht, wenn man folgende Änderungen an Klasse A und B vornähme:


class A{
public void getA(){...}
public void getX(){...}
}
class B{
public void getB(){...}
public void getX(){...}
}

Klasse C in C++ :

class C extends A,B{
public void getA(){...} //A.getA()
public void getB(){...} //B.getB()
public void getX(){...} //A.getX()
public void getX(){...} //B.getX()
}

Eine Klasse C, die A und B erweitert, müsste sich nun “entscheiden”, welche der beiden getX()-Methoden aufgerufen werden soll – die von A oder die von B ?

Das ist ein Problem.

In C++ ist Mehrfachvererbung erlaubt. Dort wird das Mehrdeutigkeitsproblem entweder so gelöst, dass man explizit angibt, welche Basisklasse genutzt werden soll. Oder aber man bedient sich komplizierter und m.E. unsauberer virtueller Klassen.

JAVA will durch das Verbot solcher Szenarien grundlegend sauberen Code sicherstellen und potentiell schwer auffindbare Fehler vermeiden.

Man kann sich jedoch helfen!

Man könnte z.B. Klasse B so verändern, dass sie von A erbt:

class A{
public void getA(){...}
public void getX(){...}
}
class B extends A{
public void getB(){...}
public void getX(){...}
}
=>
class C extends B{
public void getA(){...}
public void getB(){...}
public void getX(){...} //B.getX
}

Klasse B überschreibt die getX()-Methode von A. C kann also nur noch auf die getX()-Methode von B verweisen.
Damit ist die Eindeutigkeit des Codes gewährleistet.

Die “fehlende” Mehrfachvererbung entpuppt sich somit als a) sehr wohl vorhanden und b) als sehr vorteilhaft:

  • man wird gedrängt, die Vererbungshierarchie besser zu planen
  • die Klassenstruktur wird übersichtlicher
  • man muss Methoden einer Klasse feiner aufteilen
  • dadurch enthält jede einzelne Klasse weniger Code
  • dadurch wiederum steigt die Wartbarkeit des Codes
  • man erhält mehrere Klassen, die man modular in anderen Projekten einsetzen kann
  • es lassen sich wesentlich komplexere Vererbungshierarchien erzeugen, die jedoch stets übersichtlich bleiben

Alles in Allem ist die “Strukturierte Mehrfachvererbung”, wie ich sie mal nennen will, in JAVA eine feine Sache und sollte von jedem Entwickler, ob der eigenen Fehleranfälligkeit, mit offenen Armen empfangen werden.


nKrebs

Hallo SAP-Jünger,

Um einen SAP Webservice zu betreiben, ist Tomcat offensichtlich nicht die richtige Wahl. Der SAP JAVA Conenctor liefert nach einiger Zeit nur noch Fehlermeldungen im Zusammenhang mit dem Verbinden zum SAP System. Vermutlich liegt das an einem Bug in den Binaries der Datei libsapjco3.so. Vielleicht habe ich die SAP.-Verbindung auch nur nicht richtig Konfiguriert. Jedenfalls haben mich die Probleme mit Tomcat dann doch etwas frustriert und ich habe IBM WebSphere ausprobiert.

Erstmal musste ich mich daran gewöhnen, dass Websphere ein wenig Zeit braucht, um zu starten. Doch wenn es einmal steht, ist es auch  performant.

Deployment:

- auf http://localhost:8080 gehen und dort oben links “Administrative Console” anklicken.

- Einloggen mit User=’System’, passwort=’password’

- unter Applications auf ‘Deploy new’ klicken, im oberen Feld die WAR file auswählen und install anklicken

Nachdem das Archiv installiert ist, erscheint es in der Liste der installierten Servlets/JSPs unter Applications->Web App WARs und kann im Browser unter http://<server>:<port>/<application web path>/<servletMapping> erreicht werden.

Viele Grüße,

nK

Hallo an Dich!
Zuletzt ging es an dieser Stelle um das Deployen von Java Anwendungen auf Tomcat. Heute wird das Ganze erweitert um das erfolgreiche Einbinden von SAP’s JAVA-Connector JCo 3.0
JCo 2.0 wird relativ gut im Netz behandelt, doch mit JCo3 sieht es nicht so gut aus.
Was du brauchst:
jco lib: libsapjco3.so
jco jar: sapjco3.jar
libsapjco3.so kommt ins JDK-Verzeichnis.
unter ubuntu ist das:
/usr/lib/jvm/java-1.5.0-sun/jre/lib/i386

Die sapjco3.jar muss in den classpath der Anwendung, die auf tomcat deployed werden soll.
Weiterhin muss die sapjco3.jar im tomcat 6 unter lib kopiert werden. bei mir: (/usr/local/share/tomcat6/lib)
danach kann wie im tomcat deployment text vorgegangen werden, um zu deployen.
Eine Lösung habe ich für alle die, die JCo auf Tomcat6 betreiben wollen, jedoch auf zwei probleme stoßen.

1. Man kann den DestinationDataProvider nur einmal registrieren

2. die Abfrage Environment.isDestinationDataProviderRegistered() produziert nach einigen Durchläufen folgende Exception:

java.lang.ExceptionInInitializerError: Error getting the version of the native layer: java.lang.UnsatisfiedLinkError: com/sap/conn/rfc/driver/CpicDriver.nativeCpicGetVersion

Der Fehler wird vermutlich durch einen Bug in JCo hervorgerufen. Möglich ist auch, dass es an falschen Einstellungen des Dataproviders liegt. Wie auch immer: eine Lösung ist, das setzen dees Dataproviders in einen leeren Try Catch Block zu schreiben und somit die fehlerhafte isDestinationDataProviderSet() methode nicht aufzurufen.

Code mit isDestinationDataProviderSet():

public SAPConnection(SAPServerData serverData){
		this.serverConnectionProperties = new Properties();
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_ASHOST, serverData.getHost());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_SYSNR, serverData.getSystemNr());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_CLIENT, serverData.getClient());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_USER, serverData.getUser());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_PASSWD, serverData.getPassword());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_LANG, serverData.getLanguage());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, "10");
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, "5");
		//this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_EXPIRATION_PERIOD, Integer.toString(serverData.getTimeout()));

		//set properties of testsystem provider
		provider.changePropertiesForABAP_AS(serverConnectionProperties);

		//avoid multiple provider loading, which would lead to an exception
		if(!Environment.isDestinationDataProviderRegistered()){
			//register provider
			Environment.registerDestinationDataProvider(provider);
		}

		//try to establish connection
		try{
			this.destination = JCoDestinationManager.getDestination(SAP_SERVER);
			this.repository=this.destination.getRepository();
		}
		catch( JCoException e){
			e.printStackTrace();
			return;
		}
	}

Code ohne isDestinationDataProviderRegistered():

public SAPConnection(SAPServerData serverData){
		this.serverConnectionProperties = new Properties();
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_ASHOST, serverData.getHost());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_SYSNR, serverData.getSystemNr());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_CLIENT, serverData.getClient());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_USER, serverData.getUser());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_PASSWD, serverData.getPassword());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_LANG, serverData.getLanguage());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, "10");
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, "5");
		//this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_EXPIRATION_PERIOD, Integer.toString(serverData.getTimeout()));

		//set properties of testsystem provider
		provider.changePropertiesForABAP_AS(serverConnectionProperties);

		//avoid multiple provider loading, which would lead to an exception.
		try {
			//register provider
			Environment.registerDestinationDataProvider(provider);
		} catch (Exception e1) {}

		//try to establish connection
		try{
			this.destination = JCoDestinationManager.getDestination(SAP_SERVER);
			this.repository=this.destination.getRepository();
		}
		catch( JCoException e){
			e.printStackTrace();
			return;
		}
	}

Hallo Freunde des Java-Codes.

Da die Anleitungen auf der Apache Tomcat Seite sehr sehr ausschweifend sind, möchte ich hier ene enorm kurze Anleitung bringen, wie man mittels Eclipse 3.4 und Apache Tomcat Servlets schnell udn sicher verfügbar machen kann.

Vorraussetzungen: Du hast im Eclipse (JAVA EE mit Web Tools) ein funktionierendes Programm und ein Servlet, was als Webservice dienen und auf die restlichen Klassen zugreifen soll. Ihr habt einen lokalen Tomcat 6.0 Server laufen und der kann per Eclipse gestartet werden. Per Browser könnt ihr lokal bereits auf das Servlet zugreifen.

Schritt 1: Erstellen eines WAR-Files (Das ist beinahe ein JAR File, doch enthält es zusätzliche Dateien, um Tomcat zu konfigurieren)

WAR ezeugen: File->Export->WAR File

Schritt 2: War File auf Tomcat ‘deployen’: kopiere das WAR file auf den Server, auf dem das Live-System letztendlich laufen soll. Der Pfad ist dabei uninteressant.

Schritt 3: Öffne einen Browser (ich nehme dazu Links, weil die Live-Server ja meist nicht zugreifbar sind) und gehe auf http://localhost:8080 (das ist die Standard Einstellung von Tomcat. Solltest du das geändert haben, so musst du das an der URL natürlich auch ändern!)

Schritt 4: Klicke links im Menü auf ‘Tomcat Manager’ und log dich als ein Benutzer ein, der in der ‘manager’-Gruppe ist.

Schritt 5:  Im Vorletzten Feld ‘Deploy’ musst du nun unter ‘WAR file to deploy’  und dort unter ‘Select WAR file to upload’ dein soeben hochgeladenes WAR-File auswählen und dann auf ‘Deploy’ klicken.

Schritt 6: Starte den Tomcat Server neu und du kannst dein Servlet nutzen.

–kdot

Es gingen viele monde ins All, seit ich EasyCNC entwarf. Damals war ich noch Azubi im Stahlwerk Gröditz (Zerspanungsmechaniker), wollte aber wissen, ob ich die relativ hässlichen CNC Simulatoren unserer Ausbildungsstätte auch besser hinbekomme.

Aber leider war ich noch zu grün, um ein fertiges Produkt entwicklen zu können. Die alpha-version könnt ihr euch hier herunterladen: easyCNC.tar

und die Dokumentation allein: EasyCNC-v0.9.5 Documentation