4

I'm having an issue trying to use dynamicComponent. I'm trying to display an outputPanel, but getting a SerializationException. I'm trying to accomplish this with the following code:

In my page I have a button that calls the goPlatform1 method as the action:

<apex:commandButton value="Go Platform1" action="{! goPlatform1 }" reRender="mainPanel" 
       disabled="{! isPlatform1Disabled }" />

With the idea that it's going to populate a variable called featurePanel:

public Component.Apex.OutputPanel goPlatform1() {
    featurePanel = ( (PlatformFeature)t1.newInstance() ).getFeaturePanel();
            return null;
}

Used by a dynamicComponent tag:

<apex:dynamicComponent componentValue="{! featurePanel }" id="mainPanel" />

The getFeaturePanel() looks like this:

global Component.Apex.OutputPanel getFeaturePanel() {
    Component.Apex.OutputPanel outPanel = new Component.Apex.OutputPanel();
    Component.Apex.PageBlock pgBlock = new Component.Apex.PageBlock();
    pgBlock.id = 'platform1Block';
    pgBlock.title = 'Platform 1 PageBlock';

    outPanel.childComponents.add(pgBlock);

    return outPanel;
}

This produces a System.SerializationException: Not Serializable: Component.apex.outputpanel message on the VF page.

4

I believe there's an issue with your featurePanel (which I guess is a public field or property - right?) and View State.

I wasn't able to find direct statement in documentation but in examples Dynamic Visualforce Components were always created and returned in get method. So they were not stored as part of view state. Exception that you provided is a clue that something is wrong about it.

So what should help you is adding transient keyword to featurePanel field/property.

I don't have all the details of your use case but I quickly prepared a simplified example.

VF:

<apex:page controller="TestPageController">
    <apex:form>
        <apex:commandButton value="Go Platform1" action="{!goPlatform1}" reRender="mainPanel"/>
        <apex:outputPanel layout="block" id="mainPanel">
            <apex:dynamicComponent componentValue="{! featurePanel }" id="mainPanel1" />
        </apex:outputPanel>
        </apex:form>
</apex:page>

Controller:

public class TestPageController {
    transient Component.Apex.OutputPanel featurePanel;

    public Component.Apex.OutputPanel getFeaturePanel() {
        return featurePanel;
    }

    public void goPlatform1() {
        featurePanel = new Component.Apex.OutputPanel();
        Component.Apex.PageBlock pgBlock = new Component.Apex.PageBlock();
        pgBlock.id = 'platform1Block';
        pgBlock.title = 'Platform 2 PageBlock';

        featurePanel.childComponents.add(pgBlock);
    }
}

So the differences are:

  1. I skipped the part where you create FeaturePanel instance
  2. merged those method of FeaturePanel with goPlatform1() method
  3. changed the return type of this method to void
  4. and I also needed to put dynamicComponent under outputPanel because otherwise it wasn't refreshed.

And it worked for me... Of course in this scenario you'll lose featurePanel information when page is refreshed.

Hope my changes weren't too big and this solution still helps you...

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.