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:
AccountServiceImpl - Hier sind alle Methoden des Webservice gelistet:
DAOLayer - Kapselung von CRUD Methoden in einer eigenen Klasse:
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!
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:
Java:
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:
Java:
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:
Java:
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!