+ Start a Discussion
AlexPHPAlexPHP 

Unset / clear ApexPages messages

Hi all

 

I am writing test cases for my Apex Page and want to verify that different messages are set at different points.

 

For this, I would like to clear out existing messages from my ApexPage.

 

Something similar to:

 

ApexPages.Messages = new List<ApexPages.Message>();


Is there a way to do this?

 

bob_buzzardbob_buzzard

Simply invoke the clear() method on the returned list of ApexPages.Message,

 

e.g.

 

 

 

ApexPages.getMessages().clear();

 

 

 

AlexPHPAlexPHP

That doesn't seem to work for me.

 

I have a method that will set an error message as such:

ApexPages.addMessage(new ApexPages.message(ApexPages.Severity.ERROR, 'This is an error message'));

 After doing so, the following assertion in my test case passes:

System.assertEquals(true, ApexPages.hasMessages());

 Then I try the clear method you suggested:

ApexPages.getMessages().clear();

 And then I would assume that there are no more messages.  So I would assume the following assertion would pass as well:

System.assertEquals(false, ApexPages.hasMessages());

... but it does not.  This assertion fails.

 

Am I doing something wrong?

 

Message Edited by AlexPHP on 11-23-2009 01:33 PM
SteveBowerSteveBower

I'm trying to answer the same question.

 

I'm testing the exception cases and instantiate a controller, set Test.setCurrentPage(), use a nextPage=controller.myfunction() to throw an exception, and then check the ApexPages.getMessages() in the Test method.  I have one message as expected.

 

I now get another controller, change some data, reset the Test.setCurrentPage(the vf page) , and do another call to generate a different exception.   There are now two messages in getMessages(). the one from above on [0] and the new one in [1].

 

So, I don't know how ApexMessages.getMessages get's clearer.   I don't think the Clear() mechanism someone suggested would work because getMessages just returns the array to you.  If if you clear it, sort it, etc... it's not effecting what's still in the ApexMessages structure.

 

I don't think it's related to the PageReferences we're passing around either.  Just not sure.

 

If you figure it out, please post it here, I'll do likewise.

 

-Steve.

 

SteveBowerSteveBower

Typo... I meant.

 

So, I don't know how ApexPages.getMessages get's cleared. 

AcMEGXAcMEGX

Hi Guys:

 

Try this:  

 

 

pref = Page.WarrantyRegistration;
pref.setRedirect(true);
pref.getUrl();

 

PageReference pref = Page.YOURVFPAGE;

 pref.setRedirect(true);

pref.getUrl();   -> this will reset ApexPages.Messages

d3developerd3developer
  AcMEGX,
  Don't understand your attempted solution. How would that fix anything? It doesn't even relate to the currentPage, which to my knowledge is the only PageReference which can hold page messages.
bob_buzzardbob_buzzard

The suggestion here is to do a client-side redirect to the page.  This will have the effect of dropping all server side resources associated with the page (all the controller variables etc).

d3developerd3developer

And would presumably require a page reload. In which case, I assume the code should read:

 

 

public PageReference reload() {

    PageReference pageRef = ApexPages.currentPage();
    pageRef.setRedirect(true); 
    return pageRef;

}

 

The docs say that this flushes everything in the view state. Not sure quite how this works with caching and variable state, etc.

 

bob_buzzardbob_buzzard

You'd lose all your variable state information, as the redirect would result in the creation of a new controller with associated properties etc.

 

If you don't have too many variables, you could push them through on the URL.

d3developerd3developer

Right. And I assume that means there is no know way to clear pageMessages without also clearing the variables.

 

But with a cached page the view state and/or variable state is essentially frozen (even, I believe, if you pass different parameters to the page).

bob_buzzardbob_buzzard

It appears that there is no way to clear the messages down.  

 

The behaviour when you pass different parameters really depends on your controller.  If the controller looks at the parameters regardless of whether values have already been initialise then there would be an impact.  

 

d3developerd3developer

I think you mean that there is no way to clear the pageMessages while preserving variable state.

 

If the controller looks at the parameters in the constructor and the page is cached, the constructor will not be called and so any new parameters will not be initialized regardless of whether or not there are new parameters passed.

 

That is my understanding at least.

bob_buzzardbob_buzzard

Actually, I do mean there's no way to clear the pageMessages.  A browser redirect doesn't clear down the existing variables, it discards the controller and all associated information and a fresh one is created when the request is received.  This does seem like an oversight on the SFDC side but I guess its one we're stuck with.

 

You are correct on the constructor.  However, if the controller looks for the parameters anywhere else then the new values will be picked up and acted upon.

d3developerd3developer

I think anywhere else would have to be a user prompted action or embedded actionFunction since I don't think action functions on apex:pages are called on cached pages either...

bob_buzzardbob_buzzard

A getter that interrogates the URL would also be prone to this, I think.

AcMEGXAcMEGX

Guys, try the code below:

 

Note value of  strDebug. ApexMessages is cleared when you return the PageReference of itself. Not all values are destroyed. Apparently, strDebug retains its ViewState value (otherwise it will get its constructor value) and page messages are cleared.

 

Hope this solves the posters question 

 

 

Controller:

 

 

public with sharing class ErrorPOC 
{
	public String strDebug {get;set;}
	public Account account {get;set;}
	public ErrorPOC()
	{
		account = new Account();	
		strDebug = 'Generated During Constructor Execution';
	}
	public PageReference generateError()
	{
		strDebug = 'Generated During Action Function';
		PageReference pref = Page.ErrorPOC;
		try
		{
			Database.insert(account);
		}
		catch(DMLException ex)
		{
			ApexPages.addMessages(ex);
		}
		return pref;
	}	
	public PageReference clearError()
	{
		PageReference pref = Page.ErrorPOC;
		return pref;
	}
}

 

 

 

