2

My implemented methods are not getting called from DAO Class.

I created bundle xml with name search_dao_bundle.xml as below and placed on same location i.e. tridion_home/config where my cd_storage_xml is placed.

<?xml version="1.0" encoding="UTF-8"?>
<StorageDAOBundles>
<StorageDAOBundle type="persistence">
    <StorageDAO typeMapping="PublishAction" class="com.tridion.storage.extension.search.JPAPublishActionDAO" />
</StorageDAOBundle>
</StorageDAOBundles>

After that I added my bundle entries into my cd_storage_conf.xml as below:

<StorageBindings>
    <Bundle src="search_dao_bundle.xml"/>
</StorageBindings>

and down under I created my new storage type as below:

<Storage Type="persistence" Id="searchdb" dialect="MSSQL" Class="com.tridion.storage.persistence.JPADAOFactory">
    <Pool Type="jdbc" Size="5" MonitorInterval="60" IdleTimeout="120" CheckoutTimeout="120" />
    <DataSource Class="com.microsoft.sqlserver.jdbc.SQLServerDataSource">
        <Property Name="serverName" Value="********" />
        <!--Property Name="portNumber" Value="1433" /-->
        <Property Name="databaseName" Value="********" />
        <Property Name="user" Value="********" />
        <Property Name="password" Value="********" />
    </DataSource>
</Storage>

After that for itemmapping I did below

<ItemTypes defaultStorageId="defaultdb" cached="false"> 
    <Item typeMapping="PublishAction" cached="false" storageId="searchdb" />
</ItemTypes>

I restarted my deployer service got below exception in my core logs

Below is my sample DAO class taken from Mihai Code:

package com.tridion.storage.extension.search;

import java.util.HashMap;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.tridion.broker.StorageException;
import com.tridion.storage.extension.search.PublishActionDAO;
import com.tridion.storage.persistence.JPABaseDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component("JPAPublishActionDAO")
@Scope("prototype")
public class JPAPublishActionDAO extends JPABaseDAO implements PublishActionDAO
{
    private static Logger log = LoggerFactory.getLogger(JPAPublishActionDAO.class);
    public JPAPublishActionDAO(String storageId, EntityManagerFactory entityManagerFactory, String storageName) 
    {
        super(storageId, entityManagerFactory, storageName);        
        log.debug("Constructor of JPAPublishActionDAO- storageId:"+storageId);
        log.debug("Constructor of JPAPublishActionDAO- entityManagerFactory:"+entityManagerFactory.isOpen());       
        log.debug("Constructor of JPAPublishActionDAO- storageName:"+storageName);
    }

     public JPAPublishActionDAO(String storageId, EntityManagerFactory entityManagerFactory, EntityManager entityManager, String storageName) 
     {       
            super(storageId, entityManagerFactory, entityManager, storageName);         
     }

     public PublishAction store(PublishAction publishAction) throws StorageException 
     {
         log.debug("JPAPublishActionDAO store");
         //System.out.println("\n******************** From Store *************************************");
            PublishAction entity = (PublishAction) super.create(publishAction);
            return entity;
     }

     @SuppressWarnings("unchecked")
    public PublishAction findByPrimaryKey(long publishActionId) throws StorageException 
     {
            log.debug("JPAPublishActionDAO findByPrimaryKey");
            StringBuilder queryBuilder = new StringBuilder();
            queryBuilder.append("select c from PublishAction c where c.id = :id");

            @SuppressWarnings("rawtypes")
            Map queryParams = new HashMap();
            queryParams.put("id", Long.valueOf(publishActionId));
            log.debug("JPAPublishActionDAO findByPrimaryKey -> queryBuilder- " +queryBuilder.toString());
            return (PublishAction) super.executeQuerySingleResult(queryBuilder.toString(), queryParams);
     }

     @SuppressWarnings("unused")
    public PublishAction update(PublishAction publishAction) throws StorageException 
     {
            log.debug("JPAPublishActionDAO update");
            PublishAction existingPublishAction = findByPrimaryKey(publishAction.getId());

            log.debug("JPAPublishActionDAO update -> existingPublishAction- " +existingPublishAction.toString());
            if (existingPublishAction != null) 
            {
                   return (PublishAction) super.update(publishAction);
            } 
            else 
            {
                   throw new StorageException("Could not find publish action in storage to update!!!");
            }
     }

