Вопрос

I am using Spring transaction management with Hibernate. My service layer methods are transactional. This error is occurring when am testing a use case when user is trying to create a company with an already existing ID. Here is my controller:

@RequestMapping(value = "/CreateCompany", method = RequestMethod.POST)
public @ResponseBody
String createUser(HttpServletRequest request) {
    String response = null;
    try {

        response = getUserServiceTransaction().save(request);

    } catch (Exception e) {
        if (logger.isErrorEnabled()) {
            logger.error(
                    "ERROR: service URL /CreateCompany; " +
                    "method createUser(..)"+ 
                    e.getMessage());
        }
    }
    return response;
}

Service save method:

@Override public String save(HttpServletRequest request) throws ServiceException {

    String requestJson = null;
    try {
        requestJson = getUtils().fetchJsonRequestString(request);
        Company company = (Company) getUtils().fromJson(requestJson,
                Company.class);

        String companyId = company.getCompanyId();
        getCompanyDao().save(company);

        List<String> linkedCompanies = null;

        String parentCompanyId = company.getCompanyId();

        linkedCompanies = company.getLinkedCompanies();

        Iterator<String> iterator = linkedCompanies.iterator();

        while (iterator.hasNext()) {
            CompanyLinkage companyLinkage = new CompanyLinkage();
            companyLinkage.setParentCompanyId(parentCompanyId);
            companyLinkage.setChildCompanyId(iterator.next());
            getCompanyLinkageDao().save(companyLinkage);
        }

        requestJson = getUtils().toKendoResponse(true);
    }
    catch (Exception e) {
        logger.error("Error:" + e);
        requestJson = getUtils().toKendoResponse(false);
    }
    return requestJson;

}

My DAO:

public class CompanyDaoImpl extends HibernateDaoSupport implements CompanyDao{

@Override
public void save(Company company) throws DAOException {
    try{
        getHibernateTemplate().save(company);
        getHibernateTemplate().flush();
    }
    catch(Exception e){
        throw new DAOException(e);
    }

}

Transactional beans:

<!-- User Service  -->
<bean id="userService" class="com.ig.avs.adapters.db.service.UserService">
    <property name="companyDao" ref="companyDao"/>
    <property name="companyLinkageDao" ref="companyLinkageDao"/>
    <property name="utils" ref="utils" />
</bean>

<bean id="userServiceTransaction"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="txManager" />
<property name="target" ref="userService" />
<property name="transactionAttributes">

<props>
<prop key="save*">PROPAGATION_REQUIRED,-java.lang.Exception</prop>
<prop key="update*">PROPAGATION_REQUIRED,-java.lang.Exception</prop>
<prop key="delete*">PROPAGATION_REQUIRED,-java.lang.Exception</prop>
<prop key="get*">PROPAGATION_SUPPORTS,readOnly , -java.lang.Exception</prop>
<prop key="find*">PROPAGATION_SUPPORTS,readOnly ,-java.lang.Exception</prop>
<prop key="list*">PROPAGATION_SUPPORTS, readOnly ,-java.lang.Exception</prop>
</props>

In my JSP am checking that if my response is d:false ( which I am creating in getUtils().toKendoResponse(false) ) then I display an alert to the user "There is some issue in registration"

However once the error comes during save in the service layer (duplicate key error) , the code reaches the end of the service. After that another error occurs in the controller:

ERROR CompanyController:47 - ERROR: service URL /CreateCompany; method createUser(..)null id in com.ig.avs.common.entity.db.Company entry (don't flush the Session after an exception occurs)

And the controller returns 'response' as null.

I have tried removing the flush I am doing in my dao layer but it didnt help. I have looked at other answers on the site regarding this but in most of them people were not returning back after an error. I am catching my exception and returning from my service so not sure where another flush is occurring.

Any input at all would be a great help!

Это было полезно?

Решение

You are using Spring for transaction management (in a very old-skool way), after the end of your service method the transaction is committed and the session flushed. So instead of catching the exception in your service, catch it in your controller.

A couple of other things

  1. Don't use HibernateDaoSupport or HibernateTemplate those should be considered deprecated as of hibernate 3.0.1 (around 2006), simply use the SessionFactory directly.
  2. Don't use TransactionProxyFactoryBean simply annotate your service with @Transactional and use <tx:annotation-driven /> this will save you a lot of headaches
  3. Why aren't you utilizing Spring to map to/from JSON but are doing it yoruself in the service layer, which is now directly tied to your web layer
  4. Judging by your service method and the dao calls you are also having problems in the mapping of your entities. Why are you manually setting the links, hibernate can take care of that in such a way that you only need to store the Company.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top