VF Page:

 

<apex:page controller="ErrorPOC">
<apex:form >
	<apex:pageMessages />
	<apex:outputText value="{!strDebug}" />
	<br />
	<apex:commandButton value="Generate Error" action="{!generateError}" />
	<apex:commandButton value="Reset Error" action="{!clearError}" />
</apex:form>
</apex:page>

 

Regards,

AcMEGX

 

 

d3developerd3developer

I've observed this before and actually I think that any function like this:

 

 

public PageReference refresh() {
  return null;
}

 

Will actually also produce the same results, whether or not it is documented.

 

AcMEGXAcMEGX

See my latter post with code on the thread. Basically its calling a PageReference to itself, this way we clear APEX messages while RETAINING other Viewstate values. 

 

PageReference pref = Page.YOURVFPAGE; 

 pref.setRedirect(false); 

pref.getUrl();   -> this will reset ApexPages.Messages

 

is as good as:

 

    PageReference pageRef = ApexPages.currentPage();
    pageRef.setRedirect(false); 
    return pageRef;

 

which you have probably already deduced.

 


d3developer wrote:
  AcMEGX,
  Don't understand your attempted solution. How would that fix anything? It doesn't even relate to the currentPage, which to my knowledge is the only PageReference which can hold page messages.

 

AcMEGXAcMEGX

OOpss... sorry...setRedirect(true) will clear the viewstate. The reverse though is true

 

Should be 

 

PageRef.setRedirect(false);

Ron WildRon Wild

None of the suggested mentioned in this thread have worked for me.  I'm still unable to clear the messages list returned from ApexPages.getMessages() in an apex test method after errors have been stored there.

 

Has anyone else been able to get this to work?

 

Thx

SteveBowerSteveBower

Hey Ron, since 2009 I've been unable to do this regardless of all these different approaches.   When I want to use the same controller instance I end up coding an integer counter in the test code which I just bump manually after each error condition by the number of messages I've added.    Then use that as an offset each time I need to refer to an error message.  So, the message accumulate, but my code can just refer to errCnt+0, errCnt+1, for the tests...

 

Best, Steve.

Ron WildRon Wild

Thanks for confirming that.   Your approach does seem to be the best .... although I would love it if SF would add an ApexPages.clearMessage() method and make our lives a little bit easier!

 

I've posted a request to SF Ideas if anyone wants to support the idea:   https://sites.secure.force.com/success/ideaView?c=09a30000000D9xtAAC&id=08730000000ZLADAA4

 

Cheers,

Ron

 

ShikibuShikibu

This does not work well for me, because I can't tell if the same message was added twice. For instance, this code:

 

ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, CreateLead.requiredMessage));
ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, CreateLead.requiredMessage));

system.debug(ApexPages.getMessages());        

 

produces this debug log output:

 

14:50:44.386 (1386295000)|USER_DEBUG|[64]|DEBUG|(ApexPages.Message["You must enter at least the Last Name or Employer to check for dupes."])

 

Though i have added two instances, because they have the same string value, getMessages returns only one.

 

Jerun JoseJerun Jose

Exactly what I am also facing at the moment.

 

If we are adding the same message through two or more ways, then getMessages() only returns one instance of it. Also, if we do something like this.

 

ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, Msg1));
ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, Msg2));
ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, Msg1));

Then, Msg1 can only be found at index 0. I was hoping that I could just check the last entry in the PageMessages array [using ApexPages.getMessages().get(ApexPages.getMessages().size()-1) ] to check the most recent entry and use that, but even that wont work for duplicate messages

 

craigmhcraigmh

AlexPHP and other ghosts of the past,

 

The getMessages() method only returns a copy of the Message[] collection, not a reference to it. Unfortunately, the clear() is only clearing out the collection copy.

 

If you're using the same PageReference for a single test method performing tests on separate operations, you do need to change your logic.

I'd recommend creating a PageReference from scratch in your test class in a helper method. You can then instantiate this Page multiple times, and perform each operation on its own instance. This will separate the data persisting, and you can easily have any logic that you would need for each reference repeated in that helper method.

craigmhcraigmh

Jerun Jose,

 

The addMessage() method seems to group anything with the same message together. I used this code:

 

        ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Message'));
        ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.WARNING, 'Message'));
        ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Message'));
        ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL, 'Message'));
        ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Message'));
        ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Message'));
        ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.CONFIRM, 'Message'));
        ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Message'));
        ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO, 'Message'));

 

And of course, only the ERROR ones showed up.

But I called ApexPages.getMessages().size(), and the result was one. So it seems as though the Message[] collection of ApexPages prevents duplicates, even if it's not a reference to the same error.

CrawfordCrawford

Not sure if this is still an issue. But I resolved a similar issue by returning a null PageReference which seems to clear the messages without requiring a redirect and clearing your variables (but.. I haven't tried this from a test class).

AnSFAdminAnSFAdmin

The only way I found to clear ApexPages.getMessages() between 2 tests is to write the tests in different 2 testmethods in my test class.

Ajay CAjay C

Clear() method is not working for me.

 

ApexPages.getMessages().clear();
ApexPages.addMessage(new ApexPages.message(ApexPages.Severity.FATAL,'New Error Message'));

return null;

 

Observation if i am setting my class api-version to 28. it is working as expected.

But I need to set api-version as 29 and clear method is not working and getting multiple error messages.

 

In my case i don't want to reset my page so i am returning null.

 

Please help me.

 

Thanks & Reagards

Ajay C

narsavagepnarsavagep
For future people searching for this issue and finding this thread - this issue was fixed/released Summer '18:
System.Test.clearApexPageMessages()