Eclipse je Kunde ein Paket, wie doppelte Klassen vermeiden?

Hi,

ich möchte künftig mein (.war) Projekt (Java EE) mehreren Usern anbieten. Aktuell würde ich mein vorhandenes Projekt in Eclipse kopieren, in der Kopie die Anpassungen machen, welche nur für den User sind und ihm aus der Kopie ein war-File machen.

Wenn ich dann 30 verschiedene Nutzer habe, habe ich alle Klassen aus meinem “Standard-Deployment” 30 Mal im Eclipse. Wenn ich nun Fehler behebe, neue Klassen einfüge usw, muss ich diese in allen 30 Projekten machen.

Wie baut man solch ein Projekt richtigerweise auf ohne alles doppelt zu haben und doppelt machen zu müssen?

Also

  1. Lass es. Mach keinen User-Spezifischen Code. Damit wirst du nicht glücklich. Hatten wir in der letzten Firma, hatte schon mit Kollegen drüber die das auch in Ihren Firmen hatten. Das ist einfach ein Kraus. Und ja, da waren durchaus welche dabei, die dann 30x den selben Bugfix irgendwo einspielen durften. Wenn etwas flexibel sein soll, dann löse das über configs.
  2. Falls du das wirklich vorhast: Nutze Git + branches. Dann bleibt es bei einem Projekt und jeder Kunde hat seinen eigenen Branch.

Hi @NicoDeluxe,

das ist eine sehr allgemeine Frage. Daher auch hier eine recht allgemeine Antwort:

Du implementierst ein PluginSystem, welches darauf basiert, dass bestimmte Funktionen an „PluginInterfaces“ delegiert werden. Die „Basis“ kannst du dann in einem Projekt implementieren und die verschiedenen Implementierungen der Plugins können in separaten Projekten implementiert werden.

Beim Zusammenstellen der WAR Datei, wählst du BASIS und die entsprechenden Plugins, die zu dem jeweiligen Kunden / User gehören.

Gruß,
Martin

@martin123 so hab ich es mir vorgestellt. Ich habe das „Basisprojekt“ in welchem ich Funktionen habe, die für ALLE Kunden gelten. Wenn jetzt ein neuer Kunde kommt und noch zusätzliche Features haben will, die aber 100% NICHT für andere Kunden in Fra kommen, dann erstelle ich ein 2. Projekt und baue die neuen Features ein. Beim Built, wird dann aber das aus dem Standard + neues Feature zusammen exportiert.

Prima, wie setz ich das um :smiley: Glaube das wird nicht ganz so einfach wie ich das gern hätte.

@Tomate_Salat

Ah oh das geht auch! Du meinst also wenn ich dann im Standard etwas ändere, merge ich das in die anderen Branches?

Das ist natürlich auch eine tolle Idee, vorallem würde ich das alleine hinbekommen aufzusetzen.
Welches System würdest du empfehlen? GIT, SVN? Welchen anbieter wo ich den Code hosten kann der auch Backups macht etc? Will das nicht lokal haben oder auf meinem Server falls da doch mal was abschmiert. Das soll lieber sicher gehostet werden

SVN ist obsolet.

Auf https://github.com/ kann man GIT Repos hosten.

Wie immer kommt es darauf an, wie tiefgreifend das ganze ist.
Aber TS erster Punkt es zu lassen kann man sich weitestgehend anschliessen. Es rechnet sich nicht und bringt sehr viel Komplexität rein.

Ein anderer Ansatz ist das ganze per Konfiguration zu steuern. Die Daten für die Konfiguration können dann zum Beispiel in einer Datenbank liegen und anhand derer kann man dann das Verhalten der Anwendung steuern.
Strategy-Pattern mal als Stichwort.

Vorteil ist, dass du damit auf das andere Thema “Java EE Updates für .war verteilen” auch schon eine Antwort hast. Du bleibst bei einer Installation für alle Kunden.

