# NestedTransaction- Exception in Hibernate



## mavinatic (5. Jan 2012)

Hallo Community, 

ich habe einen Webservice programmiert und ich benutze Hibernate. In dem Webservice wird die Aufgabe der Authentifizierung übernommen( Login, Logout, AddAccount).

Ich habe mir eine Hilfsklasse geschrieben um Transaktionsproblemen aus dem Weg zu gehen. 
HibernateFactory:

```
package com.mmo.loginservice.utils;

import java.util.Properties;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;


public class HibernateFactory 
{
	private SessionFactory factory = null;
	private Session session = null;
	
	public HibernateFactory()
	{
		
	}
	
	public Session getSession()
	{
		session = factory.getCurrentSession();
		if(session==null)
		{
			session = factory.openSession();
		}
		
		return session;
	}
	
	public void closeSession(Session session)
	{
		if(session!=null)
		{
			session.close();
		}
	}
	
	public synchronized void saveObject(Object object)
	{
		Session session = getSession();
		Transaction tx = session.beginTransaction();
		tx.begin();
		
		session.save(object);
		
		session.flush();
		
		tx.commit();
		
		session.close();
	}
	
	public synchronized void updateObject(Object object)
	{
		Session session = getSession();
		Transaction tx = session.beginTransaction();
		
		tx.begin();
		
		session.update(object);
		
		session.flush();
		
		tx.commit();
		
		session.close();
	}
	
	public synchronized void deleteObject(Object object)
	{
		Session session = getSession();
		Transaction tx = session.beginTransaction();
		tx.begin();
		session.delete(object);
		session.flush();
		tx.commit();
		session.close();
	}
	
	public void init()
	{
//		Configuration config = new Configuration();
//		Properties prop = new Properties();
//		prop.put("connection.driver_class", "org.apache.derby.jdbc.ClientDriver");
//		prop.put("connection.url", "jdbc:derby://localhost:1527/app;create=true");
//		prop.put("connection.username", "APP");
//		prop.put("connection.password", "APP");
//		prop.put("connection.pool_size", "5");
//		prop.put("hibernate.dialect", "org.hibernate.dialect.DerbyDialect");
//		prop.put("hibernate.current_session_context_class", "thread");
//		prop.put("hibernate.show_sql", "true");
//		prop.put("hibernate.hbm2ddl.auto", "update");
//		prop.put("hibernate.cache.region.factory_class", "net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory");
//		prop.put("hibernate.cache.use_second_level_cache", "true");
//		prop.put("hibernate.cache.use_query_cache", "true");
//		config.addProperties(prop);
//		

		
		AnnotationConfiguration config = new AnnotationConfiguration().configure();
		factory = config.buildSessionFactory();
	}
}
```

AccountServiceImpl - Hier sind alle Methoden des Webservice gelistet:

```
package com.mmo.loginservice.implementation;

import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

import com.mmo.loginservice.beans.Account;
import com.mmo.loginservice.beans.Session;
import com.mmo.loginservice.exception.ServiceException;
import com.mmo.loginservice.interfaces.AccountService;
import com.mmo.loginservice.utils.LoginServiceUtils;

@WebService(endpointInterface="com.mmo.loginservice.interfaces.AccountService", targetNamespace="http://loginservice.mmo.com/", portName="AccountServicePort", serviceName="AccountService")
public class AccountServiceImpl implements AccountService 
{
	private DataAccessObjectLayer daoLayer = null;
	private LoginServiceUtils utils = new LoginServiceUtils();
	
	public AccountServiceImpl(DataAccessObjectLayer dao)
	{
		this.daoLayer = dao;
	}
	
	@Override
	public Session login(String username, String password) throws ServiceException 
	{
		// TODO: Implement login_Method
		if(username!=null && password!=null)
		{
			Account account = daoLayer.getAccountByUser(username);
			if(account!=null)
			{
				String hashPassword = utils.makeSHA1(password);
				if(account.getPassword().equalsIgnoreCase(hashPassword))
				{
					Session session = daoLayer.createSession(username);
					return session;
				} else
				{
					throw new ServiceException("AccountService@login - account password wrong");
				}
			} else
			{
				throw new ServiceException("AccountService@login - account fetchedBy daoLayer == null");
			}	
		} else
		{
			throw new ServiceException("AccountService@login - no parameters");
		}		
	}

	@Override
	public void logout(Session session) throws ServiceException 
	{
		// TODO: Implement logout_Method
		if(session!=null)
		{
			String sessionkey = session.getSessionKey();
			String user = session.getUser();
			
			if(user!=null && sessionkey!=null)
			{
				Account account = daoLayer.getAccountByUser(user);
				if(account!=null)
				{
					account.setOnline(false);
					daoLayer.updateAccount(account);
					
					daoLayer.deleteSession(session);
				} else
				{
					throw new ServiceException("AccountService@login - account fetchedBy daoLayer == null");
				}
			} else
			{
				throw new ServiceException("AccountService@logout - session object isnt null but no values");
			}
		} else
		{
			throw new ServiceException("AccountService@logout - no parameteres");
		}
	}

	@Override
	public void addAccount(String username, String password) throws ServiceException 
	{
		// TODO: Implement addAccount_Method
		if(username!=null && password!=null)
		{
			String hashedPassword = utils.makeSHA1(password);
			daoLayer.createAccount(username, hashedPassword);
		} else
		{
			throw new ServiceException("AccountService@addAccount - no parameters");
		}
	}

}
```

