# NullpointerException



## Tarantoga (31. Aug 2011)

Hallo Leute!
Ich habe folgendes Problem.
Aus einem Controller heraus will ich eine Methode aufrufen die Werte in eine Datenbank einfügen soll.

Die DAO-Methode:

```
public void mailLookup(String mail){
      String sql = "insert into DEMO.USERS (USERNAME, PASSWORD, MAIL) values ('test', 'test', 'test')";
      Connection conn = null;
      
     
       
       try{
                 
           conn = dataSource.getConnection();
           Statement stmt = conn.createStatement();
           
           stmt.executeUpdate(sql);
           stmt.close();
        
               
          
       }
       catch(SQLException e){
         
       }              
       finally{
           if(conn != null){
               try{
                   conn.close();
               }
               catch(SQLException e){
                   
               }
           }
       }
    }
```

Ich habe sowohl die DataSource als auch das SQL-Statement ansich getestet und beide funktionieren einwandfrei. (Die DataSource wird u.a. von Spring Security verwendet und das Statement habe ich auch schon direkt auf die Datenbank abgesetzt und da gibt es keine Probleme.)

Folgender Fehler wird geworfen:
[XML]INFO: 91903 DEBUG [http-thread-pool-8080(3)] org.springframework.web.bind.annotation.support.HandlerMethodInvoker     - Invoking request handler method: public java.lang.String com.aherbsthofer.airlink.web.RegisterController.checkMail(java.lang.String)

INFO: 91903 DEBUG [http-thread-pool-8080(3)] org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver     - Resolving exception from handler [com.aherbsthofer.airlink.web.RegisterController@140df03]: java.lang.NullPointerException

INFO: 91904 DEBUG [http-thread-pool-8080(3)] org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver     - Resolving exception from handler [com.aherbsthofer.airlink.web.RegisterController@140df03]: java.lang.NullPointerException

INFO: 91904 DEBUG [http-thread-pool-8080(3)] org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver     - Resolving exception from handler [com.aherbsthofer.airlink.web.RegisterController@140df03]: java.lang.NullPointerException

INFO: 91938 DEBUG [http-thread-pool-8080(3)] org.springframework.web.servlet.DispatcherServlet     - Could not complete request


INFO: 91938 DEBUG [http-thread-pool-8080(3)] org.springframework.security.web.context.SecurityContextPersistenceFilter     - SecurityContextHolder now cleared, as request processing completed

WARNUNG: StandardWrapperValve[dispatcher]: PWC1406: Servlet.service() for servlet dispatcher threw exception
java.lang.NullPointerException
[/XML]

An was kann das liegen?
LG
Tarantoga

PS: Generell ist es ziemlich mühsam solche Methoden zu testen. Da diese nie in Main Classes sind und Netbeans ja irgendwie nur die debuggen kann.
Kennt da jemand vielleicht Möglichkeiten, das einfacher zu testen? 
Ohne alles durch Anfrage über einen Controller zu starten. Das sind ja alles zusätzliche Fehlerquellen.
(Die in obigen Fall aber mittlerweile ausgeschlossen werden können, denke ich.)


----------



## tfa (31. Aug 2011)

> An was kann das liegen?


Keine Ahnung. Aber warum verschluckst du Exceptions, ohne sie wenigsten zu loggen oder auszugeben?


----------



## nillehammer (31. Aug 2011)

Irgendwie blöd, dass die Zeilennummer nicht mit ausgegeben wird. Dann wäre es klar, an welcher Stelle versucht wird, auf eine null-Referenz zu zugreifen. So kann man anhand des geposteten Codes nur spekulieren:
1. datasource nicht initialisiert?
2. conn = dataSource.getConnection(); schmeißt eine SQLException, die verschluckt wird. Der Code läuft deswegen normal weiter und darum ist conn null und die NullPointerException fliegt in der nächsten Zeile
3. Gleiches könnte auch bei conn.createStatement(); passieren.

Ich würde mal auf 2. tippen.

Ansonsten hat tfa Recht Exceptions nie einfach schlucken, immer wenigstens loggen. In diesem speziellen Fall würde ich sie sogar in eine RuntimeException einpacken und weiter werfen, weil Dein Code nicht sinnvoll weiterarbeiten kann, wenn bei seiner Ausführung Exceptions fliegen. Die RuntimeException könnte wenigstens von Spring behandelt werden, in dem eine Fehlermeldung "Datenbank steht nicht zur Verfügung" oder so angezeigt wird.


----------



## tuttle64 (1. Sep 2011)

@Tarantoga: Füge ein simples x.printStackTrace(); im den zwei catch-Blöcken ein und poste alles was bei der Ausführung des Programms ausgegeben wird.


----------



## Tarantoga (1. Sep 2011)

Habe ich gemacht!
Leider habe ich keinen Output! Bei e.printStackTrace(); sagt die IDE "Should be removed"?

Jedoch bin ich in den Serverlogs dieser Referenz gefolgt: "at com.aherbsthofer.airlink.dao.UserDao.mailLookup(UserDao.java:92)"

