# HttpServlet konstruktor und init()-funktion?



## ruutaiokwu (13. Mai 2011)

hallo zusammen,

kann mir jemand sagen, wann der konstruktor und wann die init()-funktion eines servlets aufgerufen wird?

ist es möglicherweise so, dass wenn eine hohe anzahl von requests auf das servlet gemacht wird, sich verschiedene instanzen des HttpServlet bilden, welche in unterschiedlichen threads laufen?

(also der konstruktor pro servlet möglicherweise > 1 mal aufgerufen wird)

wie sieht es mit der init-funktion aus? in der api-dok lese ich folgendes: 

"A convenience method which can be overridden so that there's no need to call super.init(config)."

???

danke & grüsse, 
jan


----------



## maki (13. Mai 2011)

> (also der konstruktor pro servlet möglicherweise > 1 mal aufgerufen wird)


Das geht nicht 



> wie sieht es mit der init-funktion aus? in der api-dok lese ich folgendes:


Init wird vom ServletContainer aufgerufen bevor der erste Request an das Servlet weitergeleitet wird.

Die Servlet Spek. sagt auch viel zu diesem Thema.

Hast du denn ein konkretes Problem?


----------



## ruutaiokwu (13. Mai 2011)

hallo maki,

danke für deine antwort!

nein, ein konkr. problem habe ich soweit nicht, frage mich nur jedes mal was ich wo reinschreiben soll? (trotzdem hat's soweit immer funktioniert, fragt sich nur auf welche weise...?)

wenn diese aussage von mir nicht stimmt: "(also der konstruktor pro servlet möglicherweise > 1 mal aufgerufen wird)"

dann stimmt wohl diese auch nicht?

-> "ist es möglicherweise so, dass wenn eine hohe anzahl von requests auf das servlet gemacht wird, sich verschiedene instanzen des HttpServlet bilden, welche in unterschiedlichen threads laufen?"


es ist also immer nur 1 instanz davon im speicher? wie sieht es mit dem threads auf bei einer hohen anzahl requests, weisst du das evtl.?


gruss, jan


----------



## maki (13. Mai 2011)

Denke da gab es ein Missverständniss..
Pro Instanz kein der Konstruktor nur einmal aufgerufen werden, nämlich um eine Instanz zu erzeugen 

Kann sein dass ich mich irre, aber ServeltPooling sollte es nicht (mehr) geben, d.h. pro ServletContainer & ServletMapping eine Instanz des Servlets, durch das alle Requests/Threads geschleust werden, ist auch kein Problem, denn Sevlets müssen von Haus aus Multithreadingfähing sein, das SingleThreadedModel ist Deprecated.

In der init() Methode kann man initialisierungen von Ressourcen durchführen und die servlet-init Paramter aus der web.xml einlesen.


----------



## ruutaiokwu (16. Mai 2011)

"Pro Instanz kein der Konstruktor nur einmal aufgerufen werden, nämlich um eine Instanz zu erzeugen"

ja, da gab es offensichtlich ein missverständnis... natürlich klar! ;-)

konkret geht es darum, properties-files (name/value) zu laden, in das erfolgt per singleton (man muss dann halt den server neu starten, ist aber resourcenschonender...)

die singleton-methode getInstance(...) kann eine IOException werfen, dort fängt das problem an. wenn das nicht der fall wäre, könnte ich bereits im klassenrumpf folgendes schreiben:

*private static final Properties myprop = ResourceLoader.getInstance();*



stattdessen gibt es nun halt andere möglichkeiten:


1:


```
public class MyServlet extends HttpServlet
{
// static, final & nicht definiert, muss also im static-konstruktor geladen werden...
// könnte auch NICHT "final" sein...
private static final Properties myprop;

 static
    {
        try
        {
            myprop = ResourceLoader.getInstance();
        }
        catch (final IOException e)
        {
            throw new RuntimeException("Problem while loading properties file: " + e);
        }
    }

}
```
-> hier habe ich die sicherheit, dass der static-block 100%ig garantiert nur 1x ausgeführt wird! (unabhängig von servlet api, im ggs. zur init-funktion...)


2:



```
public class MyServlet extends HttpServlet
{
// final & nicht definiert, muss also im konstruktor geladen werden...
// könnte auch NICHT "final", möglicherweise aber "static"...
private final Properties myprop;

 public MyServlet()
    {
        try
        {
            myprop = ResourceLoader.getInstance();
        }
        catch (final IOException e)
        {
            throw new RuntimeException("Problem while loading properties file: " + e);
        }
    }

}
```
-> wenn WIRKLICH nur 1 exemplar instanziert wird, auch kein problem...


3:


```
public class MyServlet extends HttpServlet
{
// könnte auch "static" sein !!!
private Properties myprop = null;

@Override
    public void init(final ServletConfig config) throws ServletException
    {
         try
        {
            myprop = ResourceLoader.getInstance();
        }
        catch (final IOException e)
        {
            throw new RuntimeException("Problem while loading properties file: " + e);
        }
    }

}
```