DAOLayer - Kapselung von CRUD Methoden in einer eigenen Klasse:

```
package com.mmo.loginservice.implementation;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Transaction;

import com.mmo.loginservice.beans.Account;
import com.mmo.loginservice.beans.PlayerData;
import com.mmo.loginservice.beans.Session;
import com.mmo.loginservice.interfaces.AccountDAO;
import com.mmo.loginservice.interfaces.PlayerDataDAO;
import com.mmo.loginservice.interfaces.SessionDAO;
import com.mmo.loginservice.utils.HibernateFactory;
import com.mmo.loginservice.utils.LoginServiceUtils;


public class DataAccessObjectLayer implements SessionDAO, AccountDAO, PlayerDataDAO
{
	private HibernateFactory factory = null;
	private LoginServiceUtils utils = new LoginServiceUtils();
	
	public DataAccessObjectLayer(HibernateFactory factory)
	{
		this.factory = factory;
	}
	
	@Override
	public Session createSession(String user) 
	{
		Session session = new Session();
		session.setSessionKey(utils.createUUID());
		session.setUser(user);
		
		factory.saveObject(session);
		
		return session;
	}

//	@Override
//	public SessionTO updateSession(SessionTO session) {
//		// TODO Auto-generated method stub
//		Session plainSession = (Session) session;
//		return null;
//	}

	@Override
	public void deleteSession(Session session) 
	{
		factory.deleteObject(session);
	}

	@Override
	public Session getSessionByUser(String user) 
	{
		org.hibernate.Session hibernateSession = factory.getSession();
		Transaction tx = hibernateSession.beginTransaction();
		tx.begin();
		Query query = hibernateSession.createQuery("SELECT x FROM Session as x WHERE x.user='"+user+"'");
		List<Session> userSession = (List<Session>) query.list();
		tx.commit();
		factory.closeSession(hibernateSession);
		
		return (Session) userSession.get(0);
	}

	@Override
	public Session[] getSessions() 
	{
		org.hibernate.Session hibernateSession = factory.getSession();
		Transaction tx = hibernateSession.beginTransaction();
		tx.begin();
		Query query = hibernateSession.createQuery("SELECT x FROM Session as x");
		List<Session> userSession = (List<Session>) query.list();
		tx.commit();
		factory.closeSession(hibernateSession);
		return (Session[]) userSession.toArray(new Session[userSession.size()]);
	}

	@Override
	public Account createAccount(String username, String password)  
	{
		try
		{
			Account acc = new Account();
			acc.setPassword(password);
			acc.setUsername(username);
			acc.setOnline(false);
			SimpleDateFormat format = new SimpleDateFormat(utils.DATE_FORMAT);
			acc.setRegistred(format.format(new Date()));
			
			factory.saveObject(acc);
			
			return (Account) acc;
		} catch(Exception e)
		{
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public void deleteAccount(Account account) 
	{
		factory.deleteObject(account);
	}

	@Override
	public Account getAccountByUser(String user) 
	{
		org.hibernate.Session session = factory.getSession();
		Transaction tx = session.beginTransaction();
		tx.begin();
		
		Query query = session.createQuery("SELECT x FROM Account as x WHERE x.username='"+user+"'");
		List<Account> list = query.list();
		
		tx.commit();
		
		factory.closeSession(session);
		if(list.size()>0)
		{
			return (Account) list.get(0);
		}
		else 
		{
			return null;
		}
	}

	@Override
	public Account[] getAccounts() 
	{
		org.hibernate.Session session = factory.getSession();
		Transaction tx = session.beginTransaction();
		tx.begin();
		
		Query query = session.createQuery("SELECT x FROM Account as x");
		List<Account> list = query.list();
		
		tx.commit();
		factory.closeSession(session);
		return (Account[]) list.toArray(new Account[list.size()]);
	}

	@Override
	public void updateAccount(Account account) {
		// TODO Auto-generated method stub
		factory.updateObject(account);
	}

	@Override
	public PlayerData createPlayerData(String name) 
	{
		PlayerData data = new PlayerData();
		data.setPlayerName(name);
		data.setPosx(new Integer(0));
		data.setPosx(new Integer(0));
		
		factory.saveObject(data);
		
		return (PlayerData) data;
	}

	@Override
	public PlayerData updatePlayerData(PlayerData data) 
	{
		factory.updateObject(data);
		return (PlayerData) data;
	}

	@Override
	public void deletePlayerData(PlayerData data) 
	{
		factory.deleteObject(data);
	}

	@Override
	public PlayerData getPlayerDataByName(String name) 
	{
		org.hibernate.Session session = factory.getSession();
		Transaction tx = session.beginTransaction();
		tx.begin();
		Query query = session.createQuery("SELECT x FROM x as PlayerData x.playerName='"+name+"'");
		List<PlayerData> list = query.list();
		tx.commit();
		factory.closeSession(session);
		return (PlayerData) list.get(0);
	}

	@Override
	public PlayerData[] getPlayerData() 
	{
		org.hibernate.Session session = factory.getSession();
		Transaction tx = session.beginTransaction();
		tx.begin();
		Query query = session.createQuery("SELECT x FROM x as PlayerData");
		List<PlayerData> list = query.list();
		tx.commit();
		factory.closeSession(session);
		return (PlayerData[]) list.toArray(new PlayerData[list.size()]);
	}
}
```

