Adding a Custom JSP Page in a Spring Web Flow¶
The flexibility of JasperReports Server lets you create your own JSP pages that integrate into the UI. In order for the SiteMesh decorator to process a custom JSP page, you must integrate it into the Spring Web Flow framework. A flow is a sequence of related pages for which you define states and transitions in relation to your own business logic. This example shows how to add a single page, but you could integrate a series of pages and the navigation among them.
To further integrate your pages with the server, you should use the CSS building blocks provided in themes to replicate the menu and column layout of the server. You can then apply the default theme of the UI or design your own style in a custom theme.
Spring Web Flow relies on the Spring MVC (Model, View, and Controller) module to implement the web interface, where the controller is a Java class. As a result, adding business logic to a web flow involves creating Java methods to implement the logic. In general, the server UI contains most of the functionality in action class code that can be associated with one or more JSP pages. The JSP files have minimal functionality because JSP code logic can become very cluttered and hard to follow. The action classes are pure Java and easier to organize. In this example, the Java method simply returns success whenever it's invoked.
For more information, refer to the Spring documentation for flows and MVC.
This example requires you to work with the JasperReports Server source code, as explained in Working With Source Code Files.
This example is divided into several tasks:
- Adding a custom JSP file integrated into the server as a web flow.
- Creating an action and adding it to the web flow.
- Adding the web flow to a menu.
Example of adding a custom JSP file integrated into the server as a web flow
-
Create a subdirectory named sampleFlow for the JSP files in your flow module in
<js-src>/jasperserver-pro/jasperserver-war/src/main/webapp/WEB-INF/jsp/. For example:cd <js-src>/jasperserver-pro/jasperserver-war/src/main/webapp/WEB-INF/jsp/mkdir sampleFlow -
Create the following JSP file and save it as
sampleView.jspin<js-src>/jasperserver-pro/jasperserver-war/src/main/webapp/WEB-INF/jsp/sampleFlow:<html> <head><title>Sample Page</title> </head> <body class="oneColumn primary column"> <h1 class="textAccent">Hello World!</h1> </body> </html>Note
Design the layout of your custom content based on the UI components in the server. The UI components are defined in the CSS files in the
<js-src>/jasperserver/jasperserver-war/src/main/webapp/themes/default/directory.This example uses a one-column layout and the
textAccentfont. -
Create the following XML file with a
flowcontainer element and an emptyview-stateelement. In a later step, you will add an action state:<?xml version="1.0" encoding="UTF-8"?> <flow xmlns="http://www.springframework.org/schema/webflow" xmlns:ns0="http://www.w3.org/2001/XMLSchema-instance" ns0:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd" start-state="sampleView"> <view-state id="sampleView" view="modules/sampleFlow/sampleView"> </view-state> <end-state id="done"/> </flow> -
Name the file
docSampleFlow.xmland save it in the<js-src>/jasperserver/jasperserver-war/src/main/webapp/WEB-INF/flowsdirectory.Example of setting flow permissions
-
Set permissions for your flow:
-
Edit the file
<js-src>/jasperserver/common/shared-config/applicationContext-security.xml. -
Locate the
flowVoterbean. This bean sets the permissions for flows. -
Add a line for your flow and set the permissions to
ROLE_ADMINISTRATOR.<bean id="flowVoter" class="com.jaspersoft.jasperserver.api.security.FlowRoleAccessVoter"> <property name="flowAccessAttribute" value="FLOW_ACCESS"/> <property name="flowDefinitionSource"> <value> repoAdminFlow=ROLE_ADMINISTRATOR ... docSampleFlow=ROLE_ADMINISTRATOR <!--objectPermissionToUserFlow=ROLE_ADMINISTRATOR--> searchFlow=ROLE_USER,ROLE_ADMINISTRATOR *=ROLE_USER,ROLE_ADMINISTRATOR </value> </property> </bean>Note
The final entry in the
flowVoterbean,*=ROLE_USER,ROLE_ADMINISTRATOR, sets the default permissions for all flows not specified directly. If you don't create an entry for your flow, these permissions apply.
Example of creating an action and adding it to the flow
-
-
Create a java class that defines the controller in the Spring MVC framework. In this example, this file always returns
successwhen invoked.-
Go to the
<js-src>/jasperserver/jasperserver-war-jar/src/main/java/com/jaspersoft/ji/war/directory. This is where the JasperReports Server source looks for java files used by the Spring web flow framework. -
Create a subdirectory for your flow package,
<js-src>/jasperserver/jasperserver-war-jar/src/main/java/com/jaspersoft/ji/war/sampleFlow/ -
Create a java file and save it as
<js-src>/jasperserver/jasperserver-war-jar/src/main/java/com/jaspersoft/ji/war/sampleFlow/SampleAction.javapackage com.jaspersoft.ji.war.sampleFlow; import org.springframework.webflow.action.MultiAction; import org.springframework.webflow.execution.Event; import org.springframework.webflow.execution.RequestContext; public class SampleAction extends MultiAction { public Event start(RequestContext context) throws Exception{ // implement some logic return success(); } }
-
-
Create a bean for the
SampleActionclass that you created. To this, create the following file and save it as<js-src>/jasperserver/jasperserver-war/src/main/webapp/WEB-INF/flows/docSampleBeans.xml:<beans xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd"> <bean id="sampleAction" class="com.jaspersoft.ji.war.sampleFlow.SampleAction"> </bean> </beans> -
Modify
docSampleFlow.xmlto start with an action state that calls theSampleActionclass you created:-
Change the start-state to
start. -
Create an action state
startthat callssampleActionand transitions to the view-statesampleViewon success. Insert this state beforesampleView. -
At the end of the flow, import
docSampleBeans.xmlas a resource.<?xml version="1.0" encoding="UTF-8"?> <flow xmlns="http://www.springframework.org/schema/webflow" xmlns:ns0="http://www.w3.org/2001/XMLSchema-instance" ns0:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd" start-state="start"> <action-state id="start"> <evaluate expression="sampleAction"/> <transition on="success" to="sampleView"/> </action-state> <view-state id="sampleView" view="modules/sampleFlow/sampleView"> </view-state> <view-state id="errorPage" view="modules/system/errorPage"/> <end-state id="done"/> <global-transitions> <transition on="backFromErrorPage" to="backFromError"/> <transition on-exception="java.lang.Throwable" to="errorPage"/> </global-transitions> <!-- end exceptions handling --> <bean-import resource="docSampleBeans.xml"/> </flow>
-
-
Add error handling as shown in the code sample above:
- Add a view-state
errorPageto your flow. In this example, you add it immediately aftersampleView. - Add a global-transitions state that handles Java exceptions by displaying
errorPage.
- Add a view-state
-
(Optional) If you want, you can rebuild the source code and view your page:
-
Rebuild the source code and redeploy the web application according to the instructions in the Building JasperReports Server section in the JasperReports Server Source Build Guide within your distribution. See Working With Source Code Files for an overview of this process.
-
Log in to your JasperReports Server.
-
Navigate to the page you created using this URL:
http://<hostname>:<port>/jasperserver-pro/flow.html?_flowId=docSampleFlowExample:
http://localhost:8080/jasperserver-pro/flow.html?_flowId=docSampleFlow
Example of creating a menu item to call your flow
Now you can add a menu item to call the flow you created. The process is similar to the one described in Adding an Item to the Main Menu, but because you're modifying the source, the file locations are different in this example.
Note
Because the commercial source code includes the community source, most modifications to the menu are made in the community source files.
-
-
Edit the file
<js-src>/jasperserver/common/shared-config/actionModel-navigation.xml. Locate theactionModelfor the View menu in the file. -
Add an
optiontag for the menu item, as shown in the following code sample. Theoptiontag has attributes to specify the label key and the name of the action to perform.<!--context for view option on primary menu--> <context name="main_view_mutton" test="!banUserRole"> <selectAction labelKey="menu.repository"> ... <condition test="checkAuthenticationRoles" testArgs="ROLE_ADMINISTRATOR"> <separator/> <option labelKey="menu.samples" clientTest="!isIPad" action="primaryNavModule.navigationOption" actionArgs="samples"/> </condition> <separator/> <condition test="checkAuthenticationRoles" testArgs="ROLE_ADMINISTRATOR"><option labelKey="NAV_028_DOC_SAMPLE" action="primaryNavModule.navigationOption"actionArgs="docSample"/></condition> </selectAction> </context> -
Add a
conditiontag for the menu item, as shown in the code sample above.Note
The condition tag prevents the menu item from being displayed to users without the specified permissions. However, to ensure the flow can't be accessed via URL, set flow permissions as shown in step 5.
-
Add the label key to the file
<js-src>/jasperserver-pro/jasperserver-war/src/main/webapp/WEB-INF/bundles/pro_nav_messages.properties, as shown in the following code sample: -
Create a working directory where you can edit and build JavaScript source code, as described in 1.0.1, “Customizing JavaScript Files,” on page 1.
-
In a text editor, open your working copy of the file
<js-src>/jasperserver/jasperserver-war/src/main/webapp/scripts/actionModel.primaryNavigation.js, and locate thenavigationPathssection. Add a line that specifies the accounts flow to begin when the menu item is selected. If you are adding your line at the end of the section, make sure to add a comma to the previous line. -
Create a file "
sampleFlowMain.js" at "jasperserver-ui/ce/jrs-ui/src/sampleFlow/sampleFlowMain.js", as shown in the following code sample: -
Add the following file entry to "
jasperserver-ui/ce/jrs-ui/webpack.config.js" -
(For JasperReports Server Professional edition only) Create a file "
sampleFlowMain.js" at "jasperserver-ui/pro/jrs-ui-pro/src/sampleFlow/sampleFlowMain.js", as shown in the following code sample:import 'jrs-ui/src/util/webpackPublicPathSetup'; const importStartup = import('jrs-ui/src/util/mainPagesStartup') const importCommonModule = () => import('../commons/commons.main') importStartup.then(({default: startup}) => startup({ importCommonModule }))Then update the JSP file mentioned in step 2 to:
<html> <head><title>Sample Page</title> <script type="text/javascript" src="${pageContext.request.contextPath}/runtime/${jsOptimizationProperties.runtimeHash}/JavaScriptServlet"></script> <script src="${pageContext.request.contextPath}/runtime/${jsOptimizationProperties.runtimeHash}/scripts/sampleFlow/sampleFlowMain.js" defer></script> </head> <body class="oneColumn primary column"> <h1 class="textAccent">Hello World!</h1> </body> </html>Compile code and view changes
-
Build the JavaScript source code in your working directory and copy the output back to JasperReports Server as described in 1.0.1, “Customizing JavaScript Files,” on page 1.
-
Rebuild the source code and redeploy the web application according to the instructions in the JasperReports Server Source Build Guide within your distribution. See Working With Source Code Files for an overview of this process.
-
Log in as an administrator. If your changes were successful, this example displays the *View > MyCompany Accounts* menu item to users, and selecting it displays the custom page defined in the
sampleView.jspfile: -
The page uses the single column layout and the orange text is the
textAccentclass in CSS.