Kommt aber tatsächlich auf den Einzellfall an, ob und wie sich das lohnt.

Dann habe ich die ganze Last aber wieder auf einem Server. Wie machen das die großen wie lexware zb? Da loggen ich mich online ein und habe da meine Buchhaltung, sowie auch tausend andere User. Die haben das sicher mit Cluster und so Kram über mehrere Server geregelt.

Wann würdet ihr denn empfehlen jedem Kunden ein eigenes deplyment zu geben ? Ich denke für meinen Fall ist das ganz sinnvoll.

Wie meinst du das mit Konfigurationen? Kannst du mir da ein kleines Beispiel geben?

Ist es problematisch, wenn die ganze Last auf einem Server ist? Wenn nein, kein Problem.

Mit Sicherheit haben die da mehrere Server. Aber ich gehe mal nicht davon aus, dass die für jeden User einen eigenen Server hochfahren.

Aber ein Beispiel. Der eine Kunde rechnet mit 19% MWST. ein neuer sitzt im Ausland und rechnet mit 28% MWST.
Jetzt kannst du natürlich hingehen und in deiner Anwendung ein BigDecimal drinstehen haben mit 19 und für den neuen Kunden einen Fork betreiben und dort 28 hinterlegen. Eventuell hast du schon eine Konfigurationsdatei in der MWST=19.0 steht, die geladen wird.

Oder du legst eine Tabelle Configuration an mit CustomerID, name, value und holst dir diese Daten aus der Datenbank.
In der DB kann auch irgendein Flag stehen, dass den Programmfluss so ändert, dass eben das geschieht, was der eine Kunde möchte.

if(user.isPremiumUser()) {
  doFancyStuff();
} else {
  doNormalStuff();
}

Möchtest du das jeder Kunde selbst seinen eigenen Server betreibt? Wer konfiguriert diesen, wie gehst du damit um, wenn es dort eben nicht läuft. Klar, kann man machen. Was ist wenn ein Kunde eben soviel Last erzeugt, dass ein Server für den einen Kunden nicht mehr ausreicht? Dann brauchst du erst recht eine Möglichkeit die Last zu verteilen.

Das dahinterliegende Geschäftsmodell ist entscheidend. Einen neuen Kunden aufzunehmen ist dann nichts anderes als ein paar Daten in eine Konfigurationstabelle einzutragen.

Skalierung ist das Stichwort. Eine mögliche Architektur wäre z.B.:
Caches → Service-Layer → Cache → DB-Layer.

Requests die häufig statt finden werden im ersten Cache gehalten. Danach kommen Services für die Business-Logik (stateless). Davon kannst du (z.B. mittels AWS) einfach soviele hochfahren wie nötig. Das Zeug was einen State hat (z.B.) Datenbanken kommen erst dahinter und deren Antworten werden auch nochmals gecacht. Somit verteilt sich im Idealfalle die ganze Last auf den Service-Layern und alles dahinter ist erstmal geschützt. (Das ganze ist natürlich ein vereinfachtes Model). Wenn man jetzt sinnvolle Metriken hat kann man rechtzeitig neue Server hochfahren und Services starten. Das ganze ist vollautomatisch regelbar. Für deinen Anwendungsfall aber womöglich etwas übertrieben (gehe ich mal von aus).

Ich würde hier auch den Weg empfehlen, welchen ionutbaiu beschrieben hat: du regelst das über die Datenbank, auf welche Module der Nutzer zugriff hat. Mittels roles kannst du das dann ja auch ganz gut absichern.

Prinzipiell mach ich es schon so. Ich hinterlege in der Datenbank flags (o oder 1) ob ein User eine gewisse Funktion nutzen darf.