Wenn ich nun mit meinem Client die addAccount-Methode ausführen möchte  bekomme ich folgende Exception:

05.01.2012 15:52:00 com.sun.xml.internal.ws.server.sei.EndpointMethodHandler invoke
SCHWERWIEGEND: nested transactions not supported
org.hibernate.TransactionException: nested transactions not supported
	at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:152)
	at com.mmo.loginservice.implementation.DataAccessObjectLayer.getAccountByUser(DataAccessObjectLayer.java:115)
	at com.mmo.loginservice.implementation.AccountServiceImpl.login(AccountServiceImpl.java:30)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at com.sun.xml.internal.ws.api.server.InstanceResolver$1.invoke(InstanceResolver.java:235)
	at com.sun.xml.internal.ws.server.InvokerTube$2.invoke(InvokerTube.java:135)
	at com.sun.xml.internal.ws.server.sei.EndpointMethodHandler.invoke(EndpointMethodHandler.java:246)
	at com.sun.xml.internal.ws.server.sei.SEIInvokerTube.processRequest(SEIInvokerTube.java:82)
	at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Fiber.java:587)
	at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Fiber.java:546)
	at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Fiber.java:531)
	at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Fiber.java:428)
	at com.sun.xml.internal.ws.server.WSEndpointImpl$2.process(WSEndpointImpl.java:232)
	at com.sun.xml.internal.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:460)
	at com.sun.xml.internal.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:233)
	at com.sun.xml.internal.ws.transport.http.server.WSHttpHandler.handleExchange(WSHttpHandler.java:95)
	at com.sun.xml.internal.ws.transport.http.server.WSHttpHandler.handle(WSHttpHandler.java:80)
	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:65)
	at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:65)
	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:68)
	at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:555)
	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:65)
	at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:527)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)

Jedoch frage ich mich wie diese Exception auffliegen kann, ich habe ja extra die Methoden aus der HibernateFactory synchronized gemacht um genau diesem Problem aus den Füßen zu gehen.

Bitte Helft mir ich verzweifel!


----------



## SlaterB (5. Jan 2012)

was läßt dich vermuten, dass synchronized mit dem Problem zu tun hat?
getAccountByUser() ist nicht synchronisiert, wieso sollte es helfen wenn andere Stellen das sind?

du könntest in getAccountByUser() auch auf das HibernateFactory-Objekt synchronisieren, dann könnte es evtl. was bringen,
aber gibt es überhaupt mehrere Threads die gleichzeitig herumgeistern, haben die dann auch zwingend dasselbe HibernateFactory-Objekt?
wo kommt dieses her?
vielleicht ist es noch schlauer, auf die Session zu synchronisieren, denn dass es sich um dieselbe Session handelt impliziert der Fehler ja,

ob parallel andere Methoden aufgerufen werden könntest du mit Logging aufklären, wenn du dir nicht sowieso schon sicher bist,


----------



## mavinatic (5. Jan 2012)

Mir ist aufgefallen dass ich eigentlich gar keine Threads habe, dass ist in einem vorgänger programmiert worden, also kann man das synchronized ignorieren.


----------



## planetenkiller (5. Jan 2012)

Nur so eine Idee: Da 
	
	
	
	





```
tx.commit();
```
 nicht in einem finally steht, wäre es vielleicht möglich, das bei bei einer Exception die Transaktion für Hibernate offen bleibt um bei weiteren aufrufen dann "nested transactions not supported" kommt?


----------



## mavinatic (5. Jan 2012)

Ich habe im finally nun auch noch ein tx.commit(); hinten dran gehängt aber ändert sich dennoch nichts!


----------



## SlaterB (6. Jan 2012)

ein Log wird dir verraten was wann passiert,
an allen Stellen die mit der Session zu tun haben, logge jeweils ob schon eine Transaktion läuft, wenn eine gestartet oder beendet wird,

komfortabler wird es mit einer Wrapper-Klasse für die Session, hast du halbwegs schon mit HibernateFactory,
aber noch nicht genug, niemand sollte direkt auf Session.beginTransaction() usw. zugreifen,
wenn das auch über eine Methode HibernateFactory.beginTransaction() ginge, dann wäre das die einzige Stelle,
wo zu loggen wäre, natürlich auch noch bei commit() usw., mehrere Methoden

du hast übrigens, falls es einen Mehrfachzugriff gibt, nicht nur mit der Transaction Probleme, sondern auch mit dem close(),
die einen führen session.close() aus, während andere vielleicht noch damit arbeiten,

falls du das ganze überhaupt nicht darauf ausgelegt hast, wieso cacht HibernateFactory dann die Session, wieso gibt getSession() sie mehrfach zurück?
selbst wenn nicht, könnten vielleicht mehrere HibernateFactories mehrfach dasselbe SessionFactory.getCurrentSession(); zurückgeben,

alles ist per Logging zu klären, in diesem Fall könntest du auch überlegen, diese Session zu sperren,
z.B. mit dem einfachen (nicht allzu eleganten) Mittel, das Session-Objekt in irgendein statisches Set einzufügen,
dann können andere dort nachschauen ob die Session schon verwendet wird,
was in diesem Fall zu tun ist, ist natürlich eine andere Frage,

