Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Overview

In order to accommodate storing attachments in the database rather than on the file system it is necessary to override the existing attachment service and modify the database access configuration of the attachment table to allow for an additional column that will contain the attachment. 

 

Wiring it all together

Create new package structures and classes in the Rice UConn module.

edu.uconn.kuali.rice.krad.bo to contain the business object

Code Block
languagejava
titleDatabaseAttachment.java
package edu.uconn.kuali.rice.krad.bo;

import org.kuali.rice.krad.bo.Attachment;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;

/**
 *
 * @author dchudnow
 *
 */
@Entity
@Table (name="KRNS_ATT_T")
public class DatabaseAttachment extends Attachment{
    
    @Column (name="FILE_CONTENT")
    private byte[] attachmentContent;
    
    public DatabaseAttachment(){
        
    }
    
    public byte[] getAttachmentContent(){
        return this.attachmentContent;
    }
    
    public void setAttachmentContent(byte[] attachmentContent){
        this.attachmentContent = attachmentContent;
    }
}

edu.uconn.kuali.rice.krad.dao.impl to contain the data access object

Code Block
languagejava
titleDatabaseAttachmentDaoOjb
public class DatabaseAttachmentDaoOjb extends PlatformAwareDaoBaseOjb implements AttachmentDao{
    private static Logger LOG = Logger.getLogger(DatabaseAttachmentDaoOjb.class);
    
    public DatabaseAttachmentDaoOjb(){
        super();
    }
    
    @Override
    public DatabaseAttachment getAttachmentByNoteId(Long noteId) {
        Criteria criteria = new Criteria();
        criteria.addEqualTo("noteIdentifier", noteId);
        LOG.debug("Datasource: "+this.getPersistenceBrokerTemplate().getDataSource());
        return (DatabaseAttachment) this.getPersistenceBrokerTemplate().getObjectByQuery(new QueryByCriteria(DatabaseAttachment.class, criteria));
    }
}

 

edu.ucoon.kuail.rice.krad.service.impl to contain the override attachment service

