EJB: Dependecy Injection funktioniert nicht

2AndAHalfBit

Aktives Mitglied
Guten Abend,

ich schreibe mir gerade eine EE-Application mit dem Glassfish-Applikationsserver als Background und habe folgendes Problem: Ich habe eine Managed Bean, über die über DI eine SessionFassade instanziert werden soll. Das passiert jedoch nicht (ich bekomme beim Aufruf der ersten Methode eine NullPointerException.

Kann mir jemand einen Tip geben, wie ich das Problem weiter analysieren kann bzw. wie ich an die notwendigen Informationen komme?

Danke für eure Hife im vorraus.

Grüße
 

2AndAHalfBit

Aktives Mitglied
Hi,

hast ja recht. Ich versuche mal das wesentliche rauszusuchen.

Hier die managed bean:

Java:
public class ProtudoWebFassade
{
	@EJB
	private ProtudoLocalSessionFacadeInterface _ejb;
	
	public String DoTest()
	{
		System.out.println("DoTest");
		
		if( _ejb == null)
			throw new NullPointerException("The EJB is null. But why???");
		return _ejb.GetDummyString();
	}

	public List<Task> GetAllTasks()
	{
		return _ejb.GetAllTasks();
	}
}

Das Businessiterface (für Local, das Remote spare ich mir weil es sieht genauso aus:


Java:
@Local
public interface ProtudoLocalSessionFacadeInterface
{
    public List<Task> GetAllTasks();

    public Task CreateTask();

    public Task SaveTask();

    public Task GetTaskById(int id);
    
    public String GetDummyString();
}


und die implementierung
Java:
@Stateless
public class ProtudoSessionBean implements ProtudoLocalSessionFacadeInterface, ProtudoRemoteSessionFacadeInterface
{
    @EJB
    private TaskSessionBeanInterface _taskEJB;

    @Override
    public List<Task> GetAllTasks()
    {
	List<Task> mockList = new ArrayList<Task>();
	
	for(int i=0; i<10; i++)
	{
	    Task task = new Task();
	    task.setId(i+1);
	    task.setName("Autogenerated Task No. " + (i+1));
	    
	    mockList.add(task);
	}
	
	return mockList;
    }

    @Override
    public Task CreateTask()
    {
	return _taskEJB.CreateTask();
    }

    @Override
    public Task SaveTask()
    {
	return _taskEJB.SaveTask();
    }

    @Override
    public Task GetTaskById(int id)
    {
	return _taskEJB.GetTaskById(id);
    }

    @Override
    public String GetDummyString()
    {
	return "It works.";
    }

}

Das Problem ist aber eigentlich nur, dass er die DepencyInjection nicht ausführt (ich bekomme auch keine Exception). Ich bekomme die von mir ausgelöste NullPointerException.

Grüße
 

2AndAHalfBit

Aktives Mitglied
//update: Es funktioniert, wenn man einen expliziten JNDI-Lookup verwendet:

Java:
	//@EJB
	private ProtudoLocalSessionFacadeInterface _ejb;

	public String DoTest()
	{
		System.out.println("DoTest");

		if (_ejb == null)
		{
			try
			{
				InitialContext context = new InitialContext();
				_ejb = (ProtudoLocalSessionFacadeInterface)context.lookup("java:global/Protudo/Protudo-EJB/ProtudoSessionBean!server.interfaces.domain.ProtudoLocalSessionFacadeInterface");
				
			} catch (NamingException e)
			{
				e.printStackTrace();
			}
		}

		return _ejb.GetDummyString();
	}

den string für das lookup habe ich im output beim starten des glassfish servers gefunden.
Und nu?!

Grüße
 

2AndAHalfBit

Aktives Mitglied
Hmmm, niemand eine Idee?
Ich habe gestern das Projekt einmal auf JBoss ausprobiert, gleiche charakteristika.

Zuästzlich habe ich folgende Anmerkung in der Java API gefunden

Indicates a dependency on the local, no-interface, or remote view of an Enterprise JavaBean.

Das bedeutet doch, das hier ein Interface (Lokales Remote Interface) angegeben werden darf, oder?

Grüße
 

FArt

Top Contributor
ProtudoWebFassade ist ein POJO, da kannst du die @EJB Annotation nicht nutzen. Guckst du z.B. hier: Annotations and Dependency Injection in EJB 3.0

Noch ein paar Tipps:
-du brauchst keine extra Interfaces für remote und lokal. Ich finde es auch schöner, das Interface gar nicht zu annotieren, dafür dann im EJB eine entsprechende @Remote und @Local Annotation zu schreiben
- halte dich an Konventionen (Methodennamen klein, ...)
- in Interfaces sind alle Methoden public (braucht man nicht explizit hinzuschreiben)
- Es ist oft nicht sinnvoll die Klassen bzw. Attribute mit deren Verwendung zu benennen. So Worte wie "Session", "Fassade", "Interface", "Local", "Remote", "Mock" in der Benennung sind oft sinnvoll und wichtig, manchmal aber völlig unnötig, später u.U. irreführend, weil plötlich ungültig.
 

2AndAHalfBit

Aktives Mitglied
Hi FArt,

danke für deine Anmerkungen. Ich werde mal versuchen, nacheinander darauf einzugehen:

1. Ich werde mir deinen Link gleich mal anschauen. Das Projekt bedient sich als Vorlage einer Vorlage aus meinem Studium - dort wird es genau so gemacht. Das Beispiel wird zwar auf dem JBoss ausgeführt, aber dort funktioniert es.

2. Zu deinen Tips
- zu den Codekonvertionen: Ich mache zu 90% .NET-Programmierung. Java erst wieder seit kurzem. Wie heisst es so schön: Ich werde mich anpassen :D:lol:
- Interface / Public methoden: I know - thanks for your hint
- Klassennamen - thx

- Wenn ich es richtig verstanden habe, ist das Lokale Interface beschränkt auf Zugriffe aus der gleichen JVM. Eine Webseite oder ein Webservice können also über das lokale Business interface gehen, während Remoteanwendungen (z.B. eine Swing-Applikation oder ein Applet, welches Clientseitig ausgeführt werden) eine Remote-Schnittstelle brauchen. Dort funktioniert dann auch keine DI mehr. In meinem Projekt möchte ich beides anbieten (dort gibt es hier einen anderen Thread, der mitlerweile erledigt ist). Das Problem an der Stelle ist, dass ein Interface immer nur 1 Schnittstelle bedienen kann (entweder Local oder Remote).

Grüße,
 

2AndAHalfBit

Aktives Mitglied
Hi, noch ein Nachtrag:

Es gibt in meinem Projekt noch eine faces-config.xml. Diese liegt im WEB-INF verzeichnis meines Webarchives (zusammen mit der web.xml).

[XML]
<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">


<managed-bean>
<managed-bean-name>webFassade</managed-bean-name>
<managed-bean-class>server.web.ProtudoWebFassade</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>

<navigation-rule>
<display-name>Startseite</display-name>
<from-view-id>/home.xhtml</from-view-id>
<navigation-case>
<from-outcome>START</from-outcome>
<to-view-id>/createTask.xhtml</to-view-id>
</navigation-case>
</navigation-rule>

<application>
<view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
</application>


</faces-config>

[/XML]

Löst das die Verwirrung auf? Hiermit ist meine WebFassade kein POJO mehr, sondern eine Managed Session Bean oder?

Grüße,
 

JimPanse

Bekanntes Mitglied
Hi,

bei JBoss 5.1 + JSF muss in der web.xml folgender Eintrag stehen:

Java:
 <context-param>
 <param-name>com.sun.faces.injectionProvider</param-name>
 <param-value>org.jboss.web.jsf.integration.injection.JBossScanningInjectionProvider</param-value>
 </context-param>

dann kannst du eine EJB-Session Beans direkt über @EJB verwenden!

Grüße
 

2AndAHalfBit

Aktives Mitglied
Hallo Jim,

so etwas kann ich jetzt nicht finden. Aber das hier:

[XML]
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>

<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>

<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
[/XML]

aber das ist doch was anderes?!
 

JimPanse

Bekanntes Mitglied
???????

Die eine Konfiguration sagt darüber aus wo die Status Informationen verwalten [CLIENT o. SERVER] und der andere die Seitenbeschreibungssprache die genutzt werden soll aber ich dachte es geht darum das du EJB SessionBeans in JSF ManagedBeans verwenden möchtest oder?

d.h. schreib doch noch einmal genau was du verwendest (JSF 1.2 o. 2.0 + EJB) + Server Version!

Greetz

Hallo Jim,

so etwas kann ich jetzt nicht finden. Aber das hier:

[XML]
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>

<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>

<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
[/XML]

aber das ist doch was anderes?!
 

2AndAHalfBit

Aktives Mitglied
Ich verwende den Glassfish Open Source Application Server in der Version 3.1.1.
Innerhalb dieses Servers entwickel ich eine Session Bean, über die auf Entities beans zugegriffen werden soll.

- Die SessionBean soll als RemoteSchnittstelle für RemoteClients zur Verfügung stehen (das klappt schon),
- darüber hinaus sollen ihre Methoden auf einer Webapplikation (JSF) zur Verfügung stehen (über eine Managed Bean, die die Dienstleistung der Session Bean als Fassade anbietet und an die Bean weiterreicht)
- und es soll analog zur Webapplikation auch noch ein Webservice angeboten werden (das spielt aber momentan noch keine Rolle).

Grüße
 

2AndAHalfBit

Aktives Mitglied
Hallo Jim,

danke für deine Mühe. Ich bin jedoch nicht auf der suche nach diversen Techniken, die mir dabei helfen können, mein Problem zu lösen. Wenn es nicht lösbar ist, nun gut. Alles was ich suche, ist eine Erklärung dafür, warum das ganze in meiner Studienaufgabe (JBoss 6) klappt, und in meinem Glassfish example halt nicht.

Gegoogled habe ich selbst schon genug, das bringt mich aber hier nicht weiter.


Grüße.
 

Ähnliche Java Themen

Neue Themen


Oben