da eigentlich immer mit close() zu rechnen ist, braucht man auch gar nicht auf getCurrentSession() zu schauen, sondern sollte immer gleich eine neue eigene holen,
wie ich jetzt sehe machst du das beim Login in etwa? dann solltest du vor dem Logout die Session doch besser nicht schließen?
überdenke dein Gesamtkonzept

dass es 
 com.mmo.loginservice.beans.Session
gibt und die Hibernate-Session, macht es auch nicht leichter, sehe ich erst jetzt..


----------



## mavinatic (6. Jan 2012)

Hallo SlaterB,

ich danke dir für deine ausführliche Erklärung! Ich werde mir aufjeden fall Log4J Tutorial "reinziehen", ich denke wirklich das ist der einzige Schritt wie ich weiterkomme ;-)

Hier sind nun alle "Aktuellen Klassen":

HibernateFactory

```
package com.mmo.loginservice.utils;

import java.util.Properties;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;


public class HibernateFactory 
{
	private SessionFactory factory = null;
	private Session session = null;
	
	public HibernateFactory()
	{
		
	}
	
	public Session getSession()
	{
		session = factory.getCurrentSession();
		if(session==null)
		{
			session = factory.openSession();
		}
		
		return session;
	}
	
	public void closeSession(Session session)
	{
		if(session!=null)
		{
			session.close();
		}
	}
	
	public synchronized void saveObject(Object object)
	{
		Transaction tx = null;
		try
		{
			Session session = getSession();
			
			tx = session.beginTransaction();
			
			tx.begin();
			
			session.save(object);
			
			session.flush();
			
			tx.commit();
			
			session.close();
		} catch(Exception ex)
		{
			ex.printStackTrace();
		} finally
		{
			if(tx!=null)
			{
				tx.commit();
			}
		}
	}
	
	public synchronized void updateObject(Object object)
	{
		Transaction tx = null;
		try
		{
			Session session = getSession();
			tx = session.beginTransaction();
			
			tx.begin();
			
			session.update(object);
			
			session.flush();
			
			tx.commit();
			
			session.close();
		} catch(Exception ex)
		{
			ex.printStackTrace();
		} finally
		{
			if(tx!=null)
			{
				tx.commit();
			}
		}
		
	}
	
	public synchronized void deleteObject(Object object)
	{
		Transaction tx = null;
		try
		{
			Session session = getSession();
			tx = session.beginTransaction();
			tx.begin();
			session.delete(object);
			session.flush();
			tx.commit();
			session.close();
		} catch(Exception ex)
		{
			ex.printStackTrace();
		} finally
		{
			if(tx!=null)
			{
				tx.commit();
			}
		}
	}
	
	public void init()
	{
//		Configuration config = new Configuration();
//		Properties prop = new Properties();
//		prop.put("connection.driver_class", "org.apache.derby.jdbc.ClientDriver");
//		prop.put("connection.url", "jdbc:derby://localhost:1527/app;create=true");
//		prop.put("connection.username", "APP");
//		prop.put("connection.password", "APP");
//		prop.put("connection.pool_size", "5");
//		prop.put("hibernate.dialect", "org.hibernate.dialect.DerbyDialect");
//		prop.put("hibernate.current_session_context_class", "thread");
//		prop.put("hibernate.show_sql", "true");
//		prop.put("hibernate.hbm2ddl.auto", "update");
//		prop.put("hibernate.cache.region.factory_class", "net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory");
//		prop.put("hibernate.cache.use_second_level_cache", "true");
//		prop.put("hibernate.cache.use_query_cache", "true");
//		config.addProperties(prop);
//		
//		config.addAnnotatedClass(Account.class);
//		config.addAnnotatedClass(PlayerData.class);
//		config.addAnnotatedClass(com.mmo.loginservice.beans.Session.class);
		
		AnnotationConfiguration config = new AnnotationConfiguration().configure();
		factory = config.buildSessionFactory();
	}
}
```

DAOLayer