Code Block
languagejava
titleDatabaseAttachmentServiceImpl
public class DatabaseAttachmentServiceImpl implements AttachmentService {
    private Logger LOG = Logger.getLogger(DatabaseAttachmentServiceImpl.class);
    private ConfigurationService kualiConfigurationService;
    private AttachmentDao attachmentDao;
    private Map<String, String> mimeTypeMapping;
    @Override
    public Attachment createAttachment(PersistableBusinessObject parent, String uploadedFileName, String mimeType,
            int fileSize, InputStream fileContents, String attachmentTypeCode) throws IOException {
        if (LOG.isDebugEnabled()) {
            LOG.debug("starting to create attachment for document: " + parent.getObjectId());
        }
        if (parent == null) {
            throw new IllegalArgumentException("invalid (null or uninitialized) document");
        }
        if (StringUtils.isBlank(uploadedFileName)) {
            throw new IllegalArgumentException("invalid (blank) fileName");
        }
        if (StringUtils.isBlank(mimeType)) {
            throw new IllegalArgumentException("invalid (blank) mimeType");
        }
        if (fileSize <= 0) {
            throw new IllegalArgumentException("invalid (non-positive) fileSize");
        }
        if (fileContents == null) {
            throw new IllegalArgumentException("invalid (null) inputStream");
        }
        // create DocumentAttachment
        String uniqueFileNameGuid = UUID.randomUUID().toString();
        DatabaseAttachment attachment = new DatabaseAttachment();
        attachment.setAttachmentIdentifier(uniqueFileNameGuid);
        attachment.setAttachmentFileName(uploadedFileName);
        attachment.setAttachmentFileSize(new Long(fileSize));
        attachment.setAttachmentMimeTypeCode(mimeType);
        attachment.setAttachmentTypeCode(attachmentTypeCode);
        LOG.debug("finished creating attachment for document: " + parent.getObjectId());
        return attachment;
    }
    @Override
    public InputStream retrieveAttachmentContents(Attachment attachment) throws IOException {
        if (attachment.getNoteIdentifier() != null) { //already saved in database
            DatabaseAttachment dbAttachment = (DatabaseAttachment) getAttachmentByNoteId(attachment.getNoteIdentifier());
            return new BufferedInputStream(new ByteArrayInputStream(dbAttachment.getAttachmentContent()));
        } else {
            DatabaseAttachment dbAttachment = (DatabaseAttachment) attachment;
            return new BufferedInputStream(new ByteArrayInputStream(dbAttachment.getAttachmentContent()));
        }
    }
    @Override
    public void deleteAttachmentContents(Attachment attachment) {
        if (attachment instanceof DatabaseAttachment) {
            DatabaseAttachment dbAttachment = (DatabaseAttachment) attachment;
            dbAttachment.setAttachmentContent(null);
        }
    }
    @Override
    public void moveAttachmentWherePending(Note note) {
        /*
         *  no pending attachments to move
         */
    }
    @Override
    public void deletePendingAttachmentsModifiedBefore(long modificationTime) {
        /*
         *  no pending attachments to move
         */
    }
    @Override
    public Attachment getAttachmentByNoteId(Long noteId) {
        return attachmentDao.getAttachmentByNoteId(noteId);
    }
    /*
     * Accesses the map for obtaining the image icon paths
     * @return map of mime type to image icon paths
     */
    public Map<String, String> getMimeTypeMapping() {
        return mimeTypeMapping;
    }
    /*
     * Sets the mime type map configured inside of Spring
     * @param mimeTypeMapping to determine image icon paths
     */
    public void setMimeTypeMapping(Map<String, String> mimeTypeMapping) {
        this.mimeTypeMapping = mimeTypeMapping;
    }
    public String convertMimeTypeToIconPath(String attachmentMimeTypeCode) {
        try {
            if (getMimeTypeMapping().containsKey(attachmentMimeTypeCode)) {
                return getMimeTypeMapping().get(attachmentMimeTypeCode);
            }
        } catch (Exception ignored) {
            LOG.debug("Mime Type not found, could not convert to correct Icon Path, check spring configuration");
        }
        // if the spring bean mapping is corrupted return the default clip image
        return "clip.gif";
    }
    public ConfigurationService getKualiConfigurationService() {
        return kualiConfigurationService;
    }
    public void setKualiConfigurationService(ConfigurationService kualiConfigurationService) {
        this.kualiConfigurationService = kualiConfigurationService;
    }
    public AttachmentDao getAttachmentDao() {
        return attachmentDao;
    }
    public void setAttachmentDao(AttachmentDao attachmentDao) {
        this.attachmentDao = attachmentDao;
    }

 

Modify org.kuali.rice.krad.config.Ojb-repository-krad.xml

Code Block
titleOJB-repository-krad.xm
    <class-descriptor class="org.kuali.rice.krad.bo.Note" table="KRNS_NTE_T">
        <field-descriptor name="noteIdentifier" column="NTE_ID" jdbc-type="BIGINT" primarykey="true" indexed="true" autoincrement="true"
                          sequence-name="KRNS_NTE_S" />
        <field-descriptor name="objectId" column="OBJ_ID" jdbc-type="VARCHAR" indexed="true" />
        <field-descriptor name="versionNumber" column="VER_NBR" jdbc-type="BIGINT" locking="true" />
        <field-descriptor name="remoteObjectIdentifier" column="RMT_OBJ_ID" jdbc-type="VARCHAR" />
        <field-descriptor name="authorUniversalIdentifier" column="AUTH_PRNCPL_ID" jdbc-type="VARCHAR" />
        <field-descriptor name="notePostedTimestamp" column="POST_TS" jdbc-type="TIMESTAMP" />
        <field-descriptor name="noteTypeCode" column="NTE_TYP_CD" jdbc-type="VARCHAR" />
        <field-descriptor name="noteText" column="TXT" jdbc-type="VARCHAR" />
        <field-descriptor name="notePurgeCode" column="PRG_CD" jdbc-type="VARCHAR" />
        <field-descriptor name="noteTopicText" column="TPC_TXT" jdbc-type="VARCHAR" />
        <reference-descriptor name="noteType" class-ref="org.kuali.rice.krad.bo.NoteType" auto-retrieve="true" auto-update="none" auto-delete="none">
            <foreignkey field-ref="noteTypeCode" />
        </reference-descriptor>
        <!-- fdocAttachmentIdentifier ABOVE AND REFERENCE BELOW ARE TEMPORARY B/C THIS SHOULD BE 1 TO MANY -->
        <!--   replaced with below reference-descriptior to accomodate saving attachments to the database 
        <reference-descriptor name="attachment" class-ref="org.kuali.rice.krad.bo.Attachment" auto-retrieve="true" auto-update="object" auto-delete="object">
       -->
            <reference-descriptor name="attachment" class-ref="edu.uconn.kuali.rice.krad.bo.DatabaseAttachment" auto-retrieve="true" auto-update="object" auto-delete="object">
                <foreignkey field-ref="noteIdentifier" />
            </reference-descriptor>
    </class-descriptor>
.
.
    <!-- KFS-5 Replace default file storage mechanism so that it writes to the DB instead of the file system --> 
    <class-descriptor class="edu.uconn.kuali.rice.krad.bo.DatabaseAttachment" table="KRNS_ATT_T">
        <field-descriptor name="noteIdentifier" column="NTE_ID" jdbc-type="BIGINT" primarykey="true" index="true"/>
        <field-descriptor name="objectId" column="OBJ_ID" jdbc-type="VARCHAR"/>
        <field-descriptor name="versionNumber" column="VER_NBR" jdbc-type="BIGINT" locking="true"/>
        <field-descriptor name="attachmentMimeTypeCode" column="MIME_TYP" jdbc-type="VARCHAR"/>
        <field-descriptor name="attachmentFileName" column="FILE_NM" jdbc-type="VARCHAR"/>
        <field-descriptor name="attachmentIdentifier" column="ATT_ID" jdbc-type="VARCHAR"/>
        <field-descriptor name="attachmentFileSize" column="FILE_SZ" jdbc-type="BIGINT"/>
        <field-descriptor name="attachmentTypeCode" column="ATT_TYP_CD" jdbc-type="VARCHAR"/>
        <field-descriptor name="attachmentContent" column="FILE_CONTENT" jdbc-type="BLOB"/>
        <reference-descriptor name="note" class-ref="org.kuali.rice.krad.bo.Note" auto-retrieve="object" auto-update="none" auto-delete="none">
            <foreignkey field-ref="noteIdentifier"/>
        </reference-descriptor>
    </class-descriptor>

Add bean definitions to override the attachment service in UConnKrOverrideSpringBeans.xml

Code Block
languagexml
.
.
    <bean id="attachmentService" class="edu.uconn.kuali.rice.krad.service.impl.DatabaseAttachmentServiceImpl" >
        <property name="kualiConfigurationService">
            <ref bean="kualiConfigurationService"/>
        </property>
        <property name="attachmentDao">
            <ref bean="attachmentDao"/>
        </property>
    </bean>
  
   <bean id="attachmentDaoOjb" parent="platformAwareDao" class="edu.uconn.kuali.rice.krad.dao.impl.DatabaseAttachmentDaoOjb"/>
.
.