     public void remove(long publishActionId) throws StorageException 
     {
            log.debug("JPAPublishActionDAO remove");
            PublishAction foundPublishAction = findByPrimaryKey(publishActionId);
            log.debug("JPAPublishActionDAO remove -> foundPublishAction- " +foundPublishAction.toString());
            if (foundPublishAction != null) 
            {
                   super.remove(foundPublishAction);
            }
     }
}

I am able to see that my constructor is getting called i.e. I am getting these logs in my core file logs

log.debug("Constructor of JPAPublishActionDAO- storageId:"+storageId);
log.debug("Constructor of JPAPublishActionDAO- entityManagerFactory:"+entityManagerFactory.isOpen());       
log.debug("Constructor of JPAPublishActionDAO- storageName:"+storageName);

However I am not getting any logs written in other methods like in method public PublishAction store log.debug("JPAPublishActionDAO store");

log.debug("JPAPublishActionDAO findByPrimaryKey");

log.debug("JPAPublishActionDAO update");

What could be the reason, I have entity class with name (PublishAction.java) and Interface class (PublishActionDAO.java) same as in sample code given.

Manoj Singh
  • 7,569
  • 34
  • 119
  • 198
  • Have you configured the storage conf & bindings in your XML? might be worth including those into your question. – johnwinter Jan 06 '13 at 15:20
  • @johnwinter, Yes I have already done, I have posted one more question regarding that issue please see (http://stackoverflow.com/questions/14135716/getting-no-bean-named-defined-while-implementing-storage-extension-in-tridion-20) :) – Manoj Singh Jan 06 '13 at 15:25
  • 2
    Don't refer to previous questions. Instead, just make sure that all the relevant information is in this question. – Frank van Puffelen Jan 06 '13 at 16:56
  • 2
    But while we're on the subject: you have yet to mark any answer to that question as "accepted". Did you manage to sort the problem out? If so, please either provide the definitive answer with that question or mark the answer that was most helpful in your solving it. – Frank van Puffelen Jan 06 '13 at 16:58
  • @Frank thanks...I have added few more details. – Manoj Singh Jan 07 '13 at 03:43
  • While I cannot tell you why the methods are not called, I can ask you to double-check: is your bindings XML in the classpath? What does the debug core log say? Any mention of the new publish action type? – Mihai Cădariu Jan 07 '13 at 08:35
  • @Mihai, Finally we got the main hero here :), well I am getting my constructor called and I can see "PublishAction" is properly loaded in core files, only concern is that my implmented methods are not getting called, I am not able to understand what could be the reason as simple methods used in Constructor are getting called, please suggest!! – Manoj Singh Jan 07 '13 at 08:50
  • @Mihai, what do you mean by "I can ask you to double-check: is your bindings XML in the classpath?" – Manoj Singh Jan 07 '13 at 09:59
  • You have a lot of samples in your description but I do not see how you call your DAO. Can you please add the code that is using this DAO? – Daniel Neagu Jan 07 '13 at 11:17
  • @sea_gull, where I need to add sample code for using DAO. My DAO should be excuted internally using JPABaseDAO or I am missing something, please suggest!! – Manoj Singh Jan 07 '13 at 11:29
  • I was suggesting to check that the binding XML is available either in the JAR of the Storage Extension or in the folder that's on the classpath of your CD instance. I see however that your extension DAO loads fine, so that's not the issue... – Mihai Cădariu Jan 07 '13 at 17:11
  • @MihaiCădariu, Can you please clear me how you got access your classes from code, did you wrote any deployer extension or how your DAO class was initiated – Manoj Singh Jan 07 '13 at 17:14

3 Answers3

3

The PublishAction type is not one of the default Tridion types which means it's not going to be used by default. In order for your DAO to be used you need to call it from somehow during the deployment process, usually from a Deployer Module. Can you check how and where are you using this PublishActionDAO?