```
package com.mmo.loginservice.implementation;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Transaction;

import com.mmo.loginservice.beans.Account;
import com.mmo.loginservice.beans.PlayerData;
import com.mmo.loginservice.beans.Session;
import com.mmo.loginservice.interfaces.AccountDAO;
import com.mmo.loginservice.interfaces.PlayerDataDAO;
import com.mmo.loginservice.interfaces.SessionDAO;
import com.mmo.loginservice.utils.HibernateFactory;
import com.mmo.loginservice.utils.LoginServiceUtils;


public class DataAccessObjectLayer implements SessionDAO, AccountDAO, PlayerDataDAO
{
	private HibernateFactory factory = null;
	private LoginServiceUtils utils = new LoginServiceUtils();
	
	public DataAccessObjectLayer(HibernateFactory factory)
	{
		this.factory = factory;
	}
	
	@Override
	public Session createSession(String user) 
	{
		Session session = new Session();
		session.setSessionKey(utils.createUUID());
		session.setUser(user);
		
		factory.saveObject(session);
		
		return session;
	}

//	@Override
//	public SessionTO updateSession(SessionTO session) {
//		// TODO Auto-generated method stub
//		Session plainSession = (Session) session;
//		return null;
//	}

	@Override
	public void deleteSession(Session session) 
	{
		factory.deleteObject(session);
	}

	@Override
	public Session getSessionByUser(String user) 
	{
		Transaction tx = null;
		try
		{
			org.hibernate.Session hibernateSession = factory.getSession();
			tx = hibernateSession.beginTransaction();
			tx.begin();
			Query query = hibernateSession.createQuery("SELECT x FROM Session as x WHERE x.user='"+user+"'");
			List<Session> userSession = (List<Session>) query.list();
			tx.commit();
			factory.closeSession(hibernateSession);
			
			return (Session) userSession.get(0);
		} catch(Exception ex)
		{
			ex.printStackTrace();
		} finally
		{
			if(tx!=null)
			{
				tx.commit();	
			}
		}
		return null;
	}

	@Override
	public Session[] getSessions() 
	{
		Transaction tx = null;
		try
		{
			org.hibernate.Session hibernateSession = factory.getSession();
			tx = hibernateSession.beginTransaction();
			tx.begin();
			Query query = hibernateSession.createQuery("SELECT x FROM Session as x");
			List<Session> userSession = (List<Session>) query.list();
			tx.commit();
			factory.closeSession(hibernateSession);
			return (Session[]) userSession.toArray(new Session[userSession.size()]);
		} catch(Exception ex)
		{
			ex.printStackTrace();
		} finally
		{
			if(tx!=null)
			{
				tx.commit();
			}
		}
		return null;
	}

	@Override
	public Account createAccount(String username, String password)  
	{
		try
		{
			Account acc = new Account();
			acc.setPassword(password);
			acc.setUsername(username);
			acc.setOnline(false);
			SimpleDateFormat format = new SimpleDateFormat(utils.DATE_FORMAT);
			acc.setRegistred(format.format(new Date()));
			
			factory.saveObject(acc);
			
			return (Account) acc;
		} catch(Exception e)
		{
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public void deleteAccount(Account account) 
	{
		factory.deleteObject(account);
	}

	@Override
	public Account getAccountByUser(String user) 
	{
		Transaction tx = null;
		try
		{
			org.hibernate.Session session = factory.getSession();
			tx = session.beginTransaction();
			tx.begin();
			
			Query query = session.createQuery("SELECT x FROM Account as x WHERE x.username='"+user+"'");
			List<Account> list = query.list();
			
			tx.commit();
			
			factory.closeSession(session);
			if(list.size()>0)
			{
				return (Account) list.get(0);
			}
		} catch(Exception ex)
		{
			ex.printStackTrace();
		} finally
		{
			if(tx!=null)
			{
				tx.commit();
			}
		}
		return null;
	}

	@Override
	public Account[] getAccounts() 
	{
		Transaction tx = null;
		try
		{
			org.hibernate.Session session = factory.getSession();
			tx = session.beginTransaction();
			tx.begin();
			
			Query query = session.createQuery("SELECT x FROM Account as x");
			List<Account> list = query.list();
			
			tx.commit();
			factory.closeSession(session);
			return (Account[]) list.toArray(new Account[list.size()]);
		} catch(Exception ex)
		{
			ex.printStackTrace();
		} finally
		{
			if(tx!=null)
				tx.commit();
		}
		return null;
	}

	@Override
	public void updateAccount(Account account) {
		// TODO Auto-generated method stub
		factory.updateObject(account);
	}

	@Override
	public PlayerData createPlayerData(String name) 
	{
		PlayerData data = new PlayerData();
		data.setPlayerName(name);
		data.setPosx(new Integer(0));
		data.setPosx(new Integer(0));
		
		factory.saveObject(data);
		
		return (PlayerData) data;
	}

	@Override
	public PlayerData updatePlayerData(PlayerData data) 
	{
		factory.updateObject(data);
		return (PlayerData) data;
	}

	@Override
	public void deletePlayerData(PlayerData data) 
	{
		factory.deleteObject(data);
	}

	@Override
	public PlayerData getPlayerDataByName(String name) 
	{
		Transaction tx = null;
		try
		{
			org.hibernate.Session session = factory.getSession();
			tx = session.beginTransaction();
			tx.begin();
			Query query = session.createQuery("SELECT x FROM x as PlayerData x.playerName='"+name+"'");
			List<PlayerData> list = query.list();
			tx.commit();
			factory.closeSession(session);
			return (PlayerData) list.get(0); 
		} catch(Exception ex)
		{
			ex.printStackTrace();
		} finally
		{
			if(tx!=null)
				tx.commit();
		}
		return null;
	}

	@Override
	public PlayerData[] getPlayerData() 
	{
		Transaction tx = null;
		try
		{
			org.hibernate.Session session = factory.getSession();
			tx = session.beginTransaction();
			tx.begin();
			Query query = session.createQuery("SELECT x FROM x as PlayerData");
			List<PlayerData> list = query.list();
			tx.commit();
			factory.closeSession(session);
			return (PlayerData[]) list.toArray(new PlayerData[list.size()]);
		} catch(Exception ex)
		{
			ex.printStackTrace();
		} finally
		{
			if(tx!=null)
				tx.commit();
		}
		return null;
	}
}
```

AccountServiceImpl

