# Im PhaseListener Service Methode aufrufen



## internet (18. Apr 2011)

hallo,
ich habe folgendes Problem:
Ich möchte beim Betreten der Seite überprüfen, ob ein User bereits aktiviert wurde.
Das mache ich über den PhaseListener
Im Link ist ein AktivierungsKey. Diesen bekomme ich auch durch ExternalContext extCtxt.
Nun muss ich aber eine Datenbankabfrage machen, ob zu irgendeinem User dieser Aktivierungsschlüssel gibt.
Diese Methode ist aber in einer Service Klasse.
Bei diesem Aufruf bekomme ich immer eine NullPointerException.
Demnach ruft der PhaseListener nicht die Service Klasse auf, in der diese Methode ist.
Muss ich irgendwo noch diese Service Klasse deklarieren (web.xml oder faces-config) ?

Hier die Methode im PhaseListener:

```
public void beforePhase(PhaseEvent event) {
		Map<String, Object> sessionMap = FacesContext.getCurrentInstance()
				.getExternalContext().getSessionMap();
		try {

			Object principal = SecurityContextHolder.getContext()
					.getAuthentication().getPrincipal();

			
			// Informationen zum eingeloggten Benutzer bekommen
			//UserDetails user = (UserDetails) principal;

			// Wenn der User noch nicht eingeloggt ist, sondern ein sog.
			// "anonymousUser" ist, dann

			if (principal.equals("anonymousUser")) {
				System.out.println("2");
				principal = null;
			}
			
			if (principal == null) {
							
				FacesContext jsf = FacesContext.getCurrentInstance();
				ExternalContext extCtxt = jsf.getExternalContext();
				String activateKey = extCtxt.getRequestParameterMap()
						.get("act");
				System.out.println("Activation KEy: " + activateKey);
				if (activateKey != null) {
					System.out.println("5");
					try {
						System.out.println("6");
						userSpring.findUserByActivationKey(activateKey);
						System.out.println("7");
					} catch (UserNotFoundException e) {
						
						// TODO Auto-generated catch block
						e.printStackTrace();
					}

				}
			}
		}

		catch (NullPointerException e) {
			sessionMap.clear();
		}

		System.out.println("Before Phase: " + event.getPhaseId());

	}
```



Der Aufruf in faces-config


```
<lifecycle>
		<phase-listener>com.example.util.QueryPhaseListener</phase-listener>
	</lifecycle>
```


----------



## Sym (18. Apr 2011)

Ist Deine Service-Klasse die UserSpring?

Wie injectest Du diese? 

So aus dem Stehgreif meine ich, dass PhaseListener keine Injections zulassen. Hol Dir Deine Service-Klasse mal über den FacesContext.


----------



## internet (18. Apr 2011)

Ja, UserSpring ist meine Service Klasse.
		Leider bin ich (noch nicht) der Experte.
		Bezüglich Injecten:
		Reicht das nicht, wenn ich im PhaseListener ein Getter + Setter habe für die UserSpring?
		Wie geht das mit dem FacesContext?
		Ich weiß wie man eine andere ManagedBean aufrufen kann:
		zB:
		AndereMgdBean andereBean = (AndereMgdBean) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("andereBean");

		Geht das genauso, wenn ich die Service Klasse aufrufe? Also:
		UserserviceImpl userserviceImpl = (UserserviceImpl) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("userserviceImpl");


----------



## Sym (18. Apr 2011)

Ja, die kannst Du genauso ziehen, wenn es eine Sessionbean ist. Wie sieht denn der Code der Bean aus?


----------



## internet (18. Apr 2011)

Die Service Klasse ist doch mit @Service annotiert.
Also sowas hier:

```
@Service(UseradministrationService.NAME)
	@Transactional(propagation=REQUIRED)
	public class UseradministrationServiceImpl implements Serializable,UseradministrationService{// Hier alle Methoden, u.a. die Methode, die aufgerufen werden soll....}
```
 
Das heißt: Ich muss die Service Klasse bzw. die Methode in der Service Klasse über eine andere ManagedBean aufrufen?


----------



## Sym (18. Apr 2011)

Wie hast Du die Bean im JSF-Context bekannt gemacht?


```
<managed-bean>
    <managed-bean-name> userSpring </managed-bean-name>
    <managed-bean-class>my.package.userSpring</managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>    
</managed-bean>
```

Entsprechend des Scopes muss Du Dir die Bean wie oben beschrieben laden.


----------



## internet (18. Apr 2011)

Also bisher habe ich in der faces-config gar keine bean bekannt gemacht.
	Grund: Weil ich beim Starten der Applikation keine Methoden aufgerufen habe.
	Erst wenn die index - Seite aufgerufen wurde kann man Methoden aufrufen.
	zb User einloggen. Das funktioniert auch.

	Aber nochmal die Frage: Die userSpring ist bei mir doch eine Service - Klasse und nicht
	eine ManagedBean. Du gibst allerdings das an:

		<managed-bean-name> userSpring </managed-bean-name>

		Ist das so richtig?


----------



## Sym (18. Apr 2011)

Wenn ich Dich richtig verstanden habe, ist Deine Service-Klasse eine Spring-Bean. Damit diese im JSF-Context verfügbar ist, muss Du diese auch in der faces-context.xml deklarieren. 

Alternativ kannst Du Dir die Bean auch über den Spring-Context holen. Dafür wäre ein entsprechender Eintrag in der web.xml notwendig - falls dieser nicht schon vorliegt.

Ich würde Dir ansonsten google ans Herz legen und nach "spring bean jsf context" oder ähnliches suchen.

edit: 



