Announcement Announcement Module
Collapse
No announcement yet.
Declarative Transaction support Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Declarative Transaction support

    Hello, I've been writing a Struts web application that uses Spring declarative transaction support and OJB as the ORM tool.

    All of my services in my application are using the PROPAGATION_REQUIRED keyword for the transaction manager. A Struts action may call one or more services to complete it's work.

    I've run into some database locking issues and after logging SQL Statements using the p6spy driver, I've found that when I do 3 web requests, I get 8 database transactions. I would have thought that each web request would have a single database transaction.

    I thought the first service within a web request would see that there was no transaction and it would start one, then other services within the same request would see that a transaction has started and participate in it, rather than starting a new one.

    Do I understand this wrong? Any information would be appreciated.

    Thanks
    Jay

  • #2
    Jay,

    How the transactions are partitioned depends on what class you have proxied and how you have implemented your DAOs. The first thing to check when having transaction problems is that the proxy is assembled correctly and that you are actually using the proxy and not the proxy target. In code you can verify that you are using the a proxy with AopUtils.isAopProxy().

    Can you post your ApplicationContext XML along with any business interfaces, that should give me enough to go on

    Rob

    Comment


    • #3
      My application context file and the actionservlet files are huge. I'll just send pieces. If you need the whole thing, I can post them, but they are pretty big.

      Here is an update. I met with our dbas and they tell me that sql that I thought would be in the same connection are happening on different connections - therefore they can't share the same transaction and this is causing the problem. If they would all happen on the same connection, we would be in business.

      Here is the section in my actionServlet for the action that calls the service.

      <bean name="/formatprepare" class="edu.iu.uis.pdp.action.format.FormatPrepareA ction" singleton="false">
      <property name="webAuthenticationService"><ref bean="pdpWebAuthenticationService"/></property>
      <property name="userService"><ref bean="pdpUserService"/></property>
      <property name="applicationSettingService"><ref bean="pdpApplicationSettingService"/></property>
      <property name="formatService"><ref bean="pdpFormatService"/></property>
      <property name="securityService"><ref bean="pdpSecurityService"/></property>
      </bean>

      All of the database work in this case is called in the formatService. Here is the declaration for it in the applicationContext file:
      <bean id="pdpFormatServiceImpl" class="edu.iu.uis.pdp.service.impl.FormatServiceIm pl">
      <property name="physicalCampusDao"><ref local="pdpPhysicalCampusDao"/></property>
      <property name="customerProfileDao"><ref local="pdpCustomerProfileDao"/></property>
      <property name="disbursementNumberRangeDao"><ref local="pdpDisbursementNumberRangeDao"/></property>
      <property name="formatProcessDao"><ref local="pdpFormatProcessDao"/></property>
      <property name="paymentDetailDao"><ref local="pdpPaymentDetailDao"/></property>
      <property name="processDao"><ref local="pdpProcessDao"/></property>
      <property name="achService"><ref local="pdpAchService"/></property>
      <property name="referenceService"><ref local="pdpReferenceService"/></property>
      <property name="glTransactionService"><ref local="pdpGlTransactionService"/></property>
      <property name="applicationSettingService"><ref local="pdpApplicationSettingService"/></property>
      <property name="formatPaymentDao"><ref local="pdpFormatPaymentDao"/></property>
      </bean>

      <bean id="pdpFormatService" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
      <property name="transactionManager"><ref bean="TransactionManager"/></property>
      <property name="target"><ref bean="pdpFormatServiceImpl"/></property>
      <property name="transactionAttributes">
      <props>
      <prop key="*">PROPAGATION_REQUIRED,-edu.iu.uis.pdp.service.DisbursementRangeExhaustedE xception,-edu.iu.uis.pdp.service.MissingDisbursementRangeExc eption</prop>
      </props>
      </property>
      </bean>

      Here are the dependant parts:


      <bean id="pdpFormatProcessDao" class="edu.iu.uis.pdp.dao.ojb.FormatProcessDaoOjb"/>

      <bean id="pdpPhysicalCampusDao" class="edu.iu.uis.pdp.dao.ojb.PhysicalCampusDaoOjb "/>

      <bean id="pdpProcessDao" class="edu.iu.uis.pdp.dao.ojb.ProcessDaoOjb">
      <property name="userService"><ref bean="pdpUserService"/></property>
      </bean>

      <bean id="pdpFormatPaymentDao" class="edu.iu.uis.pdp.dao.jdbc.FormatPaymentDaoJdb c">
      <property name="dataSource"><ref bean="dataSource"/></property>
      </bean>

      <bean id="pdpPaymentFileLoadDao" class="edu.iu.uis.pdp.dao.ojb.PaymentFileLoadDaoOj b">
      <property name="referenceDao"><ref local="pdpReferenceDao"/></property>
      </bean>

      <bean id="pdpDisbursementNumberRangeDao" class="edu.iu.uis.pdp.dao.ojb.DisbursementNumberRa ngeDaoOjb">
      <property name="userService"><ref bean="pdpUserService"/></property>
      </bean>

      <bean id="pdpReferenceDao" class="edu.iu.uis.pdp.dao.ojb.ReferenceDaoOjb">
      <property name="userService"><ref bean="pdpUserService"/></property>
      </bean>

      <bean id="pdpGlPendingTransactionDao" class="edu.iu.uis.pdp.dao.ojb.GlPendingTransaction DaoOjb"/>

      <bean id="pdpApplicationSettingDao" class="edu.iu.uis.pdp.dao.ojb.ApplicationSettingDa oOjb"/>

      <bean id="pdpCustomerProfileDao" class="edu.iu.uis.pdp.dao.ojb.CustomerProfileDaoOj b">
      <property name="userService"><ref bean="pdpUserService"/></property>
      </bean>

      <bean id="pdpBankDao" class="edu.iu.uis.pdp.dao.ojb.BankDaoOjb">
      <property name="userService"><ref bean="pdpUserService"/></property>
      </bean>

      <bean id="pdpPaymentDetailDao" class="edu.iu.uis.pdp.dao.ojb.PaymentDetailDaoOjb" >
      <property name="userService"><ref bean="pdpUserService"/></property>
      <property name="referenceService"><ref local="pdpReferenceService"/></property>
      </bean>

      <bean id="pdpPaymentDetailHistoryDao" class="edu.iu.uis.pdp.dao.ojb.PaymentDetailHistory DaoOjb">
      <property name="userService"><ref bean="pdpUserService"/></property>
      </bean>

      <bean id="pdpAchAccountNumberDao" class="edu.iu.uis.pdp.dao.ojb.AchAccountNumberDaoO jb"/>

      <bean id="pdpPaymentDetailSearchDao" class="edu.iu.uis.pdp.dao.ojb.PaymentDetailSearchD aoOjb">
      <property name="userService"><ref bean="pdpUserService"/></property>
      </bean>

      Here is the FormatService interface:

      public interface FormatService {
      // Look up information about the user's campus
      public PhysicalCampus getPhysicalCampus(String campusCd);

      // Get the customer profiles to list on the screen
      public List getAllCustomerProfiles();

      // Get disbursement numbers to list on the screen
      public List getAllDisbursementNumberRanges();

      // Find out if the format is already running somewhere
      public Date getFormatProcessStartDate(String campus);

      // Mark the process log so a format only happens once per campus. Mark all the
      // payments that will be formatted and return a summary. attachments will be Y, N or null for both.
      public List startFormatProcess(User user, String campus, List customers, Date paydate, boolean immediate,
      String attachments);

      // Mark the process as ended.
      public void endFormatProcess(String campus);

      // Actually format the data for check printing.
      public void performFormat(Integer procId) throws DisbursementRangeExhaustedException,MissingDisburs ementRangeException;

      // If the start format process was run and the user doesn't want to continue,
      // this needs to be run to set all payments back to open
      public void clearUnfinishedFormat(Integer procId);

      // Get a list of FormatResults for a format
      public List getFormatSummary(Integer procId);
      }


      The action calls startFormatProcess from the FormatService implement and all of the database work is done within that method.

      If you need more info, let me know.

      Thanks
      Jay

      Comment


      • #4
        Jay,

        Are you using Spring's OJB support classes? I can't see where you are configuring the persistence broker template and the data source for your OJB daos.

        Rob

        Comment


        • #5
          Yes, we are using the Spring OJB support classes. We also have a few DAOs that are using the JDBC support classes.

          Here is the complete applicationContext.xml file. The OJB setup is done at the bottom.

          Thanks
          Jay


          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

          <beans>
          <!-- service tier -->
          <bean id="pdpWebAuthenticationService" class="edu.iu.uis.services.authn.impl.WebAuthentic ationServiceCas"/>

          <bean id="pdpUserService" class="edu.iu.uis.services.user.impl.UserCacheServ ice">
          <property name="cachedService"><ref bean="pdpUserServiceImpl"/></property>
          <property name="eternal"><value>false</value></property>
          <property name="maximumSize"><value>100</value></property>
          <property name="spoolable"><value>false</value></property>
          <property name="timeToIdle"><value>3600</value></property>
          <property name="timeToLive"><value>3600</value></property>
          </bean>

          <bean id="pdpUserServiceImpl" class="edu.iu.uis.services.user.impl.UserServiceGd s">
          <property name="securityFile"><value>GDS.properties</value></property>
          <property name="settingsFile"><value>GDS.properties</value></property>
          </bean>

          <bean id="pdpGroupService" class="edu.iu.uis.services.group.impl.GroupService Ads">
          <property name="securityFile"><value>ADS.properties</value></property>
          </bean>

          <bean id="pdpPaymentFileServiceImpl" class="edu.iu.uis.pdp.service.impl.PaymentFileServ iceImpl">
          <property name="customerProfileService"><ref bean="pdpCustomerProfileService"/></property>
          <property name="applicationSettingService"><ref bean="pdpApplicationSettingService"/></property>
          <property name="mailService"><ref bean="pdpMailService"/></property>
          </bean>

          <bean id="pdpSecurityService" class="edu.iu.uis.pdp.service.impl.PdpSecurityServ iceImpl">
          </bean>

          <bean id="pdpPaymentFileService" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
          <property name="transactionManager"><ref bean="TransactionManager"/></property>
          <property name="target"><ref bean="pdpPaymentFileServiceImpl"/></property>
          <property name="transactionAttributes">
          <props>
          <prop key="*">PROPAGATION_REQUIRED,-edu.iu.uis.pdp.exception.PaymentLoadException</prop>
          </props>
          </property>
          </bean>

          <bean id="pdpApplicationSettingServiceImpl" class="edu.iu.uis.services.setting.impl.Applicatio nSettingServiceImpl">
          <property name="applicationSettingDao"><ref local="pdpApplicationSettingDao"/></property>
          </bean>

          <bean id="pdpApplicationSettingService" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
          <property name="transactionManager"><ref bean="TransactionManager"/></property>
          <property name="target"><ref bean="pdpApplicationSettingServiceImpl"/></property>
          <property name="transactionAttributes">
          <props>
          <prop key="*">PROPAGATION_REQUIRED</prop>
          </props>
          </property>
          </bean>

          <bean id="pdpReferenceServiceImpl" class="edu.iu.uis.pdp.service.impl.ReferenceServic eImpl">
          <property name="referenceDao"><ref local="pdpReferenceDao"/></property>
          </bean>

          <bean id="pdpReferenceService" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
          <property name="transactionManager"><ref bean="TransactionManager"/></property>
          <property name="target"><ref bean="pdpReferenceServiceImpl"/></property>
          <property name="transactionAttributes">
          <props>
          <prop key="*">PROPAGATION_REQUIRED</prop>
          </props>
          </property>
          </bean>

          <bean id="pdpCustomerProfileServiceImpl" class="edu.iu.uis.pdp.service.impl.CustomerProfile ServiceImpl">
          <property name="customerProfileDao"><ref local="pdpCustomerProfileDao"/></property>
          </bean>

          <bean id="pdpCustomerProfileService" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
          <property name="transactionManager"><ref bean="TransactionManager"/></property>
          <property name="target"><ref bean="pdpCustomerProfileServiceImpl"/></property>
          <property name="transactionAttributes">
          <props>
          <prop key="*">PROPAGATION_REQUIRED</prop>
          </props>
          </property>
          </bean>

          <bean id="pdpDisbursementNumberRangeServiceImpl" class="edu.iu.uis.pdp.service.impl.DisbursementNum berRangeServiceImpl">
          <property name="disbursementNumberRangeDao"><ref local="pdpDisbursementNumberRangeDao"/></property>
          </bean>

          <bean id="pdpDisbursementNumberRangeService" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
          <property name="transactionManager"><ref bean="TransactionManager"/></property>
          <property name="target"><ref bean="pdpDisbursementNumberRangeServiceImpl"/></property>
          <property name="transactionAttributes">
          <props>
          <prop key="*">PROPAGATION_REQUIRED</prop>
          </props>
          </property>
          </bean>

          <bean id="pdpBankServiceImpl" class="edu.iu.uis.pdp.service.impl.BankServiceImpl ">
          <property name="bankDao"><ref local="pdpBankDao"/></property>
          </bean>

          <bean id="pdpBankService" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
          <property name="transactionManager"><ref bean="TransactionManager"/></property>
          <property name="target"><ref bean="pdpBankServiceImpl"/></property>
          <property name="transactionAttributes">
          <props>
          <prop key="*">PROPAGATION_REQUIRED</prop>
          </props>
          </property>
          </bean>

          <bean id="pdpFormatServiceImpl" class="edu.iu.uis.pdp.service.impl.FormatServiceIm pl">
          <property name="physicalCampusDao"><ref local="pdpPhysicalCampusDao"/></property>
          <property name="customerProfileDao"><ref local="pdpCustomerProfileDao"/></property>
          <property name="disbursementNumberRangeDao"><ref local="pdpDisbursementNumberRangeDao"/></property>
          <property name="formatProcessDao"><ref local="pdpFormatProcessDao"/></property>
          <property name="paymentDetailDao"><ref local="pdpPaymentDetailDao"/></property>
          <property name="processDao"><ref local="pdpProcessDao"/></property>
          <property name="achService"><ref local="pdpAchService"/></property>
          <property name="referenceService"><ref local="pdpReferenceService"/></property>
          <property name="glTransactionService"><ref local="pdpGlTransactionService"/></property>
          <property name="applicationSettingService"><ref local="pdpApplicationSettingService"/></property>
          <property name="formatPaymentDao"><ref local="pdpFormatPaymentDao"/></property>
          </bean>

          <bean id="pdpFormatService" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
          <property name="transactionManager"><ref bean="TransactionManager"/></property>
          <property name="target"><ref bean="pdpFormatServiceImpl"/></property>
          <property name="transactionAttributes">
          <props>
          <prop key="*">PROPAGATION_REQUIRED,-edu.iu.uis.pdp.service.DisbursementRangeExhaustedE xception,-edu.iu.uis.pdp.service.MissingDisbursementRangeExc eption</prop>
          </props>
          </property>
          </bean>

          <bean id="pdpPaymentDetailServiceImpl" class="edu.iu.uis.pdp.service.impl.PaymentDetailSe rviceImpl">
          <property name="paymentDetailDao"><ref local="pdpPaymentDetailDao"/></property>
          </bean>

          <bean id="pdpPaymentDetailService" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
          <property name="transactionManager"><ref bean="TransactionManager"/></property>
          <property name="target"><ref bean="pdpPaymentDetailServiceImpl"/></property>
          <property name="transactionAttributes">
          <props>
          <prop key="*">PROPAGATION_REQUIRED</prop>
          </props>
          </property>
          </bean>

          <bean id="pdpPaymentDetailSearchServiceImpl" class="edu.iu.uis.pdp.service.impl.PaymentDetailSe archServiceImpl">
          <property name="paymentDetailSearchDao"><ref local="pdpPaymentDetailSearchDao"/></property>
          <property name="applicationSettingService"><ref bean="pdpApplicationSettingService"/></property>
          </bean>

          <bean id="pdpPaymentDetailSearchService" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
          <property name="transactionManager"><ref bean="TransactionManager"/></property>
          <property name="target"><ref bean="pdpPaymentDetailSearchServiceImpl"/></property>
          <property name="transactionAttributes">
          <props>
          <prop key="*">PROPAGATION_REQUIRED</prop>
          </props>
          </property>
          </bean>

          <bean id="pdpGlTransactionServiceImpl" class="edu.iu.uis.pdp.service.impl.GlTransactionSe rviceImpl">
          <property name="glPendingTransactionDao"><ref local="pdpGlPendingTransactionDao"/></property>
          <property name="fisService"><ref bean="pdpFisService"/></property>
          </bean>

          <bean id="pdpGlTransactionService" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
          <property name="transactionManager"><ref bean="TransactionManager"/></property>
          <property name="target"><ref bean="pdpGlTransactionServiceImpl"/></property>
          <property name="transactionAttributes">
          <props>
          <prop key="*">PROPAGATION_REQUIRED</prop>
          </props>
          </property>
          </bean>

          <bean id="pdpAchServiceImpl" class="edu.iu.uis.pdp.service.impl.AchServiceJdbc" >
          <property name="dataSource"><ref bean="dataSource"/></property>
          </bean>

          <bean id="pdpAchService" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
          <property name="transactionManager"><ref bean="TransactionManager"/></property>
          <property name="target"><ref bean="pdpAchServiceImpl"/></property>
          <property name="transactionAttributes">
          <props>
          <prop key="*">PROPAGATION_REQUIRED</prop>
          </props>
          </property>
          </bean>

          <bean id="pdpFisServiceImpl" class="edu.iu.uis.services.fis.impl.FisServiceImpl ">
          <property name="dataSource"><ref bean="dataSource"/></property>
          </bean>

          <bean id="pdpFisService" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
          <property name="transactionManager"><ref bean="TransactionManager"/></property>
          <property name="target"><ref bean="pdpFisServiceImpl"/></property>
          <property name="transactionAttributes">
          <props>
          <prop key="*">PROPAGATION_REQUIRED</prop>
          </props>
          </property>
          </bean>

          <bean id="pdpPaymentMaintenanceServiceImpl" class="edu.iu.uis.pdp.service.impl.PaymentMaintena nceServiceImpl">
          <property name="paymentDetailDao"><ref bean="pdpPaymentDetailDao"/></property>
          <property name="paymentDetailService"><ref bean="pdpPaymentDetailService"/></property>
          <property name="achAccountNumberDao"><ref bean="pdpAchAccountNumberDao"/></property>
          <property name="paymentDetailHistoryDao"><ref bean="pdpPaymentDetailHistoryDao"/></property>
          <property name="referenceService"><ref local="pdpReferenceService"/></property>
          <property name="glTransactionService"><ref local="pdpGlTransactionService"/></property>
          </bean>

          <bean id="pdpPaymentMaintenanceService" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
          <property name="transactionManager"><ref bean="TransactionManager"/></property>
          <property name="target"><ref bean="pdpPaymentMaintenanceServiceImpl"/></property>
          <property name="transactionAttributes">
          <props>
          <prop key="*">PROPAGATION_REQUIRED</prop>
          </props>
          </property>
          </bean>

          <bean id="pdpMailService" class="edu.iu.uis.services.mail.impl.MailServiceIm pl">
          <property name="fromAddress"><value>email</value></property>
          <property name="securityFile"><value>ADS.properties</value></property>
          </bean>

          <!-- data tier -->
          <bean id="pdpPaymentFileParser" class="edu.iu.uis.pdp.xml.impl.PaymentFileParserIm pl" singleton="false">
          <property name="xsdUrl"><value>payment1.xsd</value></property>
          </bean>

          <bean id="pdpFormatProcessDao" class="edu.iu.uis.pdp.dao.ojb.FormatProcessDaoOjb"/>

          <bean id="pdpPhysicalCampusDao" class="edu.iu.uis.pdp.dao.ojb.PhysicalCampusDaoOjb "/>

          <bean id="pdpProcessDao" class="edu.iu.uis.pdp.dao.ojb.ProcessDaoOjb">
          <property name="userService"><ref bean="pdpUserService"/></property>
          </bean>

          <bean id="pdpFormatPaymentDao" class="edu.iu.uis.pdp.dao.jdbc.FormatPaymentDaoJdb c">
          <property name="dataSource"><ref bean="dataSource"/></property>
          </bean>

          <bean id="pdpPaymentFileLoadDao" class="edu.iu.uis.pdp.dao.ojb.PaymentFileLoadDaoOj b">
          <property name="referenceDao"><ref local="pdpReferenceDao"/></property>
          </bean>

          <bean id="pdpDisbursementNumberRangeDao" class="edu.iu.uis.pdp.dao.ojb.DisbursementNumberRa ngeDaoOjb">
          <property name="userService"><ref bean="pdpUserService"/></property>
          </bean>

          <bean id="pdpReferenceDao" class="edu.iu.uis.pdp.dao.ojb.ReferenceDaoOjb">
          <property name="userService"><ref bean="pdpUserService"/></property>
          </bean>

          <bean id="pdpGlPendingTransactionDao" class="edu.iu.uis.pdp.dao.ojb.GlPendingTransaction DaoOjb"/>

          <bean id="pdpApplicationSettingDao" class="edu.iu.uis.pdp.dao.ojb.ApplicationSettingDa oOjb"/>

          <bean id="pdpCustomerProfileDao" class="edu.iu.uis.pdp.dao.ojb.CustomerProfileDaoOj b">
          <property name="userService"><ref bean="pdpUserService"/></property>
          </bean>

          <bean id="pdpBankDao" class="edu.iu.uis.pdp.dao.ojb.BankDaoOjb">
          <property name="userService"><ref bean="pdpUserService"/></property>
          </bean>

          <bean id="pdpPaymentDetailDao" class="edu.iu.uis.pdp.dao.ojb.PaymentDetailDaoOjb" >
          <property name="userService"><ref bean="pdpUserService"/></property>
          <property name="referenceService"><ref local="pdpReferenceService"/></property>
          </bean>

          <bean id="pdpPaymentDetailHistoryDao" class="edu.iu.uis.pdp.dao.ojb.PaymentDetailHistory DaoOjb">
          <property name="userService"><ref bean="pdpUserService"/></property>
          </bean>

          <bean id="pdpAchAccountNumberDao" class="edu.iu.uis.pdp.dao.ojb.AchAccountNumberDaoO jb"/>

          <bean id="pdpPaymentDetailSearchDao" class="edu.iu.uis.pdp.dao.ojb.PaymentDetailSearchD aoOjb">
          <property name="userService"><ref bean="pdpUserService"/></property>
          </bean>

          <bean id="ojbConfigurer" class="org.springframework.orm.ojb.support.LocalOj bConfigurer"/>

          <bean id="TransactionManager" class="org.springframework.orm.ojb.PersistenceBrok erTransactionManager"/>

          <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryB ean">
          <property name="jndiName"><value>java:jdbc/dev/pdp/PDPDB</value></property>
          </bean>
          </beans>

          Comment


          • #6
            Jay,

            I am at a loss here, everything seems in order. However, the only thin I can think of is that this might be an issue with transactions spread across OJB and JDBC, I'm not really sure how that works.

            I do have one more question though: are you invoking methods on multiple transactional proxies and looking for the transation to span the different proxies because it doesn't. When you first call a method on a transactional proxy you start the transaction. Any other methods called in the control flow of the starting method will execute under the transaction. When the starting method ends so does the transaction. If this is the pattern you are following then that is likely where your problem lies. You need to encapsulate each logical transaction into a metho on your transaction proxy.


            If this doesn't help I will post this on the dev list and hopefully someone will know the answer.

            Rob

            Comment

            Working...
            X