```
package com.mmo.loginservice.implementation;

import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

import com.mmo.loginservice.beans.Account;
import com.mmo.loginservice.beans.Session;
import com.mmo.loginservice.exception.ServiceException;
import com.mmo.loginservice.interfaces.AccountService;
import com.mmo.loginservice.utils.LoginServiceUtils;

@WebService(endpointInterface="com.mmo.loginservice.interfaces.AccountService", targetNamespace="http://loginservice.mmo.com/", portName="AccountServicePort", serviceName="AccountService")
public class AccountServiceImpl implements AccountService 
{
	private DataAccessObjectLayer daoLayer = null;
	private LoginServiceUtils utils = new LoginServiceUtils();
	
	public AccountServiceImpl(DataAccessObjectLayer dao)
	{
		this.daoLayer = dao;
	}
	
	@Override
	public Session login(String username, String password) throws ServiceException 
	{
		// TODO: Implement login_Method
		if(username!=null && password!=null)
		{
			Account account = daoLayer.getAccountByUser(username);
			if(account!=null)
			{
				String hashPassword = utils.makeSHA1(password);
				if(account.getPassword().equalsIgnoreCase(hashPassword))
				{
					Session session = daoLayer.createSession(username);
					return session;
				} else
				{
					throw new ServiceException("AccountService@login - account password wrong");
				}
			} else
			{
				throw new ServiceException("AccountService@login - account fetchedBy daoLayer == null");
			}	
		} else
		{
			throw new ServiceException("AccountService@login - no parameters");
		}		
	}

	@Override
	public void logout(Session session) throws ServiceException 
	{
		// TODO: Implement logout_Method
		if(session!=null)
		{
			String sessionkey = session.getSessionKey();
			String user = session.getUser();
			
			if(user!=null && sessionkey!=null)
			{
				Account account = daoLayer.getAccountByUser(user);
				if(account!=null)
				{
					account.setOnline(false);
					daoLayer.updateAccount(account);
					
					daoLayer.deleteSession(session);
				} else
				{
					throw new ServiceException("AccountService@login - account fetchedBy daoLayer == null");
				}
			} else
			{
				throw new ServiceException("AccountService@logout - session object isnt null but no values");
			}
		} else
		{
			throw new ServiceException("AccountService@logout - no parameteres");
		}
	}

	@Override
	public void addAccount(String username, String password) throws ServiceException 
	{
		// TODO: Implement addAccount_Method
		if(username!=null && password!=null)
		{
			String hashedPassword = utils.makeSHA1(password);
			daoLayer.createAccount(username, hashedPassword);
		} else
		{
			throw new ServiceException("AccountService@addAccount - no parameters");
		}
	}

}
```


----------



## SlaterB (6. Jan 2012)

> Ich werde mir aufjeden fall Log4J Tutorial "reinziehen", ich denke wirklich das ist der einzige Schritt wie ich weiterkomme

Logging heißt System.out.println(),
alles andere ist vielleicht schöner, kocht aber auch nur mit Wasser


----------



## mavinatic (6. Jan 2012)

Das hier ist mein Stacktrace!


```
DEBUG - invoke HibernateFactory.saveObject()
DEBUG - invoke getSession()
DEBUG - Opened session at timestamp: 13258538086
DEBUG - BeginTransaction@saveObject()
DEBUG - begin
DEBUG - Obtaining JDBC connection
DEBUG - Obtained JDBC connection
DEBUG - initial autocommit status: false
org.hibernate.TransactionException: nested transactions not supported
	at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:152)
	at com.mmo.loginservice.utils.HibernateFactory.saveObject(HibernateFactory.java:56)
	at com.mmo.loginservice.implementation.DataAccessObjectLayer.createAccount(DataAccessObjectLayer.java:128)
	at com.mmo.loginservice.implementation.AccountServiceImpl.addAccount(AccountServiceImpl.java:91)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at com.sun.xml.internal.ws.api.server.InstanceResolver$1.invoke(InstanceResolver.java:235)
	at com.sun.xml.internal.ws.server.InvokerTube$2.invoke(InvokerTube.java:135)
	at com.sun.xml.internal.ws.server.sei.EndpointMethodHandler.invoke(EndpointMethodHandler.java:246)
	at com.sun.xml.internal.ws.server.sei.SEIInvokerTube.processRequest(SEIInvokerTube.java:82)
	at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Fiber.java:587)
	at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Fiber.java:546)
	at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Fiber.java:531)
	at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Fiber.java:428)
	at com.sun.xml.internal.ws.server.WSEndpointImpl$2.process(WSEndpointImpl.java:232)
	at com.sun.xml.internal.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:460)
	at com.sun.xml.internal.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:233)
	at com.sun.xml.internal.ws.transport.http.server.WSHttpHandler.handleExchange(WSHttpHandler.java:95)
	at com.sun.xml.internal.ws.transport.http.server.WSHttpHandler.handle(WSHttpHandler.java:80)
	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:65)
	at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:65)
	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:68)
	at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:555)
	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:65)
	at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:527)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)
ERROR - HibernateFactory.saveObject() - Error occured: nested transactions not supported
DEBUG - committing
DEBUG - committed JDBC Connection
DEBUG - Releasing JDBC connection
DEBUG - Released JDBC connection
```


----------



## SlaterB (6. Jan 2012)

kommt die Exception beim aller ersten Zugriff?
hast du je getestet ob das überhaupt funktioniert?

fange mit einfachen Programmen an, eine main-Methode, eine SessionFactory, eine Session, ein Zugriff usw.,
funktioniert das oder nicht?

wenn ja, dann müsste dieser erste eine Zugriff ohne störenden Rest ja auch in dem anderen Programm funktionieren,
teste nach und nach wo der Unterschied ist, ob @WebService oder sonstige eingebaute Spielereien was damit zu tun haben,