Daniel Neagu
  • 1,711
  • 11
  • 13
  • as you can see in storage configuration we call com.tridion.storage.persistence.JPADAOFactory which internally calls JPABaseDAO. And our new DAO class extends the same as well as implements custom interface as well and later it implements interface methods as well. My problem is that my new custom DAO class is loaded perfectly, however does not recognize my custom interface as well as entity class.Or I am missing any configuration for it. As per http://www.sdltridionworld.com/articles/sdltridion2011/tutorials/extending-content-delivery-storage-sdltridion-2011-1.aspx, I am doing same as it – Manoj Singh Jan 07 '13 at 15:15
  • As well as I can see my new ItemMapping "PublishAction" is getting loaded perfectly in core files, just method are not getting executed. – Manoj Singh Jan 07 '13 at 15:17
  • Hi @ManojSingh. The code is just fine. The fact that it loads goes to show that you created everything good. The only question now is how are you using the DAO. That DAOFactory only creates and makes available the needed DAO's but external code needs to make use of it. At the end of http://www.sdltridionworld.com/articles/sdltridion2011/tutorials/extending-content-delivery-storage-sdltridion-2011-3.aspx you have an unit test. If it passes then create a Deployer Extension: http://www.sdltridionworld.com/articles/sdltridion2011/tutorials/Deployer_Extensions_With_Eclipse_1.aspx to use your DAO. – Daniel Neagu Jan 07 '13 at 16:37
  • @sea_gull..many thanks are you sure we need to create deployer extension to access my new DAO class as I haven't found any article for that (http://sdltridionworld.com/images/SDLWCMS_HowTo_StorageExtension_US_EN_a_tcm89-19437.pdf) – Manoj Singh Jan 07 '13 at 16:47
  • It all depends on what is really the usage of your extension. Technically speaking you can use it directly in an UnitTest; you do not necessary need a deployer extension. Most people use Deployer extenstions because they are called during the deployment process. Some people just want to use it directly on the website and then they just have code calling that DAO (first to get it from the StorageManagerFactory, then to perform CRUD operations with that DAO). – Daniel Neagu Jan 07 '13 at 17:08
  • @ManojSingh: sea_gull is right - you need indeed to call the new DAO. The reason for it being this is a new type, so the Content Delivery storage mechanism won't know what to do with it. You have to call it somehow (potentially from a deployer module, but not necessarily). I used a unit test for calling (proving that it works). I'll post some code in another answer... – Mihai Cădariu Jan 07 '13 at 17:19
3

I cannot post formatted code in a comment, hence this new answer.

@sea_gull is right - you need indeed to call the new DAO. The reason for it being this is a new type, so the Content Delivery storage mechanism won't know what to do with it. You have to call it somehow (potentially from a deployer module, but not necessarily). I used a unit test for calling it (just to provie that it works).

This is my sample unit test code I use to call the storage extension with:

package com.tridion.extension.search.test;

import static org.junit.Assert.fail;

import java.util.Date;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tridion.broker.StorageException;
import com.tridion.storage.StorageManagerFactory;
import com.tridion.storage.extension.search.PublishAction;
import com.tridion.storage.extension.search.PublishActionDAO;

/**
 * @author Mihai Cadariu
 */
public class DAOTestCase {

    private final Logger log = LoggerFactory.getLogger(DAOTestCase.class);

    /**
     * Test method for
     * {@link com.tridion.storage.extension.search.PublishActionDAO#store(com.tridion.storage.search.PublishAction)}.
     */
    @Test
    public void testDAO() {
        try {
            log.debug("Get PublishActionDAO");
            PublishActionDAO publishActionDAO = (PublishActionDAO) StorageManagerFactory.getDefaultDAO("PublishAction");

            log.debug("Create new PublishAction bean");
            PublishAction publishAction = new PublishAction();
            publishAction.setAction("testStore action");
            publishAction.setContent("testStore content");
            publishAction.setTcmUri("testStore tcmUri");
            publishAction.setUrl("testStore url");
            publishAction.setCreationDate(new Date());

            // Store
            log.debug("Store bean");
            publishAction = publishActionDAO.store(publishAction);
            log.debug("Stored bean " + publishAction);
            long id = publishAction.getId();

            // FindByPrimaryKey
            log.debug("Find PublishAction by PK=" + id);
            publishAction = publishActionDAO.findByPrimaryKey(id);
            log.debug("Found bean " + publishAction);

            if (publishAction == null) {
                log.error("Cannot find bean");
                fail("TestFindByPrimaryKey failed: cannot retrieve object with pk " + id);
            }

            log.debug("Modifying bean content");
            String content = publishAction.getContent();
            content += "\r\nMODIFIED " + new Date();
            publishAction.setContent(content);

            // Update
            log.debug("Update bean");
            publishActionDAO.update(publishAction);

            // Remove
            log.debug("Remove bean");
            publishActionDAO.remove(id);
        } catch (StorageException se) {
            log.debug("TestDAO failed: Exception occurred " + se);
            fail("TestDAO failed: Exception occurred " + se);
            se.printStackTrace();
        }
    }
}