Das Programm welches wir schreiben ist eine Art Warenwirtschaft, da werden tausende Artikel gespeichert, zu Amazon übertragen usw, Dies für mehrere Kunden gleichzeitig. Derzeit läuft es auf einem Cloudserver, wenn ich Anpassungen mache, muss ich jedes mal alles kurz lahmlegen um das neue Deployment hochzufahren. Im Prinzip ist das ein zentrales System in dem der Kunde Artikel an Amazon, Ebay etc verteilt, Bestellungen da raus holt und diese an sein LAger gibt etc. Jeder Kunde hat da ganz eigene Wünsche für Spezialprogrammierungen zb Anbindung an sein Lagersystem, Anbindung an dies und das.

Die Server würden wir bereitstellen, dafür hab ich einen Profi der würde einen Container für jeden Kunden aufsetzen (Docker glaube) wo das Deployment drin steckt. Das Hosting würde dann natürlich gleich mit verkauft werden. Wenn ein Kunde jedoch eigene Hardware hat, kann er es selbst hosten.

Jira ist da ein gutes Beispiel, die haben eigene Hostings oder auch selfhosted, das kommt dem sehr nahe. Atlassian betreibt da sicherlich je User eine eigene Instanz.

Außerdem können in dem Tool von Endkunden Reklamationen gemeldet werden usw, da ist finde ich eleganter, wenn der _Kunde auf ein Portal zb retoure.meinShop.de geht als auf einen “Fremdanbieter”

Außerdem kommt ein neues Datenschutzgesetz, dass das vorgehen wie bisher verbietet. Man darf keine Kundendaten zusammen speichern irgendwie, (da hab ich grad nicht den Durchblick).

Aus den Gründen finde ich ein Deployment pro User eleganter. Wenn ein Kunde mehr Speicher oder sonst was braucht, kann er es einfach dazu buchen ohne, dass ich den gesamten Cloudserver aufstocken muss.

Tomate Salate, AWS hatte ich ein angebiot, da lag ich bei 1500 EUR monatlich! Um gottes Willen!

Edit: Kann man denn nicht auch mehrere Domains in einem Wildfly deployen? Also dass jeder User ein eigenes Deployment auf einem Server bekommt? Dann wäre je User eine Domain in Wildfly oder? Dann könnte man pro Domain die standalone.xml anpassen (eigene Datenbank je Kunde usw). Dann wäre aber nach wie vor das Problem, wenn was abschmiert leiden alle Kunden darunter.

Nun ja, sowas würde sich ja durchaus auch als Microservice anbieten, welcher einfach von deiner Hauptanwendung konsumiert werden könnte. Damit würdest du auch verhindern, dass du eine monolithische Anwendung hast.

Nun ja, ein Problem mit AWS ist, dass man wohl sehr leicht Geld dort verbrennen kann. Hatte vor kurzem eine AWS-Schulung und da viel afair vom Trainer doch relativ häufig der Hinweis, dass man viel Geld sparen kann, wenn man sich seiner Anforderungen wirklich klar ist (und weiß, wie man dementsprechend seine Einstellungen setzt).

Auf das Wort „Microservice“ hab och gewartet :smiley: da fällt mittlerweile bei jeder Diskussion. Wie sollte man das „vorschalten“?

Gar nicht. Der Service wird konsumiert - er ist kein Teil deiner Hauptanwendung. Du schreibst den, sicherst ihn ab und lässt ihn irgendwo rennen. Deine Hauptanwendung kennt dann die URL+Auth-informationen und schickt die Daten dann dorthin.

Wenn du mehrere Services unter einer Domain mit automatischem Gateway erreichbar machen willst, dann ist sowas (wirklich sehr einfach*) mit Eureka (Service Discovery) und Zuul (Automatisches Gateway) realisierbar. Das spiel kann man noch weiter treiben, Netflix bietet einiges für die Orchestrierung.

  • Zumindest mit Spring boot. Damit hab ich schon mal aus neugier innerhalb eines Tages sowas aufgesetzt nur mit noch viel mehr Zeug (Session-Replikation, Load-Balancer, …)