vielleicht der Schritt mit Login und Zugriff auf die Session erst in späteren WebService-Aufruf,
falls es so ist, was passiert wenn alles zusammen ausgeführt wird?

wenn also irgendwie irgendwo von einem funktionieren Beispiel ausgegangen wird, kann nicht einfach so ein Fehler dazukommen,
an sich einfache Logik oder?
an deiner Ausgabe ist nicht nachvollziehbar wie sich das gesamte Restprogramm verhält, vielleicht sind irgendwo Zugriffe die du noch nicht loggst,
daher vom fast leeren Programm ausgehen, da kann das nicht passieren und dann nach und nach etwas hinzunehmen,
wann passiert der Fehler, was sind die neuen Codebestandteile, werden sie aufgerufen und nicht geloggt?

ist der Fehler eigentlich reproduzierbar oder zufallsabhängig?

usw., alles überschaubare Schritte, arbeiten arbeiten arbeiten


----------



## mavinatic (6. Jan 2012)

Hey SlaterB,

wie ich merke bist du ein "Erfahrender", da ich noch Azubi und somit anfänger bin, ist es für mich nicht so selbstverständlich wie du es sagst.

Ich habe das Programm debugged und das alles passiert genauso, als würde ich nur ein Objekt persistieren würde.

Im 1. Zugriff auf die DB kommt schon die nestedTransaction Exception, daher ist für mich das alles nicht nachvollziehbar! Ich habe es auch getestet ob es funktioniert, denn dies ist nur eine erweiterte Version von meinem Programm.
Es wundert mich auch, da alles schon geklappt hat und nur jetzt nicht mehr!

Ich habe direkt in die MainClass probiert ein Objekt zu speichern:

```
package com.mmo.loginservice.main;

import javax.xml.ws.Endpoint;

import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.SimpleLayout;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.mmo.loginservice.beans.Account;
import com.mmo.loginservice.implementation.AccountServiceImpl;
import com.mmo.loginservice.implementation.DataAccessObjectLayer;
import com.mmo.loginservice.implementation.GameDataServiceImpl;
import com.mmo.loginservice.utils.HibernateFactory;

public class Main 
{
	private static final Logger logger = Logger.getRootLogger();
	
	public Main()
	{
		initLogger();
		String addressAccount = "http://localhost:8080/accountService";
		String addressGameData = "http://localhost:8080/gameDataService";
		
		logger.info("init HibernateFactory");
		HibernateFactory factory = new HibernateFactory();
		factory.init();
	
		Account acc = new Account();
		acc.setOnline(true);
		acc.setPassword("s");
		acc.setRegistred("123");
		acc.setUsername("HELP");
		logger.debug("Acc Obj erstellt");
		
		Session session = factory.getSession();
		logger.debug("session erstellt/bekommne");
		Transaction tx = session.beginTransaction();
		logger.debug("BeginTransactionNOW");
		tx.begin();
		logger.debug("running");
		session.save(acc);
		logger.debug("SAVED");
		tx.commit();
		logger.debug("COMIT");
		session.close();
		logger.debug("Session closed");
		
		logger.info("init LoginService");
		DataAccessObjectLayer layer = new DataAccessObjectLayer(factory);
		logger.info("init DAOLayer");
				
		Endpoint.publish(addressAccount, new AccountServiceImpl(layer));
		logger.info("AccountService published @ "+addressAccount);
		Endpoint.publish(addressGameData, new GameDataServiceImpl(layer));
		logger.info("GameDataService published @ "+addressGameData);
	}
	
	private void initLogger()
	{
		PatternLayout layout = new PatternLayout();
		layout.setConversionPattern("<%d{yyyy-MM-dd HH:mm:ss}> %-5p : %c{5} : %m%n");
		ConsoleAppender app = new ConsoleAppender(layout);
		logger.addAppender(app);
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new Main();
	}

}
```

Mit folgendem Ergebnis:

```
<2012-01-06 14:10:31> DEBUG : root : Acc Obj erstellt
<2012-01-06 14:10:31> DEBUG : com.mmo.loginservice.utils.HibernateFactory : invoke getSession()
<2012-01-06 14:10:31> DEBUG : org.hibernate.internal.SessionImpl : Opened session at timestamp: 13258554312
<2012-01-06 14:10:31> DEBUG : root : session erstellt/bekommne
<2012-01-06 14:10:31> DEBUG : hibernate.engine.transaction.spi.AbstractTransactionImpl : begin
<2012-01-06 14:10:31> DEBUG : hibernate.engine.jdbc.internal.LogicalConnectionImpl : Obtaining JDBC connection
<2012-01-06 14:10:31> DEBUG : hibernate.engine.jdbc.internal.LogicalConnectionImpl : Obtained JDBC connection
<2012-01-06 14:10:31> DEBUG : engine.transaction.internal.jdbc.JdbcTransaction : initial autocommit status: false
<2012-01-06 14:10:31> DEBUG : root : BeginTransactionNOW
Exception in thread "main" org.hibernate.TransactionException: nested transactions not supported
	at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:152)
	at com.mmo.loginservice.main.Main.<init>(Main.java:43)
	at com.mmo.loginservice.main.Main.main(Main.java:72)
```

Es ist 1 Objekt, 1 Transaction und diese fällt auf die Nase? Kann doch nicht sein? Es gibt nur eine Stelle wo ich eine Transaction beginne!


----------



## SlaterB (6. Jan 2012)

nun gut, jetzt ist es auch für mich sichtbar:


```
Transaction tx = session.beginTransaction(); // erstellt die Transaction und beginnt sie auch
        logger.debug("BeginTransactionNOW");
        tx.begin(); // beginnt sie ein zweites Mal..
```


----------



## mavinatic (6. Jan 2012)

Okay, ich habe das gefixed!

Nun habe ich dennoch das Problem, dass folgende Exception auftaucht und deshalb habe ich überall das Session.flush(); entfernt!


```
<2012-01-06 14:35:58> DEBUG : com.mmo.loginservice.utils.HibernateFactory : Transaction comit@saveObject()
org.hibernate.SessionException: Session was already closed
	at org.hibernate.internal.SessionImpl.close(SessionImpl.java:266)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:350)
	at $Proxy58.close(Unknown Source)
	at com.mmo.loginservice.utils.HibernateFactory.saveObject(HibernateFactory.java:61)
	at com.mmo.loginservice.implementation.DataAccessObjectLayer.createAccount(DataAccessObjectLayer.java:126)
	at com.mmo.loginservice.implementation.AccountServiceImpl.addAccount(AccountServiceImpl.java:91)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at com.sun.xml.internal.ws.api.server.InstanceResolver$1.invoke(InstanceResolver.java:235)
	at com.sun.xml.internal.ws.server.InvokerTube$2.invoke(InvokerTube.java:135)
	at com.sun.xml.internal.ws.server.sei.EndpointMethodHandler.invoke(EndpointMethodHandler.java:246)
	at com.sun.xml.internal.ws.server.sei.SEIInvokerTube.processRequest(SEIInvokerTube.java:82)
	at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Fiber.java:587)
	at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Fiber.java:546)
	at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Fiber.java:531)
	at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Fiber.java:428)
	at com.sun.xml.internal.ws.server.WSEndpointImpl$2.process(WSEndpointImpl.java:232)
	at com.sun.xml.internal.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:460)
	at com.sun.xml.internal.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:233)
	at com.sun.xml.internal.ws.transport.http.server.WSHttpHandler.handleExchange(WSHttpHandler.java:95)
	at com.sun.xml.internal.ws.transport.http.server.WSHttpHandler.handle(WSHttpHandler.java:80)<2012-01-06 14:35:58> ERROR : com.mmo.loginservice.utils.HibernateFactory : HibernateFactory.saveObject() - Error occured: Session was already closed

	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:65)
	at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:65)
	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:68)
	at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:555)
	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:65)
	at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:527)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)
org.hibernate.TransactionException: Transaction not successfully started
	at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:170)
	at com.mmo.loginservice.utils.HibernateFactory.saveObject(HibernateFactory.java:70)
	at com.mmo.loginservice.implementation.DataAccessObjectLayer.createAccount(DataAccessObjectLayer.java:126)
	at com.mmo.loginservice.implementation.AccountServiceImpl.addAccount(AccountServiceImpl.java:91)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at com.sun.xml.internal.ws.api.server.InstanceResolver$1.invoke(InstanceResolver.java:235)
	at com.sun.xml.internal.ws.server.InvokerTube$2.invoke(InvokerTube.java:135)
	at com.sun.xml.internal.ws.server.sei.EndpointMethodHandler.invoke(EndpointMethodHandler.java:246)
	at com.sun.xml.internal.ws.server.sei.SEIInvokerTube.processRequest(SEIInvokerTube.java:82)
	at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Fiber.java:587)
	at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Fiber.java:546)
	at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Fiber.java:531)
	at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Fiber.java:428)
	at com.sun.xml.internal.ws.server.WSEndpointImpl$2.process(WSEndpointImpl.java:232)
	at com.sun.xml.internal.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:460)
	at com.sun.xml.internal.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:233)
	at com.sun.xml.internal.ws.transport.http.server.WSHttpHandler.handleExchange(WSHttpHandler.java:95)
	at com.sun.xml.internal.ws.transport.http.server.WSHttpHandler.handle(WSHttpHandler.java:80)
	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:65)
	at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:65)
	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:68)
	at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:555)
	at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:65)
	at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:527)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)
```


Ich habe das Commit entfernt und nur im finally Block gemacht :-/ dennoch nicht


----------



## SlaterB (6. Jan 2012)

das klingt nicht nach der Klasse Main, wieso entfernst du dich von der wieder?
ohne die Klasse Main ist alles wie gesagt undurchsichtig,

einen Punkt hatte ich ja früher schon angesprochen, vielleicht reicht der: 
close() nur beim Logout, solange brauchst du die Session noch, 
falls zwischendurch schon close(), dann wäre bei weiteren Aufrufen die Exception kein Wunder


----------



## mavinatic (6. Jan 2012)

hm...das "Problem" ist, dass dieses HibernateFactory-Objekt für ALLE eingehenden Verbindungen zur Verfügung steht, deswegen kann ich nicht login -> Verbindung startet und logout -> Verbindung endet.

Ich habe absolut kienen Plan, wie ich das Session & Transactionsmanagement gestalten soll. Vielleicht jemand einen Tipp.


----------



## SlaterB (6. Jan 2012)

Tipp:
entferne alles was wie close() aussieht -> Programm läuft


----------

