# MVC in Java pur / Controller als Instanz? / Theorie!



## HankScorpio (4. Jan 2013)

Hallo zusammen,

ich stelle mir gerade im Moment die Frage, wie man am besten
- *ohne Framework*,
- die Controller gestaltet und
- den Aufruf des passenden Controllers zu einem Request realisieren könnte.

Meine Lösungsidee war ungefähr die:
- Alle Requests gehen an ein zentrales Servlet, das "Dispatcher"-Servlet.
- In einer HashMap mit <String,String> ordne ich jeweils einem "Action-Wort" (z.B. "invokeMeasurement") den Klassennamen einer Controllerklasse zu (z.B. "MeasurementInvoker").
- Alle Controllerklassen implementieren das Interface "AllgemeinerController", das die Methode _verarbeiteRequest_ vorschreibt.
- In dem "Dispatcher"-Servlet empfange ich das Action-Wort - sagen wir mal als GET-Parameter.
- Das Dispatcher-Servlet führt allerhand Dinge aus, die für _jeden_ Request durchgeführt werden müssen, egal, was für eine Action angefordert wird.
- In der HashMap wird dann nachgeschaut, welcher Klassenname zu dem Action-Wort gehört. 
- Für den Request wird eine Instanz dieser Controller-Klasse erzeugt, nur auf Grundlage des Klassennamens als String.
- Da die Controller-Instanzen alle auf das Interface "AllgemeinerController" hören, wird beim frisch erzeugten Objekt (der Controllerklasse XY...) die Methode "verarbeiteRequest" aufgerufen.

Stellt sich die Frage:
Hat es überhaupt Sinn, für jeden Request eine Instanz des jeweiligen Controllers zu erzeugen? Oder reicht eine einzige Instanz für alle Requests (auch exakt gleichzeitige), solange nicht künstlich irgendwelche Threadsafety-kaputtmachenden Dinge gemacht werden (z.B. konkurrierender Zugriff auf Variablen im Klassen- oder Objekt-Scope).
Denn sonst könnte man ja auch statt der eingangs vorgeschlagenen HashMap<String,String> (ActionWort -> Klassenname) auch direkt machen HashMap<String,AllgemeinerController>, sodass jedem Actionwort eine Instanz eines Objekts zugeordnet wäre, das das Interface erfüllt. Diese Zuordnung könnte ja in einem _static initializer_ des Dispatchers erfolgen. So würde die eine (ganz zu Beginn erzeugte) Instanz des Controllers aus der HashMap alle Requests handlen.

D.h. ganz kurz reduziert: Controllerklassenname als String in die HashMap oder gleich eine aufrufbare Instanz der spezifischen Controllerklasse? Was spricht für das eine, was für das andere?

*Zum Sinn der Sache:* Es geht mir jetzt gerade nicht darum, wie man das am effektivsten und zeitsparendsten in einem Echtprojekt löst (Da implementiert man natürlich nicht alles mühsam zu Fuß, das ist klar, Frameworks gibt es nicht bloß zum Spaß), sondern es ist heute eher die akademische Überlegung, wie MVC in "Java/Servlet-pur" am besten angenähert werden kann, ohne eine bestimmte Third-Party-Framework-Lösung heranzuziehen. D.h. es soll so allgemein gehalten sein wie möglich. 
Es geht darum, das Konzept mal in Java-pur zu sehen und nicht es mit Fertigkomponenten möglichst komfortabel und schnell zu produzieren.

Die üblichen Beispiele dazu mit Plain-Servlet sind ja i.d.R. so primitiv (insb. kein zentraler Controller, über den erst mal alle Requests geleitet werden), dass sie sich gedanklich auf reale Probleme kaum übertragen lassen (ein Servlet, eine JSP-Seite als View zum Draufforwarden und eine JavaBean für die View-Daten oder so ungefähr). Klar, man kann für jedes Formular als POST-Datenempfänger ein eigenes Servlet als Controller implementieren, aber das wär ja ziemlich redundant und unübersichtlich, wenn gemeinsamer, gleicher Verarbeitungscode in x verschiedenen Servlets vorkäme. 

Gruß und danke euch schon mal für alles Mit-Überlegen,
Hank Scorpio

PS: Achja, und ein schönes Wochenende an alle! ...und ein noch schöneres für alle, die Überlegungen beisteuern...


----------



## Ullenboom (4. Jan 2013)

