This stage is triggered each time a component is rendered by Wicket, typically when its page is requested or when it is refreshed via AJAX.

h3. Method onConfigure

Method @onConfigure()@ has been introduced in order to provide a good point to manage the component states such as its visibility or enabled state. This method is called before the render phase starts. As stated in [chapter 6.1|guide:keepControl_1], @isVisible@ and @isEnabled@ are called multiple times when a page or a component is rendered, so it's highly recommended not to directly override these method, but rather to use @onConfigure@ to change component states. On the contrary method @onBeforeRender@ (see the next paragraph) is not indicated for this task because it will not be invoked if component visibility is set to false.

h3. Method onBeforeRender

The most important hook method of this stage is probably @onBeforeRender()@. This method is called before a component starts its rendering phase and it is our last chance to change its children hierarchy.

If we want add/remove children components this is the right place to do it. In the next example (project LifeCycleStages) we will create a page which alternately displays two different labels, swapping between them each time it is rendered:

{code}
public class HomePage extends WebPage
{
	private Label firstLabel;
	private Label secondLabel;

	public HomePage(){
		firstLabel = new Label("label", "First label");
		secondLabel = new Label("label", "Second label");
		
		add(firstLabel);
		add(new Link("reload"){
			@Override
			public void onClick() {
			}
		});
	}
	
	@Override
	protected void onBeforeRender() {
		if(contains(firstLabel, true))
			replace(secondLabel);
		else
			replace(firstLabel);
		
		super.onBeforeRender();
	}
}
{code}

The code inside @onBeforeRender()@ is quite trivial as it just checks which label among @firstLabel@ and @secondLabel@ is currently inserted into the component hierarchy and it replaces the inserted label with the other one.

This method is also responsible for invoking children @onBeforeRender()@ so if we decide to override it we have to call @super.onBeforeRender()@. However, unlike @onInitialize()@, the call to superclass method should be placed at the end of method's body in order to affect children's rendering with our custom code.

Please note that in the example above we can trigger the rendering stage pressing F5 key or clicking on link “reload”.

{warning}
If we forget to call superclass version of methods @onInitialize()@ or @onBeforeRender()@, Wicket will throw an @IllegalStateException@ with the following message:

@java.lang.IllegalStateException: @org.apache.wicket.Component@ has not been properly initialized. Something in the hierarchy of <page class name> has not called super.onInitialize()/onBeforeRender() in the override of onInitialize()/ onBeforeRender() method@

{warning}

h3. Method onComponentTag

Method @onComponentTag(ComponentTag)@ is called to process component tag, which can be freely manipulated through its argument of type @org.apache.wicket.markup.ComponentTag@. For example we can add/remove tag attributes with methods @put(String key, String value)@ and @remove(String key)@, or we can even decide to change the tag or rename it with method @setName(String)@ (the following code is taken from project OnComponentTagExample):

*Markup code:*

{code:html}
<head>
  <meta charset="utf-8" />
  <title></title>
</head>
<body>		
  <h1 wicket:id="helloMessage"></h1>		
</body>
{code}

*Java code:*

{code}
public class HomePage extends WebPage {
   public HomePage() {
      add(new Label("helloMessage", "Hello World"){
         @Override
         protected void onComponentTag(ComponentTag tag) {            
            super.onComponentTag(tag);
            //Turn the h1 tag to a span
            tag.setName("span");
            //Add formatting style
            tag.put("style", "font-weight:bold");
         }
      });
    }
}
{code}

*Generated markup:*

{code:html}
<head>
  <meta charset="utf-8" />
  <title></title>
</head>
<body>		
  <span wicket:id="helloMessage" style="font-weight:bold">Hello World</span>		
</body>
{code}

Just like we do with @onInitialize@, if we decide to override @onComponentTag@ we must remember to call the same method of the super class because also this class may also customize the tag. Overriding @onComponentTag@ is perfectly fine if we have to customize the tag of a specific component, but if we wanted to reuse the code across different components we should consider to use a behavior in place of this hook method.

We have already seen in [chapter 6.2|guide:keepControl_2] how to use behavior @AttributeModifier@ to manipulate the tag's attribute. In [chapter 17.1|guide:advanced_1] we will see that base class @Behavior@ offers also a callback method named @onComponentTag(ComponentTag, Component)@ that can be used in place of the hook method @onComponentTag(ComponentTag)@.

h3. Methods onComponentTagBody

Method @onComponentTagBody(MarkupStream, ComponentTag)@ is called to process the component tag's body. Just like @onComponentTag@ it takes as input a @ComponentTag@ parameter representing the component tag. In addition, we also find a @MarkupStream@ parameter which represents the page markup stream that will be sent back to the client as response. 

@onComponentTagBody@ can be used in combination with the @Component@'s method @replaceComponentTagBody@ to render a custom body under specific conditions. For example (taken from project OnComponentTagExample) we can display a brief description instead of the body if the label component is disabled:

{code}
public class HomePage extends WebPage {
   public HomePage() {

      add(new Label("helloMessage", "Hello World"){
         @Override
         protected void onComponentTagBody(MarkupStream markupStream, ComponentTag tag) {            
            
           if(!isEnabled())
               replaceComponentTagBody(markupStream, tag, "(the component is disabled)"); 
          else    
               super.onComponentTagBody(markupStream, tag);
         }
      });   
    }
}
{code}

Note that the original version of @onComponentTagBody@ is invoked only when we want to preserve the standard rendering mechanism for the tag's body (in our example this happens when the component is enabled).