How to Create Controllers

Extensibility
Extensibility covers the mechanisms by which you, as the user or developer, can extend the functionality of the Teradata Database, for example with the use of User Defined Functions, or UDFs.
Teradata Employee

How to Create Controllers

You have two options for creating controller classes. You can extend the classes provided by SpringMVC or you can extend classes provided by Teradata Viewpoint. Both types of classes are configured the same way in your application configuration files.

Documentation for the SpringMVC controller classes can be found at the Spring Framework web site and in several books.

Teradata Corporation recommends using the Teradata Viewpoint controller classes. These classes have been optimized for writing Teradata Viewpoint portlets, so you will write much less code and that code will be simpler and easier to maintain and test. The biggest advantage of the Teradata Viewpoint controller classes is code reuse. You can use the same code to respond to both portlet and servlet requests. Also, you can use the same code to handle user preferences forms and portlet configuration forms (assuming the forms have the same content, which they usually do).

This page documents how to implement Teradata Viewpoint controller classes. For information on how to integrate these controller classes into your application, see How to Create a View Controller and How to Create a Preferences Controller.

There are two Teradata Viewpoint controller classes:

  • Controller is used to render pages that do not contain forms.
  • FormController is used to handle pages that contain forms.

Both of these classes have a common set of methods that you will use to implement your controller functionality. These common methods can be found in the javadocs for the ControllerContext class.

What Can You Do from a Teradata Viewpoint Controller?

In every request handling method in a Teradata Viewpoint controller, you have access to a ControllerContext parameter. This parameter provides access to all of the information you need about the request and response. The following sections describe the methods available via this parameter (the parameter is abbreviated ctx in the following examples).

Basic Operations

The following examples illustrate the basic, built-in capabilities of the Teradata Viewpoint controller and FormController based controllers that you are likely to use in every portlet that you write.

Read request parameters

You can access the parameters specified in the incoming request using getParameter:

String context = ctx.getParameter("context");

Specify the view

You can specify which view to use to render the response using setViewName:

ctx.setViewName("summary");

Spring will use the viewResolver rules to find the associated view implementation. This command would normally execute WEB-INF/portlet-jsp/summary.jsp.

Pass data to the view

You can pass java objects to your view using addViewObject:

ctx.addViewObject("pigsCanFly", false);

In your JSP file, you can use JSP expression language to reference a view object by its name:

<c:if test="${pigsCanFly}">
<img src="/images/flyingPig.jpg" />
</c:if>

Read and write attributes

Your controller can read and write attributes. Attributes are java objects that can be stored at one of four levels:

  • REQUEST - Attribute is available for the remainder of the request.
  • SESSION - Attribute is available as long as the current user is logged on.
  • PORTLET - Attribute is available as long as the current user is logged on. Value is only visible to requests from this portlet instance.
  • APPLICATION - Attribute is available as long as application continues to run. Value is visible to requests from all users.

Here is an example:

Integer currentDepth = (Integer) ctx.getAttribute("depth", AttributeLevel.SESSION);
ctx.setAttribute("nextDepth", currentDepth + 1, AttributeLevel.REQUEST);

Load and save preferences

Because portlet preferences are referenced so frequently in controllers, there is a built-in interface to load and save them. For example:

// get the user's preferences for this portlet instance
SkewedSessionsPreferences preferences = new SkewedSessionsPreferences();
preferences = ctx.loadPreferences("skewedSessions", preferences);

Load and save portlet configuration

The Portal Role Manager allows the administrator to configure portlet defaults for all users. Your portlet needs to provide the implementation of the configuration form. The loadPreferences and savePreferences methods are smart enough to know if they are being called from your configuration form or your user preferences form and automatically perform the correct action to load or save portlet default preferences or user preferences.

This means that you can usually re-use the same view and the same controller for both configuration and preferences.

Advanced Operations

The following examples illustrate the additional built-in capabilities of ViewpointController and ViewpointFormController classes that you may need for more complex portlets.

Get the request URL

If you need to know the URL that initiated the request that you are processing, you can get it with the getRequestURL method:

String url = ctx.getRequestURL();

Get the user's portal username

If you need to know the portal username (the name under which the user logs in to the Teradata Viewpoint portal), you can use getRemoteUser:

String username = ctx.getRemoteUser();

NOTE: This method only works in portlet requests, not in servlet requests.

Read and write cookie values

If you need to know the value of cookies that have been set in the browser, you can use getCookies to read them:

import javax.servlet.http.Cookie;
...
Cookie[] cookies = ctx.getCookies();

If you want to set a cookie value, you can use setCookie:

Cookie tabCookie = new Cookie("defaultTab", "2");
ctx.addCookie(tabCookie);

NOTE:  This method only works in servlet requests, not in portlet requests.

Implement multi-page portlets

Implementing a multi-page portlet (such as a portlet that supports drill-down from a summary page to a detail page) requires implementing multiple controller methods (typically one for each page). Let's start with a simple example: a portlet does not auto-refresh and has two pages. The first page displays data in a table and the second page displays data in a graph. We have a link in each page that points to the other page.

Teradata Viewpoint controllers automatically recognize a parameter named pageName and try to find a controller method with the same name. Also, you need to know that the default page name is summary. If there is not pageName parameter (as when the portlet is initially displayed on the page), then the summary method is invoked. So you would create your controller like this:

class TwoPageExampleController extends ViewpointControllerBase

// this is called when there is no pageName parameter
public void summary(ControllerContext ctx)
{
table(ctx);
}

// this is called when pageName = "table"
public void table(ControllerContext ctx)
{
ctx.setViewName("table");
// create view objects for table view
...
}

// this is called when pageName = "graph"
public void graph(ControllerContext ctx)
{
ctx.setViewName("graph");
// create view objects for graph view
...
}
}

Then, in the portlets-jsp directory, create the JSP files for the two views. Here is table.jsp:

...
<vp:TableWidget .../>
<portlet:renderURL var="graphURL">
<portlet:param name="pageName" value="graph"></portlet:param>
</portlet:renderURL>
<a href="${graphURL}">View as graph</a>
...

Here is graph.jsp:

...
<vp:GraphWidget .../>
<portlet:renderURL var="tableURL">
<portlet:param name="pageName" value="table"></portlet:param>
</portlet:renderURL>
<a href="${tableURL}">View as table</a>
...

Implement different content when portlet is maximized

The user has the option of maximizing your portlet so that it is the full width of the portal. You may want to take advantage of this to display additional data. For example, if you are displaying a graph, you might want to display twice as many data points. Or, if you are displaying a table, you might want to display additional columns. You can detect whether or not the portlet is maximized using the getWindowState method. Here is an example:

if (ctx.getWindowState().equals(WindowState.MAXIMIZED))
{
columns = Arrays.asList(preferences.getMaximizedSummaryColumns());
}
else
{
columns = Arrays.asList(preferences.getSummaryColumns());
}

Respond to a request using non-HTML content

Normally a response to a request returns HTML content. If you want to return a different type of content, you need to specify the mime-type of the content. The setContentType method allows you to do this. For example, if you want to return javascript, you add this method call to your controller:

ctx.setContentType("text/javascript")