Wenn ich das mal mit anderen GUIs vergleiche, werden die Controller/Presenter immer neu aufgebaut pro Request. Objekterzeugung koste in Java quasi nix mehr. Warum eine Map füllen? Das ist ja Zustand und den möchte man i.d.R. vermeiden. Je zustandsloser desto besser.


----------



## HankScorpio (4. Jan 2013)

Hallo Herr Ullenboom,

vielen Dank für die schnelle Antwort und, wo ich schon mal die Gelegenheit habe: *Vielen Dank für Ihr Standardwerk zur Java-Programmierung!* Das Java-Insel-Buch war mir schon oft sehr nützlich und ich habe es auch vielfach weiterempfohlen.



Ullenboom hat gesagt.:


> Wenn ich das mal mit anderen GUIs vergleiche, werden die Controller/Presenter immer neu aufgebaut pro Request.


Gut, danke für den Hinweis! Dann werd ich das auch in der Richtung weiterüberlegen.



Ullenboom hat gesagt.:


> Warum eine Map füllen? Das ist ja Zustand und den möchte man i.d.R. vermeiden. Je zustandsloser desto besser.


Auf die Map war ich gekommen, als ich überlegt habe, wie man die "Staffelholz-Übergabe" vom zentralen Controller/Dispatcher an die einzelnen "Sub-Controller"/Actions machen könnte, also den logischen Link zwischen einem Query-String-Parameter-Wert ("action=XY") und der dafür aufzurufenden Controller-Klasse ("XYController").

Da waren mir verschiedene Möglichkeiten eingefallen:

die besagte Map als "Controller-Verzeichnis", entweder als <String,String(Klassenname)> oder <String,Controller(Instanz)>
Da die Information, welche Klasse zu welchem Action-Wort gehören soll, über den ganzen Lebenszyklus der Anwendung hinweg unverändert bliebe und für jeden Request nur ausgelesen werden würde, dachte ich, es wäre vielleicht nicht verkehrt, sie als Quasi-Konstante/Zustand zu behalten
Reflexion: nach allen Klassen suchen, die als Controller taugen (--> Annotation auswerten)
ein langer if-elseif-...-Block a la 

```
//Pseudocode auf die Schnelle
AllgemeinerController zustaendigerController = null;
if (action.equals("invokeMeasurement")) {
  zustaendigerController = new MeasurementInvoker();   // public class MeasurementInvoker implements AllgemeinerController { ...
} else if (action.equals("prepareTea")) {
  zustaendigerController = new TeaPot();   // public class TeaPot implements AllgemeinerController { ...
} else if (...) {
  ...
}
if (zustaendigerController == null) {
   System.err.println("Ups, kein passender Controller gefunden. Das wäre ein 404er.");
} else {
   zustaendigerController.verarbeiteRequest(...);
}
```
So wäre es wohl am einfachsten, aber das ist natürlich auch nicht gerade "schön". :/ Eine Map mit der Zuordnung ("Action"-->Klassenname) hingegen könnte man auch einfach aus einer externen XML-/CSV-/...-Datei aufbauen und bräuchte sie gar nicht fest im Code zu hinterlegen.

Nach Klassen zu suchen, die eine Annotation als Controller haben und dann daraus die Informationen zum "Action-Wort" auszulesen (Variante 2 / Reflexion), wäre vielleicht die eleganteste Lösung, oder? [size=-2](wäre zugegebenermaßen keine ganz eigene Neuerfindung  )[/size]

Gruß,
Hank Scorpio


----------



## Ullenboom (5. Jan 2013)

Wenn die Web-App geladen wird, alle Klassen suchen, die eine Annotation tragen. Die Map als Assoziativspeicher ist dann ein Cache, ja das ist ratsam, denn pro Request alle Klassen suchen ist nicht so pralle. Wichtig ist, wo man den Cache "ablegt" (Klassenlader bedenken). Auf den Cache kann der Front-Controller zurückgreifen und dann weiterleiten. Den Weg über die Annotationen gehen einige Fameworks, finde ich nett. Sicherlich lohnt es sich, zu lernen, wie andere Frameworks wie Wicket, Spring MVC, Stripes arbeiten.


----------



## maki (5. Jan 2013)

struts 1.x hat so ähnlich funktioniert, erwähnehnenswert ist da auch das Commandpattern, typisiert wäre dann sowas wie eine Map<Command,Controller> möglich.


----------