Sie führt, wie nillehammer erwartet hatte, zu "dataSource.getConnection".
Ich verstehe nur nicht warum. Schließlich verwendet Spring Security genau dieselbe Datasource für die Authentifizierung.

Sie sieht so aus:
[XML]<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.apache.derby.jdbc.ClientDriver"></property>
        <property name="url" value="jdbc:derby://localhost:1527/customers; create=true"></property>
        <property name="username" value="demo"></property>
        <property name="password" value="demo"></property>
    </bean>[/XML]

LG


----------



## nillehammer (1. Sep 2011)

Wie initialisierst Du die datasource denn? Per Injection mit Spring müsste es ja gehen. Wenn Spring selbst die Datasource benutzen kann...


----------



## Tarantoga (1. Sep 2011)

Ja,
ich verwende die Injection via der @Autowired Annotation.
Und das erfolgreich in der gesamten Applikation.
Es ist wirklich eigenartig.
Was könnten den die Gründe sein, dass zb. printStackTrace() nichts ausgibt?
Tritt die Exception womöglich an anderer Stelle auf?
Sonst müsste doch im Output Window etwas zu sehen sein.

LG


----------



## nillehammer (1. Sep 2011)

> Was könnten den die Gründe sein, dass zb. printStackTrace() nichts ausgibt?


In Deinem Code fliegt keine SQLException (zu dem Teil, der eine werfen könnte, kommt er garnicht, weil vorher schon die NullPointer fliegt). Deswegen kriegst Du keinen Output.

Kann es sein, dass du dein Dao selbst initialisierst (also selbst new MyDao aufrufst)? Ich glaube, damit es mit Spring DI funktioniert, muss Spring es auch initialisieren (kenne mich mit anderen DI-Conainern aus, mit Spring leider nicht). Ansonsten poste doch mal bitte die komplette Dao-Klasse und nutze den JAVA-Tag dafür.


----------



## Tarantoga (2. Sep 2011)

```
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.aherbsthofer.airlink.dao;

import com.aherbsthofer.airlink.domain.User;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.sql.DataSource; 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTemplate;

/**
 *
 * @author ah
 */
@ManagedBean
@SessionScoped
public class UserDao {

    @Autowired
    private DataSource dataSource;
    
    @Autowired
    private HibernateTemplate hibernateTemplate;
    
    

    
       
    public void createUser(String username, String password, String mail){
        
       String sql = "INSERT INTO USERS (USERNAME, PASSWORD, ENABLED, AUTHORITY, MAIL) VALUES (?, ?, ?, ?, ?)";
       Connection conn = null;
       
       try{
        
           
           
           conn = dataSource.getConnection();
           PreparedStatement ps = conn.prepareStatement(sql);
        
           ps.setString(1, username);
           ps.setString(2, password);
           ps.setInt(3, 1);
           ps.setString(4, "ROLE_USER");
           ps.setString(5, mail);
           
           ps.execute();
           ps.close();
           
       }
       catch(SQLException e){
           
       }              
       finally{
           if(conn != null){
               try{
                   conn.close();
               }
               catch(SQLException e){
                   
               }
           }
       }
       
        
    }      
  
    
    public void saveUser(User user){
        
    }
   
    
    
    
    public void mailLookup(String mail){
      String sql = "insert into DEMO.USERS (USERNAME, PASSWORD, MAIL) values ('doris', 'doris', 'doris')";
      Connection conn = null;
      
     
       
       try{
                 
           try{
           conn = dataSource.getConnection();
           }
           catch(Exception e){e.printStackTrace();}
           Statement stmt = conn.createStatement();
           
           stmt.executeUpdate(sql);
           stmt.close();
        
               
          
       }
       catch(SQLException e){
       e.printStackTrace();
       }              
       finally{
           if(conn != null){
               try{
                   conn.close();
               }
               catch(SQLException e){
               e.printStackTrace();    
               }
           }
       }
    }
    
    
    
  }
```


Im Controller sieht es so aus:


```
@Controller
@RequestMapping("/register")
public class RegisterController {
    
    @Autowired
    private RegisterDataValidator validator;
    
    @Autowired
    private UserDao userDao;

...


@RequestMapping(value="/mail", method= RequestMethod.GET)
    public @ResponseBody String checkMail(@RequestParam("mail") String mail) {
       userDao.mailLookup(mail);
       if(validator.checkMail(mail)){	                                       
           return "o";
        }

..
```


Die Instanzierung liegt also ganz bei Spring.

LG


----------



## nillehammer (2. Sep 2011)

Der Code sieht so erstmal gut aus. Ich hab ein bischen rumgesurft. .In allen Quellen, die ich per google (Suche: spring inject datasource into dao) gefunden habe, musste man die DataSource als Spring-Bean konfigurieren, um sie injecten zu können. Oder man besorgt sie sie sich selbst über JNDI. Schonmal sorry, falls das nicht helfen sollte. Ideen habe ich sonst auch keine mehr.


----------



## Tarantoga (2. Sep 2011)

Die Datasource ist natürlich als Spring Bean registriert. 
Hmm, sehr eigenartig.
Jedenfalls vielen Dank für deine Mühen!

LG


----------