If you call the code from a Deployer extension, this is the sample code I used:

public class PageDeployModule extends PageDeploy {

    private final Logger log = LoggerFactory.getLogger(PageDeployModule.class);

    public PageDeployModule(Configuration config, Processor processor) throws ConfigurationException {
        super(config, processor);
    }

    /**
     * Process the page to be published
     */
    @Override
    protected void processPage(Page page, File pageFile) throws ProcessingException {
        log.debug("Called processPage");

        super.processPage(page, pageFile);
        processItem(page);
    }

    private void processItem(Page page) {
        log.debug("Called processItem");
        try {
            SearchConfiguration config = SearchConfiguration.getInstance();
            String externalUrl = config.getExternalAccessUrl() + page.getURLPath();
            String internalUrl = config.getInternalAccessUrl() + page.getURLPath();

            PublishAction publishAction = new PublishAction();
            publishAction.setAction("Publish");
            publishAction.setTcmUri(page.getId().toString());
            publishAction.setUrl(externalUrl);
            publishAction.setContent(Utils.getPageContent(internalUrl));

            PublishActionDAO publishActionDAO = (PublishActionDAO) StorageManagerFactory.getDefaultDAO("PublishAction");
            publishAction = publishActionDAO.store(publishAction);
            log.debug("Stored bean " + publishAction);
        } catch (StorageException se) {
            log.error("Exception occurred " + se);
        }
    }
}

You can use the same approach for the PageUndeploy, where you mark the action as "Unpublish".

Nuno Linhares
  • 10,214
  • 1
  • 22
  • 42
Mihai Cădariu
  • 2,407
  • 14
  • 17
  • @Mihai...thanks so I just need to make new class with name example DAOTestCase in same package on DAO and after that we need to deploy the JAR in tridion_home/lib, however question remain same how DAOTestCase get executed and how my class gets the values for below code publishAction.setAction("testStore action"); publishAction.setContent("testStore content"); publishAction.setTcmUri("testStore tcmUri"); publishAction.setUrl("testStore url"); – Manoj Singh Jan 07 '13 at 17:31
  • The new type you are storing must contain some meaningful stuff to store. That's the info you will need to populate your DAO field with. In my sample, I was implementing a search extension, so I needed data like URL, content, timestamp, action type. You will need to call the new storage type yourself based on your need. Again, in my search extension, I actually called it from a custom Deployer module, but you should call it from wherever you need it (e.g. another DAO potentially) – Mihai Cădariu Jan 07 '13 at 17:36
  • Actually i am also trying to implement same search indexer (autonomy) for our website and would be storing same type data which you are trying to store, so first try to implement same logic which you have used and later I will modify it according to my need, so is there any sample code posted how you called it DAO from custom Deployer module or it just simple way to new class and add the module entry in cd_deployer config – Manoj Singh Jan 07 '13 at 17:47
  • @thanks Mihai for pointing in right direction, I will try to implement same for page/component/binary data as it is required for my implementation, what is the other way (another DAO potentially) if I don't want to use deployer extension to initiate my class, and which would be good as per performance wise. – Manoj Singh Jan 07 '13 at 18:06
0

More information needed: 1) What actually you are publishing while wanted to get invoked these methods - A Dynamic CP or a Page

2) From where you have received this code? I did not see any "create" method in your code...from where did you receive this code

In your previous post related to the "No named Bean loaded" error; Nuno has mentioned for one discussion on Tridion Forum (also given the forum link over there) started by Pankaj Gaur (i.e. me)...did you referred that?

Please note, If your Constructor is getting called, then there is no issue in your configuration at least; it is either the code or the mismatch in the type that you are publishing.

Also Note that, if you are trying to re-publish something without making any change, the Storage Extension might not get loaded (or the methods might not get invoked); so my suggestion during debuging, publsh always after making some changes in your presentation.

I hope it helps, else share the skeleton code along with the JAR file, and I will try t

Pankaj Gaur
  • 307
  • 2
  • 4
  • 17