Attachment Service
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
DatabaseAttachment.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
DatabaseAttachmentDaoOjb
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
DatabaseAttachmentServiceImpl
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
OJB-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
. . <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"/> . .
Â
Â