internet hat gesagt.:


> Aber nochmal die Frage: Die userSpring ist bei mir doch eine Service - Klasse und nicht
> eine ManagedBean.?


Sie ist ein Service im Spring-Sinne und eine Managed-Bean im JSF-Sinne.


----------



## internet (19. Apr 2011)

Hallo,
also ich habe in der beforePhase nun folgender Methodenaufruf

```
UseradministrationServiceImpl userSpring = (UseradministrationServiceImpl) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("userSpring"); 
userSpring.findUserByActivationKey(activateKey);
```

Hier fliegt er mir aber immer raus.
In der faces-config steht bei mir das hier:


```
<managed-bean>
		<managed-bean-name>userSpring</managed-bean-name>
		<managed-bean-class>com.example.useradministration.awk.UseradministrationServiceImpl</managed-bean-class>
		<managed-bean-scope>session</managed-bean-scope>
	</managed-bean>
```


Warum bekomme ich da immer eine NullpointerExcption?
Was mache ich falsch?


----------



## Sym (19. Apr 2011)

Wo genau fliegt die NPE? Hast Du da mal nen Debugger drüber laufen lassen?


----------



## internet (19. Apr 2011)

genau hier:
userSpring.findUserByActivationKey(activateKey);


----------



## Sym (19. Apr 2011)

Ist denn die userSpring null oder fliegt diese Exception in der Methode? Hast Du da mal nen Debugger drüber laufen lassen?


----------



## internet (19. Apr 2011)

ja, hab ich gerade.
Die userSpring ist null


----------



## Sym (19. Apr 2011)

Hast Du Dir den Log Deines Application-Servers mal angesehen? Dort müsste zu finden sein, welche Beans initialisiert werden, bzw. wo es Probleme gibt.


----------



## internet (19. Apr 2011)

ja, habe ich.
Sehe ich aber nicht.
Ich hatte eine Bean gleich genannt - dies habe ich nun aber geändert

Es scheint mir, dass das in der faces-config nicht stimmt?


----------



## JimPanse (19. Apr 2011)

Dein Aufruf ist Falsch! 

Am besten in eine Utility-Klasse auslagern:

FacesUtil.java

```
public class FacesUtil{

public static <T> T getManagedBean(final FacesContext facesContext, final String beanName, final Class<T> expectedType) {
		
		ELContext elContext = facesContext.getELContext();
		Application application = facesContext.getApplication();
		ValueExpression ve = application.getExpressionFactory().createValueExpression
                                                                    (elContext, "#{" + beanName + "}", expectedType);
		T bean;
		try {
		
			bean = (T) ve.getValue(elContext);
		} catch (ClassCastException e) {
		//handle me
		}

		return bean;
	}
}
```

Aufruf:


```
UseradministrationServiceImpl userSpring = (UseradministrationServiceImpl) FacesUtil.getManagedBean(facesContext, "userSpring", UseradministrationServiceImpl.class); 

userSpring.findUserByActivationKey(activateKey);
```

mit 
	
	
	
	





```
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("userSpring");
```
 lädst du Parameter die in der SessionMap abgelegt worden sind!

Grüße

PS: Ich würde die Spring und die ManagedBean nicht in eine Klasse verpacken!


----------



## Sym (19. Apr 2011)

Sollte die Bean nicht in der Sessionmap abgelegt sein? Ich meine, dem ist so. 

Wobei Dein Ansatz natürlich sauberer ist. Ich würde jedoch neben der ClassCastExcpetion noch eine NPE fangen (oder dies vorher prüfen), da das Laden einer Bean über den Namen allgemein recht fehlerträchtig sein kann.


----------



## internet (19. Apr 2011)

Wenn ich dein Code einfüge, dann bekomme ich für facesContext ein Error.

```
facesContext cannot be resolved to a variable
```


----------



## Sym (19. Apr 2011)

Um Dir bei solchen Fehlern helfen zu können ist es immer sinnvoll, wenn Du genau die Stelle findest, die den Fehler wirft. Sprich einmal den Debugger starten und schauen, bis wohin Du kommst.

Und dann hilft es immer, den Fehler auch mit entsprechender Fehlermeldung zu posten.


----------



## internet (19. Apr 2011)

In der Phase Util habe ich doch den Parameter facesContext. In der Listener Klasse habe ich keine Variable namens facesContext. Das ist der Fehler. Wie muss ich die Variable deklarieren? Außerhalb der Methode oder in der Methode ?

Ps: Besten Dank euch beiden schon mal


----------



## Sym (19. Apr 2011)

Du hast doch einen FacesContext. Nur bei Dir heißt dieser jsf und nicht facesContext wie bei JimPanse.

So müsste der Aufruf aussehen:


```
UseradministrationServiceImpl userSpring = (UseradministrationServiceImpl) FacesUtil.getManagedBean(jsf, "userSpring", UseradministrationServiceImpl.class); 

userSpring.findUserByActivationKey(activateKey);
```

Oder verstehe ich Dich falsch? 

Versuch bitte zukünftig zu beschreiben, wo der Fehler auftaucht. Ist das ein Kompiler-Fehler? Oder sagt Dir das schon Deine Entwicklungsumgebung. Dann kann Dir besser geholfen werden.


----------



## JimPanse (19. Apr 2011)

2 Möglichkeiten:



```
public void beforePhase(PhaseEvent arg0){

//1. Möglichkeit
arg0.getFacesContext();

//2.Möglichkeit
FacesContext context = FacesContext.getCurrentInstance();
}
```

Du kannst die Methode auch umschreiben und dir den FacesContext in der Utility-Klasse holen!


----------

