Api => impl

freez

Top Contributor
Guten Morgen Community,

ich habe ein Problem in Zusammenhang mit getrennten API und IMPL Jars. Mein Setup und das spezifische Problem kommt zwar eher aus dem Java EE Bereich, da es aber prinzipiell ums Handling mit Jars bei der Entwicklung geht habe ich mich entschieden es hier zu posten.

Mein Setup:
- MyBatis + MyBatis Generator
- Spring 3

Wenn ich ein Projekt auf unterschiedliche Datenbanken zugreifen lassen möchte (nicht gleichzeitig ... je nachdem wo es eingesetzt wird), habe ich mir überlegt, dass ich ein [c]dbapi.jar[/c] erstelle, welches grundsätzlich nur Interfaces zum Interagieren mit einer beliebigen Datenbank enthält. Dazu erstelle ich mehrere Jars, welches die konkrete Implementierung der [c]dbapi.jar[/c] enthält: z.B. oracleimpl.jar, mysqlimpl.jar, mssqlimpl.jar ... soweit so gut.

Jedes Jar möchte ich in einem separaten Eclipse Projekt verwalten (ggfs. mit Maven verwaltet). Nun möchte ich auch gerne mit dem Mybatis Generator meine Objekte generieren lassen. Hier habe ich aber das Problem, dass sich diese je nach Datenbank unterscheiden können (speziell die Mapper und Provider ... bei den DBObjekten und Examples bin ich mir nicht sicher ... das Datenbankschema sollte bei allen DBs grundsätzlich ja gleich sein - was auch immer das im Detail bedeutet (Datentypen)). Ich benötige aber die DBObjekte in der api und in der impl ... zB. [c]public void saveOrder(Order o);[/c] .... von jedem DBObjekt habe ich aber pro Datenbank eine generierte Version.

Wie gehe ich nun damit um? Muss ich mein Konzept ganz verwerfen und anders vor gehen? Oder sehe ich ein Problem, welches eigentlich gar keins ist? Bislang hatte ich nie die Anforderung mehrer DBs zu unterstützen.
 
Zuletzt bearbeitet:

Phash

Top Contributor
hmm du müsstest alles, was DB spezifisch ist, auslagern und nur über Interfaces damit arbeiten.

Deine Idee scheint erstmal gut zu sein, aber noch nicht weit genug zu gehen.

Das heisst, du müsstest halt auch erst zur Laufzeit die Mapper und Provider bereitstellen, und da wirds schwierig - du kannst zwar verschiedene Implementationen dafür anbieten, aber nicht jeder kann alles, und du wirst dich in deiner Anwendung auf den kleinsten gemeinsamen Nenner einigen müssen
 

freez

Top Contributor
Ok. Danke schonmal.

Ich habe nun eins gemacht: Ich habe mir einen Generator geschrieben, der Pojos aus den DB Objekten erzeugt. Dazu habe ich Mapper, die diese Pojos auf die konkreten MySQL/Oracle... Objekte umsetzen. Das Ganze starte ich mit dem MyBatis Generator mit. Somit habe ich für jedes DB Objekt ein Standard Objekt, welches ich in den Interfaces nutzen kann (api.jar) und dann für jeden Datenbanktyp die MyBatis Objekte, welche ich dann in der jeweiligen Implementierung nutzen kann.


Allerdings habe ich jetzt ein anderes Problem. Wie sage ich Spring nun, dass
Java:
@AutoWired
@Qualifier("OrderService")
IOrderService oSrv;

nun nicht mehr Oracle, sondern MySQL nutzen soll, ohne in der ganzen Anwendung [c]@Qualifier("OrderService")[/c] anpassen zu müssen.

Das sollte ja eigentlich damit erledigt sein, in dem ich die passende Impl.jar dem Server beilege. Allerdings funktioniert das nicht:

Code:
Error creating bean with name 'ajaxbn': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field srvc.IActor springweb.AjaxTestbean.srvc; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [srvc.IActor] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency
 
Zuletzt bearbeitet:

freez

Top Contributor
OK, erst mal erledigt. Das letzte Problem lag am caomponent Scan. Ich habe ein neues Package genutzt, welches ich noch nicht mit konfiguriert hatte.

Allerdings funktioniert es trotzdem nicht so wie gedacht, dass ich die mysqlimpl.jar einfach in den Tomcat lib Ordner werfe und schon nutzt er MySQL. Tomcat erwartet dann scheinbar auch die api.jar. Auch wenn ich die in den lib Ordner dazu lege, läuft die Anwendung nicht, weil die Implementierung angeblich nicht gefunden wird.

Hat dazu noch jemand ne Idee? Oder ein einfaches funktionierendes Beispiel zum nachmachen?
 

KSG9|sebastian

Top Contributor
Du solltest die Jars mit deiner Anwendung deployen. Liegen die Jars unter Tomcat/lib wird ein anderer Classloader verwendet, dieser wiederum kennt natürlich das API-Jar nicht, da dieses in der Webapp (Classloader weiter unten) liegt.
 

freez

Top Contributor
OK, das scheint jedenfalls zu dem Problem zu passen. Na gut.

kann man dann mit Maven für jede Implementierung ein separates WAR File generieren? Oder muss ich dass händisch machen (pom.xml bearbeiten und andere Implementierung als Dependency konfigurieren und dann Export WAR File)?
 

KSG9|sebastian

Top Contributor
Liefer doch ein WAR mit allen Abhängigkeiten aus und konfiguriere, welche Implementierung genutzt werden soll. Ist doch viel einfacher.

Mit Maven könntest du es z.B. über Profile lösen. Für jede Implementierung ein Profil anlegen mit der entsprechenden Dependency. Beim Build dann. entsprechend das gewünschte Profil aktivieren?
 

freez

Top Contributor
Mit Maven könntest du es z.B. über Profile lösen. Für jede Implementierung ein Profil anlegen mit der entsprechenden Dependency. Beim Build dann. entsprechend das gewünschte Profil aktivieren?

Danke für den Tipp mit den Profilen. Die kannte ich noch nicht.

Habe eine Frage dazu: Kann ich in Eclipse mit dem m2plugin irgendwie einfach zwischen den Profilen umschalten? Oder muss ich das jedes mal über die Pom.xml über [c]<activeByDefault>true</activeByDefault>[/c] regeln?
 
Ähnliche Java Themen

Ähnliche Java Themen


Oben