# Spring - @Autowired funktioniert nicht



## y0dA (7. Nov 2010)

Hallo!
Im Detail bin ich gerade dabei ein Projekt mit
-) Maven
-) JSF 2.0
-) Spring 3.0
-) Tomcat 6.0

aufzusetzen.

Maven und JSF 2.0 klappt mittlerweile jedoch schaffe ich es gerade nicht dass die Dependency Injection funktioniert mit Annotationen.

spring.config.xml (applicationContext.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" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
         [url]http://www.springframework.org/schema/beans/spring-beans-3.0.xsd[/url]
         [url=http://www.springframework.org/schema/context]Index of /schema/context[/url]
         http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<!-- Scan classpath for Spring components starting at base-package. Automatically 
		inludes: - AutowiredAnnotationBeanPostProcessor - CommonAnnotationBeanPostProcessor -->
	<context:component-scan base-package="at.mpf.mybudget" />

	<context:annotation-config />
</beans>
```

CustomerService.java

```
@Service
public class CustomerService {

	public String test() {
		return "ruf mich an!";
	}
}
```

Customer (fundiert zu Testzwecken als Controller in der Hoffnung dass DI funktioniert = Fehlanzeige):

```
@ManagedBean
@SessionScoped
@Controller
public class Customer {
	private String firstName;
	private String lastName;

	private String test;
	
	@Autowired // ist null..
	private CustomerService customerService;
	
	public String getTest() {
		return this.customerService.test();
	}

	public void setCustomerService(CustomerService customerService) {
		this.customerService = customerService;
	}

	public CustomerService getCustomerService() {
		return customerService;
	}
}
```

pom.xml - Dependencies

```
<properties>
		<myfaces.version>2.0.2</myfaces.version>
		<spring.version>3.0.4.RELEASE</spring.version>
	</properties>

	<!-- Project dependencies -->
	<dependencies>
		<dependency>
			<groupId>org.apache.myfaces.core</groupId>
			<artifactId>myfaces-api</artifactId>
			<version>${myfaces.version}</version>
			<scope>compile</scope>
		</dependency>

		<dependency>
			<groupId>org.apache.myfaces.core</groupId>
			<artifactId>myfaces-impl</artifactId>
			<version>${myfaces.version}</version>
			<scope>compile</scope>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.0</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.14</version>
			<scope>compile</scope>
		</dependency>

		<dependency>
			<groupId>commons-logging</groupId>
			<artifactId>commons-logging</artifactId>
			<version>1.1.1</version>
		</dependency>

		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-validator</artifactId>
			<version>4.0.2.GA</version>
		</dependency>

		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.4.2</version>
		</dependency>

		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.4.2</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${spring.version}</version>
		</dependency>

	</dependencies>
```


----------



## kidsos (7. Nov 2010)

Hi,

zu Testzwecken würde ich einen JUnit-Test machen. Damit bist du unabhängig von der Präsentationstechnologie (in deinem Fall JSF), so z.B.:


```
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:service.spring.xml" })
@Transactional
public class CategoryServiceTest {

	@Autowired
	private CategoryDao categoryDao;
	private Category category;

	@Before
	public void setUp() {
		category = new Category();
		category.setName("Buher");
	}

	@Test
	public void testInsert() {
		category = categoryDao.save(category);
		assertEquals(category, categoryDao.readByPrimaryKey(category.getId()));
	}
}
```

Für eine Schichtentrennung ist es auch sinnvoll gegen Interfaces zu programmieren (ist ja auch Sinn von DI)

Ich bin im übrigen an der gleichen Sache dran wie du, d.h. Webprojekt mit Maven, JSF, JPA und Spring. Vielleicht kann man hier voneinander profitieren. Für DAO-Sachen verwende ich übrigens Hades. Erspart einem jede Menge Schreibarbeit.


----------



## y0dA (7. Nov 2010)

Danke für deine Antwort.

Das man gegen Interfaces entwickelt ist mir durchaus bewusst..ich habe doch geschrieben dass oben gepostetes zu Testzwecken entstanden ist und nix mit dem eigentlichen Projekt zu tun hat 

Bezüglich dem JUnit Test, bei selbigen funktioniert die DI ebenfalls nicht (nehme an weil die spring-config.xml im WEB-INF Ordner liegt).
Wenn ich die spring-config.xml bspw. unter src/main/resource lege klappt die DI.
Brauchen die Tests nicht eigentlich immer eine eigene applicationConfig.xml oder kann ich auch auf die .xml im WEB-INF Ordner für die Tests benutzen?


----------



## kidsos (7. Nov 2010)

> Wenn ich die spring-config.xml bspw. unter src/main/resource lege klappt die DI.


Dort sollte sie auch normal hin. Bei mir liegt sie ebenfalls dort.



> Bezüglich dem JUnit Test, bei selbigen funktioniert die DI ebenfalls nicht (nehme an weil die spring-config.xml im WEB-INF Ordner liegt).


Für Tests kannst du ja den SpringJUnit4ClassRunner benutzen (konfiguriert den Container wahrscheinlich so, dass du DI auch in Tests verwenden kannst). Und mit @ContextConfiguration kannst du deine XML-Datei angeben


----------



## y0dA (7. Nov 2010)

kidsos hat gesagt.:


> Dort sollte sie auch normal hin. Bei mir liegt sie ebenfalls dort.


Da bin ich mir nicht so sicher, es ist auch egal da die DI selbst dann nicht funktioniert (also wenn die spring-config in src/main/resource liegt).
Hierbei würde mich trotzdem interessieren wie du dann in der web.xml auf die Spring Config verwiesen hast?
Bei mir (da im WEB-INF):

```
<!-- Spring configuration -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			/WEB-INF/spring-config.xml
		</param-value>
	</context-param>
```




kidsos hat gesagt.:


> Für Tests kannst du ja den SpringJUnit4ClassRunner benutzen (konfiguriert den Container wahrscheinlich so, dass du DI auch in Tests verwenden kannst). Und mit @ContextConfiguration kannst du deine XML-Datei angeben


Hmm?
Wie gesagt, den Test habe ich zum laufen bekommen.

Zum eigentlichen Problem gibts keine Idee, also warum es in der Webapplikation nicht funktioniert?


----------



## kidsos (7. Nov 2010)

Hm, im Moment programmiere ich noch den Service-Teil meines Projekts, d.h. wie dann das in meine Web Application kommt, damit hab ich mich noch gar nicht beschäftigt. Ich orientiere mich ein bissl an diesem Beispiel (das man auch runterladen kann). Dort wird Spring bspw. so konfiguriert:
[XML]<!-- Spring configuration-->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			/WEB-INF/web.spring.xml
            classpath:service.spring.xml
		</param-value>
	</context-param>[/XML]
D.h. einmal gibt es eine Spring Config für den Service- und dann noch eine für den Web-Teil (dort wird das Projekt in mehrere Module aufgeteilt, zur besseren Trennung).


----------



## y0dA (7. Nov 2010)

Selbiges Tutorial habe ich auch schon durch 

Naja vllt. kommt ja noch von anderer Stelle ein Hinweis.

Abgesehen davon, wie löst du die Sache mit Maven - hälst du dich an die Projektstruktur des Tutorials? Also das der Webcontent unter src/main/webapp zu finden ist? Machst du in der Console immer ein mvn eclipse:eclipse - dadurch bekomme ich nämlich "Referenced Libraries" welches für mich neu ist - kannte eigentlich immer nur die "Maven Dependencies" Lib. Vorteil an mvn eclipse:eclipse ist jedoch zweifellos dass unter Deployment Assembly die libs gesetzt werden, das kann m2clipse meines Wissens nicht.


----------



## y0dA (8. Nov 2010)

```
@ManagedBean
@SessionScoped
public class Customer {
    private String firstName;
    private String lastName;
 
    private String test;
    
    @Autowired // ist null..
    private CustomerService customerService;
}
```
--> *@ManagedBean*
--> *@Autowired*
Kann es sein dass man die JSF Annotationen und die Spring Annotationen nicht mischen darf?


----------



## Gast2 (8. Nov 2010)

Ist CustomerService überhaupt als Bean in der config deklariert?


----------



## y0dA (8. Nov 2010)

SirWayne hat gesagt.:


> Ist CustomerService überhaupt als Bean in der config deklariert?



Hmm?

Dachte genau dafür gebe es Annotationen (hier bspw. @Service), damit ich sie eben nicht mehr angeben muss.


```
@Service
public class CustomerService {
..
}
```


----------



## Gast2 (8. Nov 2010)

Ich weiß nicht was die Annotation macht...
Aber um den Fehler einzuschränken kannst sie ja mal deklarieren ob es dann geht, 
vielleicht wird auch der appilcation context gar nicht gelanden


----------



## kidsos (8. Nov 2010)

> Abgesehen davon, wie löst du die Sache mit Maven - hälst du dich an die Projektstruktur des Tutorials?


Im Prinzip schon. Hab mich auch zu Multimodule-Projekten mit Maven etwas belesen und finde die Struktur eigentlich auch gar nicht so schlecht. Der Vorteil ist, du kannst den Service-Teil vollkommen unabhängig von dem Presentation Layer testen. Wenn ich dann bspw. JSF verwenden möchte (was ich noch machen möchte; momentan bin ich noch am probieren, wie ich ein Maven-Projekt mit JSF aufsetze, habs fast geschafft), dann mache ich einfach ein Webapp-Projekt auf oder was auch immer. Das steht mir frei. Nebenbei kann ich natürlich immer noch nachschauen, wie der Autor das in dem Beispiel gemacht hat.

Für die Maven-Projekterstellung verwende ich m2eclipse, arbeite gar nicht mit der Konsole.

In deinem ApplicationContext.xml (bei dir spring.config.xml) muss noch so etwas wie das hier stehen, damit Spring die Beans auch solche erkennt:
[XML]<context:component-scan base-package="deinPackageName">
	</context:component-scan>[/XML]


----------



## y0dA (9. Nov 2010)

kidsos hat gesagt.:


> [XML]<context:component-scan base-package="deinPackageName">
> </context:component-scan>[/XML]


Siehe meine spring-config.xml

Naja komme wohl erst wieder morgen dazu zu testen woran es liegt, gebe dann noch bescheid was das Problem war (sofern lösbar).


----------

