# Spring DI



## muss_ (18. Mrz 2011)

Hallo zusammen,
ich habe in den letzten Wochen Spring 3 gelernt und nun versuche ich eine Beispielprogramm zu schreiben.Dabei bin ich aber unsicher wie weit man DI benutzen soll.

Z.B. in meinem Programm habe ich Klasse Usergroup welches nur Rechte hat und sie im Konstruktor übergeben bekommt und Klasse User welches im Konstruktor Usergroup übergeben bekommt.
Die Rechte werden aus einer Datenbank beim anmelden gelesen. Also weiss das Programm von Rechten erstmal nichts.

Ist es nun besser ein Usergroup Objekt mit DI zu erzeugen und Rechte mit setter-Methoden setzen und das gleiche mit User, oder die Objekte doch mit new erzeugen und DI nur beim Objekten benutzen bei denen ich schon im voraus weiss was ich setzen muss?

Ich hoffe ich konnte mein Problem richtig beschreiben. Danke im Voraus für die Antworten.


----------



## mvitz (18. Mrz 2011)

Da ich mal annehme, dass du neben den Rechten auch User und Usergroup aus der Datenbank holst, würde ich das hier manuell machen.

Aber z.B. die Klasse die den Datenbankzugriff macht, braucht ja die Connection zur Datenbank. Diese ist wieder ein klassischer Kandidat für DI.


----------



## muss_ (18. Mrz 2011)

Danke für die Antwort.
Ich habe nun ein anderes Problem. Ich kann die variablen von Oberklasse nicht bei Vererbung sehen.


```
public abstract class Service {
	
	private Set<Right> requiredRights = null;
	
	public Set<Right> getRequiredRights() {
		return requiredRights;
	}

	protected void setRequiredRights(Set<Right> requiredRights) {
		this.requiredRights = requiredRights;
	}
}
public class OrderService extends Service{
	private static OrderService orderService = null;    
}
```
Nun möchte ich mit DI die Rechte für OrderService setzen:

[XML]
	<bean id="service" abstract="true" class = "de.core.Service"/>


	<bean id="orderService" class="de.core.OrderService" parent = "service">
		<property name="requiredRights">
 			<set> 
 				<value>"READ"</value> 
 				<value>"WRITE"</value>
			</set>
		</property>
	</bean>
[/XML]

Ich bekomme allerdings "exception: invalid property requiredRights".
Muss ich vlt. welche Annotationen benutzen damit es funktioniert???


----------



## mvitz (19. Mrz 2011)

Der Setter muss halt Public sein.

Zudem bin ich mir nicht sicher ob du über "READ" und "WRITE" ein Objekt vom Typ "Right" injezieren kannst. Eigentlich wird Spring das als String interpretieren (ACHTUNG der String ist dann "WRITE" mit den ") und wird es auch wieder nicht injezieren können.


----------



## muss_ (19. Mrz 2011)

Danke für den Tipp.
Right ist ein enum und ohne Anführungsstriche war Spring auch in der Lage das zu setzen.

Nun habe ich eine letzte Frage:
Ich möchte z.B. beim erstellen von OrderService also im Konstruktor geguckt wird ob der User der diese Service nutzen wird auch die entsprechen Rechte hat. Wenn ich aber im Konstruktor etwas schreibe dann werden die Objekte nicht inijiziert.
Hast du vlt noch eine guter Tipp?

(ohne try-catch Block funktioniert.)

```
public OrderService(Set<Right> requiredRights) {
		this.requiredRights = requiredRights;

		try {
			isPermitted();
		} catch (NotPermittedException e) {
			e.printStackTrace();
		}
}
```


----------



## mvitz (19. Mrz 2011)

Ich nehme an, dass isPermited auf dem Set operiert?

Wenn ja, dann musst du im applicationContext (die XML Datei) anstelle von property mit constructor-arg arbeiten, dann injeziert Spring die Abhängigkeiten über den Konstruktor.


----------



## muss_ (19. Mrz 2011)

Also die XML Datei:
[XML]
	<util:set id  ="rights" set-class = "java.util.HashSet"> 
		<value>READ</value> 
		<value>WRITE</value>
	</util:set>

	<bean id="service" abstract="true" class = "de.erpel.core.Service"/>

	<bean id="orderService" class="de.erpel.core.OrderService">
		<constructor-arg ref = "rights" />
	</bean>
[/XML]
und die isPermitted():

```
public boolean isPermitted() throws NotPermittedException{
		Iterator<Right> it;
		it = requiredRights.iterator();
		
		while(it.hasNext()){
			boolean found = false;
			for(Right right : session.getUser().getRights()){
				if(it.next() == right)
					found = true;
					break;
			}
			if(found == false)
				return found;
		}
		return true;
	}
```

was meinst du mit auf dem Set operiert?


----------



## mvitz (19. Mrz 2011)

Genau das, was du machst.

Also ich hab jetzt bei mir einmal folgendes kleines Beispiel erstellt:


```
import java.util.Set;
public abstract class Service {
    private final Set<String> requiredRights;
    public Service(Set<String> requiredRights) {
        this.requiredRights = requiredRights;
    }
    public Set<String> getRequiredRights() {
        return requiredRights;
    }
}
```


```
import java.util.Set;
public class OrderService extends Service {
    public OrderService(Set<String> requiredRights) {
        super(requiredRights);
        for (String right : getRequiredRights()) {
            System.out.println(right);
        }
    }
}
```
[XML]<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  <bean id="orderService" class="OrderService">
    <constructor-arg>
      <set>
        <value>READ</value>
        <value>WRITE</value>
      </set>
    </constructor-arg>
  </bean>
</beans>[/XML]

```
public class Main {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        Service service = ctx.getBean("orderService", Service.class);
    }
}
```

Gibt folgende Ausgabe:

```
19.03.2011 15:17:02 org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@45a877: startup date [Sat Mar 19 15:17:02 CET 2011]; root of context hierarchy
19.03.2011 15:17:03 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [applicationContext.xml]
19.03.2011 15:17:03 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1bcc0bc: defining beans [orderService]; root of factory hierarchy
READ
WRITE
```


----------



## muss_ (19. Mrz 2011)

Danke für deine Mühe.
Aber soweit kam ich auch, meine Frage ist nun wie kann ich bei Konstrutor OrderService die Methode isPermitted() aufrufen kann.


----------



## mvitz (19. Mrz 2011)

Du möchtest, also, ohne das du das in Java formulierst dafür sorgen, dass die Methode isPermitted automatisch von Spring aufgerufen wird?

Das geht dann aber weit über DI hinaus. Möglich ist das wohl über AspectJ bzw. Spring AOP. Oder aber über Spring Lifecycle Methoden (glaube zumindest das es die gibt).


----------



## Jay_030 (20. Mrz 2011)

Wenn du Methoden durch Spring absichern möchtest (z.B. Exception, wenn User die Rechte nicht hat, um den Service zu nutzen), solltest du dir Spring Security anschauen. Das deckt u.a. diese Belange ab.


----------



## muss_ (20. Mrz 2011)

Jay_030 hat gesagt.:


> Wenn du Methoden durch Spring absichern möchtest (z.B. Exception, wenn User die Rechte nicht hat, um den Service zu nutzen), solltest du dir Spring Security anschauen. Das deckt u.a. diese Belange ab.


Eigentlich suche ich genau das. Danke für den Tipp


----------