4: die andere möglichkeit wäre, die IOException in der singleton-klasse zu catchen, und an eine RuntimeException weiterzugeben. so dass getInstance() *direkt* im klassenrumpf ausgeführt werden könnte...



fall 4 ist natürlich ein wenig ein anderes thema... da kann man keine exceptions mehr catchen.

angenommen man hat die zahl zwischen 1-3, was ist am sinnvollsten? was würdest zu sagen?


gruss, jan


----------



## ruutaiokwu (16. Mai 2011)

jmar83 hat gesagt.:


> "Pro Instanz kein der Konstruktor nur einmal aufgerufen werden, nämlich um eine Instanz zu erzeugen"
> 
> ja, da gab es offensichtlich ein missverständnis... natürlich klar! ;-)
> 
> ...


----------



## maki (16. Mai 2011)

1-3 sind nicht sinnvoll imho.
4 ist genauso sinnvoll wie die anderen, warum man keine RuntimeException catchen können soll ist nicht logisch.

Sehe keine Notwendigkeit für ein Singleton, dafür kann man auch sehr gut den ApplicationScope nutzen, oder besser gleich Serlvet Init Parameter.

Wie groß ist denn deine Property Datei? Warum nutzt du keine Servlet Init Parameter (liest die in der Init Methode)?


----------



## ruutaiokwu (16. Mai 2011)

hallo maki,

*"da kann man keine exceptions mehr catchen"*

sollte heissen

*"da MUSS man keine exceptions mehr catchen"*

habe da immer wieder ein durcheinander mit diesem RuntimeException's

*"Sehe keine Notwendigkeit für ein Singleton, dafür kann man auch sehr gut den ApplicationScope nutzen, oder besser gleich Serlvet Init Parameter."*

ja, dann hat man das objekt für sämtliche webapplikationen verfügbar, unabhängig von request, session, einzelner webapplikation etc... nur: man sollte doch dafür sorgen, dass die instanz, die man der ApplicationScope.setAttribute(str, obj) mitgibt, sich nicht bei jedem request neu kreiert wird?

den application scope hätte man innerhalt der init(...)-funktion verfügbar, richtig? (nicht aber innerhalb des konstruktor, schon gar nicht innerhalb des static-konstruktors!)

also innerhalb der init-funktion ("local scope") die properties instanzieren, und dem application scope setzen? wäre das sauber?


servlet-init parameter geht nicht, das liest ja die web.xml aus... nicht geeignet in meinem fall...

gruss, jan


p.s.: habe meine codes nachträglich kommentiert, so gut es geht begründet...


----------



## maki (16. Mai 2011)

> "da MUSS man keine exceptions mehr catchen"
> 
> habe da immer wieder ein durcheinander mit diesem RuntimeException's


Verstehe nicht was du damit sagen willst, unchecked Exceptions kann man genauso catchen wie checked Exceptions.
Bei einer IOException während dem auslesen der Conig parameter sollte es allerdings egal sein ob du catched oder nicht, heisst  erstmal die App kann nciht hochgefahren werden.
Wenn es ein durcheinander gibt liegt das nciht daran ob checked oder unchecked Exceptions verwendet werden, wobei checked Excetpions schaffen mehr durcheinander.



> ja, dann hat man das objekt für sämtliche webapplikationen verfügbar, unabhängig von request, session, einzelner webapplikation etc...


Hö?
Nein, ganz und gar nicht.



> nur: man sollte doch dafür sorgen, dass die instanz, die man der ApplicationScope.setAttribute(str, ojb) mitgibt, sich nicht bei jedem request neu kreiert wird?


Wieso habe ich das Gefühl dass wir nicht von denselben Dingen reden?



> also innerhalb der init-funktion ("local scope") die properties instanzieren, und dem application scope setzen? wäre das sauber?


Zumindest besser als das was du jetzt so treibst.
Was ein local Scope ist weisst nur du allein.



> servlet-init parameter geht nicht, das liest ja die web.xml aus... nicht geeignet in meinem fall...


Warum sollte das nciht geeignet sein?


----------



## ruutaiokwu (16. Mai 2011)

1. muss != kann

```
public class SoWieSo
{

// getInstance1 throws RuntimeException
private static final Object o1 = Singleton.getInstance1();
// -> geht im klassenrumpf, da try/catch bei RuntimeException NICHT ZWANGSLÄUFIG notwendig, aber möglich...

// getInstance2 throws IOException
private static final Object o2 = Singleton.getInstance2();
// -> geht NICHT im klassenrumpf, da try/catch bei IOException ZWANGSLÄUFIG notwendig...
}
```


2.was ist denn der application scope, PRO SERVLET (nicht für das ganze deployment) IMMER verfügbar, request- und session-unabhängig?


3. möglichweise?

4. keine members in spiel bringen: da die init-funktion nur 1x aufgerufen wird, kann die ganze Properties-geschichte dort LOKAL instanziert, und dem applications scope mitgegeben werden...


5. u.a. handelt es sich um sprachresourcen...


gruss, jan


----------

