3

An easy to see list of all files added to an Account (or other object) would be nice. I am getting a "Content cannot be displayed: Attempt to de-reference a null object" for my VF page. The Account I am testing on does have a loaded file. Class:

public class accountFileExt {

Account a;

public accountFileExt (ApexPages.StandardController controller) {
    a = (Account) controller.getRecord();        
}

public List <ContentDocument> getAccountsContentDocuments () {
    Map<Id, ContentDocumentLink> m = new Map<Id, ContentDocumentLink>([
            select ContentDocumentId
            from ContentDocumentLink
            where LinkedEntityId =: a.id
            ]);
    return [
            select Title, OwnerId, ParentId, PublishStatus
            from ContentDocument
            where Id in :m.keySet()
            order by Title
            ];
}

}

I have updated the query class but am not sure why it gets 0 results for second query.

and here is the page template

<apex:page standardController="Account" extensions="accountFileExt">
    <apex:pageBlock title="Account Files">
        <apex:pageBlockTable value="{!AccountsContentDocuments}" var="c">
            <apex:column value="{!c.title}"/>
        </apex:pageBlockTable>
    </apex:pageBlock>
</apex:page>

Thanks

1
  • I am at a loss here - don't I have the ContentDocumentIDs in the first query - then why isn't the second query finding them? That's the link structure
    – jaw999
    Commented Mar 11, 2014 at 13:45

3 Answers 3

1

This class worked for me - I think the way you are building the map is causing the issue. You are using the standard Map constructor, but I think the map key needs to be the ContentDocumentId field, not the Id field - once I changed that, it seems to work

public class accountFileExt{

Account a;

public accountFileExt (ApexPages.StandardController controller) {
    a = (Account) controller.getRecord();        
}

public List <ContentDocument> getAccountsContentDocuments () {
    Map<Id, ContentDocumentLink> m = new Map<Id, ContentDocumentLink>();
    for (ContentDocumentLink cl: [Select ContentDocumentId
            from ContentDocumentLink
            where LinkedEntityId =: a.id
            ]){
            m.put(cl.ContentDocumentId, cl);
            }
    return [
            select Title, OwnerId, ParentId, PublishStatus
            from ContentDocument
            where Id in :m.keySet()
            order by Title
            ];
}
}
1
  • Yes, that's it, thanks. Maps are an area I need to hone my skills on. Thanks again.
    – jaw999
    Commented Mar 12, 2014 at 13:42
2

You can find the line number of the problem by looking in the debug log.

It is in the DocumentLinks query because that code executes before the variable a is assigned in the constructor (as execution order isn't the same is the order of the code in the class).

This can be fixed in a variety of ways; here is one:

public class accountFileExt {

    Account a;

    public accountFileExt (ApexPages.StandardController controller) {
        a = (Account) controller.getRecord();        
    }

    public List <ContentDocument> getAccountsContentDocuments () {
        Map<Id, ContentDocumentLink> m = new Map<Id, ContentDocumentLink>([
                select Id
                from ContentDocumentLink
                where LinkedEntityId =: a.id
                ]);
        return [
                select Title, OwnerId, ParentId, PublishStatus
                from ContentDocument
                where ParentId in :m.keySet()
                order by Title
                ];
    }
}
2
  • Thanks! This eliminates the null object error but no lines display on the page loaded onto an Account. It returns 0 for the second return.
    – jaw999
    Commented Mar 7, 2014 at 21:30
  • Sorry all I did was address your NPE. I have no experience with these objects so do not know if the relationships or approach are right. Hopefully @BritishBoyinDC can help you.
    – Keith C
    Commented Mar 7, 2014 at 23:19
2

I've done this with the ConnectAPI so users can select docs to share with another account/opportunity. I have a utility class with a wrapper, then display that wrapper on the VF page. I

public with sharing class ChatterUtilityClass {

public List<AttachmentWrapper> feeda {get;set;}

    public void getAttachments(Id SourceRecordId) {
      ConnectApi.FeedItemPage fip = ConnectApi.ChatterFeeds.getFeedItemsFromFeed(null, ConnectApi.FeedType.Record, SourceRecordId) ;

        feeda = new List<AttachmentWrapper> ();
        for (ConnectApi.FeedItem fit : fip.items) {
            if (fit.Type == ConnectApi.FeedItemType.ContentPost) {
                feeda.add( new AttachmentWrapper( (ConnectApi.ContentAttachment)fit.attachment));
            }
        }
    }

public void setupAttachmentstoShare (Id TargetRecordId) {

for (AttachmentWrapper aw: feeda) {

    if (aw.bInclude) {
        ConnectApi.ContentAttachmentInput cai = new ConnectApi.ContentAttachmentInput();
        cai.contentDocumentId = aw.sourceca.Id;

        ConnectApi.FeedItemInput input = new ConnectApi.FeedItemInput();
        input.attachment = cai;
        input.visibility = ConnectApi.FeedItemVisibilityType.InternalUsers; 

        ConnectApi.ChatterFeeds.postFeedItem(null, 
                                            ConnectApi.FeedType.Record,
                                            TargetRecordId, 
                                            input,
                                            null);
        }
    }
}



    public class AttachmentWrapper {
        public Boolean bInclude {get;set;}
        public ConnectApi.ContentAttachment sourceca {get;set;}

        public AttachmentWrapper(ConnectApi.ContentAttachment ca) {
            sourceca = ca;
            bInclude = FALSE;
    }   
    } 
} 

Page Extension Controller:

public with sharing class ConvertOpportunitytoGrantController {

private final Opportunity opty; 
public ChatterUtilityClass ChatterUtility {get;set;}

    public ConvertOpportunitytoGrantController (ApexPages.StandardController stdController) {
        this.opty = (Opportunity)stdController.getRecord();

        ChatterUtility = new ChatterUtilityClass();
        ChatterUtility.getAttachments(this.opty.Id); 
        }
public pageReference shareFiles() {
  ChatterUtility.setupAttachmentstoShare([Id of object to share files with]);
}    
}

And then the page:

<apex:page standardController="Opportunity" sidebar="FALSE" cache="FALSE" extensions="ConvertOpportunitytoGrantController">

<apex:pageBlock title="Attachments">
<apex:pageBlockTable value="{!ChatterUtility.feeda}" var="fa">

<apex:column headerValue="Include?">
<apex:inputCheckbox value="{!fa.bInclude}"/>
</apex:column>

<apex:column headerValue="File Name">
<apex:image url="{!fa.sourceca.renditionUrl}" />
</apex:column>

<apex:column headerValue="Name">
<apex:outputLink target="_blank" value="/{!fa.sourceca.versionId}">{!fa.sourceca.Title}</apex:outputLink>
</apex:column>

</apex:pageBlockTable>
</apex:pageBlock>

</apex:form>
</apex:page>
3
  • This one is beyond me. The wrapper class is having a compile error on line ChatterUtility.setupAttachmentstoShare([Id of object to share files with])
    – jaw999
    Commented Mar 10, 2014 at 18:33
  • You need to replace [Id of object to share files with] with a valid id field of the object you want to share the selected chatter files with e.g. account.Id Commented Mar 10, 2014 at 19:41
  • Thanks, this is above what I am looking for. I may try to play with later when I have more time to test. Any thoughts on what I am missing with the simpler one I am trying?
    – jaw999
    Commented Mar 11, 2014 at 15:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .