63
Version 9.0 Getting Started with Building Blocks™ ©2008 Blackboard Inc. Proprietary and Confidential

Blackboard Learn Building Blocks Getting Started Guide for Release 9

Embed Size (px)

Citation preview

Page 1: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Version 9.0

Getting Started with Building Blocks™

©2008 Blackboard Inc. Proprietary and Confidential

Page 2: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Publication Date: December, 2008

Worldwide Headquarters International Headquarters

Blackboard Inc. Blackboard International B.V.

650 Massachusetts Avenue N.W. Sixth Floor Washington, DC 20001-3796

Dam 27 2nd Floor 1012 JS Amsterdam The Netherlands

800-424-9299 toll free US & Canada

+1-202-463-4860 telephone +31 20 5206884 (NL) telephone

+1-202-463-4863 facsimile +31 20 5206885 (NL) facsimile

www.blackboard.com global.blackboard.com

Blackboard, the Blackboard logo, Blackboard Academic Suite, Blackboard Learning System, Blackboard Learning System ML, Blackboard Community System, Blackboard Transaction System, Building Blocks, and Bringing Education Online are either registered trademarks or trademarks of Blackboard Inc. in the United States and/or other countries. Microsoft and Windows are registered trademarks of Microsoft Corporation in the United States and/or other countries. Java is a registered trademark of Sun Microsystems, Inc. in the United States and/or other countries. Macromedia, Authorware and Shockwave are either registered trademarks or trademarks of Macromedia, Inc. in the United States and/or other countries. Real Player and Real Audio Movie are trademarks of RealNetworks in the United States and/or other countries. Adobe and Acrobat Reader are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States and/or other countries. Macintosh and QuickTime are registered trademarks of Apple Computer, Inc. in the United States and/or other countries. WebEQ is a trademark of Design Science, Inc. in the United States and/or other countries. JSpell is a trademark of The Solution Café in the United States and/or other countries. Other product and company names mentioned herein may be the trademarks of their respective owners. U.S. Patent No. 6,988,138. Patents pending.

No part of the contents of this manual may be reproduced or transmitted in any form or by any means without the written permission of the publisher, Blackboard Inc.

©2008 Blackboard Inc. Proprietary and Confidential Page 2

Page 3: Blackboard Learn Building Blocks Getting Started Guide for Release 9

About the Author

Mark O’Neil is the Academic Applications Developer and Curricular Systems Engineer for Academic Computing, Dartmouth College. He designs (and sometimes writes!) software for use in the curriculum and oversees the College's installation of the Blackboard Academic Suite. He has designed and written an XML driven Snapshot tool, PhotoRoster and User Management tools, Custom My Courses Module, the Campus Bb Custom Authentication implementation, and is currently completing a Bb Administrator GUI. Mark also serves on the Bb-OpenSource steering committee. When not at work you will find him shaping steel in his blacksmith shop, on a remote New Hampshire road riding his '41 Indian 741b motorcycle, or enjoying life with his wife and daughter.

A thank you from the author: I would like to thank everyone at Blackboard for their assistance and encouragement throughout. A huge thank you and hugs for Christie and Libby! Without their support and patience I would not have been able to write this guide.

©2008 Blackboard Inc. Proprietary and Confidential Page 3

Page 4: Blackboard Learn Building Blocks Getting Started Guide for Release 9

About the Author................................................................................3 Preface ............................................................................................6 

Why Building Blocks? ................................................................................... 6 What's Inside............................................................................................. 6 What You'll Need........................................................................................ 6 Using Code Examples................................................................................... 6 We Would Like to Hear from You .................................................................... 7 

Chapter 1: Setting Up your Development Environment ....................................8 Local Development or Remote Development? ............................................8 The Development Environment ..............................................................8 Step 1 — Install Java and Tomcat ............................................................9 

Download Java and Tomcat ........................................................................... 9 Additional Resources .................................................................................. 10 Install Java.............................................................................................. 10 Install Tomcat .......................................................................................... 10 Test Tomcat ............................................................................................ 11 

Step 2 — Install and Configure Eclipse .................................................... 14 Eclipse ................................................................................................... 14 MyEclipse Workbench ................................................................................. 14 

Step 3 — Test the Development Environment........................................... 15 Create a MyEclipse Web Project .................................................................... 15 Create the Project Resources........................................................................ 15 Configure MyEclipse to work with the local version of Tomcat ................................ 16 Deploy the HelloWorld Webapp ..................................................................... 17 Start Tomcat and Test the HelloWorld Web Project............................................. 19 

Step 4 — Setup the Blackboard Development Server Debugger ..................... 20 Server Security ......................................................................................... 21 

Chapter 2: Your First Building Block ......................................................... 22 Components of a Building Block............................................................ 22 The Tag Libraries.............................................................................. 23 The Bb-manifest ............................................................................... 23 HelloWorld: From Webapp to Building Block ............................................ 25 

Create the HelloWorld bb-manifest ................................................................ 25 Create the Building Blocks Package ................................................................ 26 Apply Blackboard UI Elements to the HelloWorld Building Block .............................. 27 

Identify Users .................................................................................. 30 Add the Blackboard jars .............................................................................. 30 HelloWorld: Hello who? ............................................................................... 31 Data Objects............................................................................................ 32 Persistence Objects ................................................................................... 32 Access User Information .............................................................................. 32 The Building Block Project Template............................................................... 34 

Identify Courses ............................................................................... 35 HelloWorld_2: Where are we? ....................................................................... 35 Access Course Information ........................................................................... 35 DbLoaders: Lightweight and Heavyweight......................................................... 38 

Identify User Memberships .................................................................. 39 HelloWorld _3 - Why am I here? ..................................................................... 39 Accessing membership information................................................................. 39 Display the course membership list................................................................. 43 

©2008 Blackboard Inc. Proprietary and Confidential Page 4

Page 5: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Chapter 3: Photo Roster Building Block ..................................................... 48 The (Open Source) Photo Roster........................................................... 48 Best Practices in Practice.................................................................... 48 

Define the Project Scope and Requirements ...................................................... 48 Design the Extension: The User Interface and Technical Specifications...................... 49 Design, Define, Develop, Deploy, Rinse, Repeat until done .................................... 52 

Set up the Photo Roster project ........................................................... 52 Photo Roster Bb-manifest Requirements........................................................... 52 

The Photo Roster Main Page ................................................................ 53 Photo Roster Classes.......................................................................... 56 

The PhotoRoster Class ................................................................................ 56 The Photo Roster Uploader Class.................................................................... 56 The PHOTO ROSTER Files Class ...................................................................... 57 

Development Notes ........................................................................... 57 Appendix A: Alternative Deployment Options.............................................. 61 

Deploy via Remote Deployment ............................................................ 61 Deployment and the bb-manifest .......................................................... 61 

Appendix B: List of Resources ................................................................. 62 Additional Resources from Blackboard ................................................... 62 Community Resources........................................................................ 63 Technical Resources .......................................................................... 63 

©2008 Blackboard Inc. Proprietary and Confidential Page 5

Page 6: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Preface

The Blackboard Building Blocks Getting Started Guide is written for programmers and administrators who wish to begin writing extensions for the Blackboard Academic Suite™. Extensions, referred to as Building Blocks, add customized features and functions to the Academic Blackboard Suite. Building Blocks are written in Java and use the Building Block APIs to tightly integrate with the Blackboard Academic Suite. The Building Block APIs provide you, the developer, with the means to shape and define your institution's Blackboard experience.

This guide will teach you how to develop innovative ideas into your own Building Blocks, working up from the basics. This guide uses examples presented in sequence to introduce you to the development environment and demonstrate how to create, debug, and deploy Building Blocks extensions.

Why Building Blocks?

The Building Blocks APIs open the Blackboard Academic Suite to customized solutions that provide new features, new tools, or access to other campus resources. Using Building Blocks provides you with the foundation for a variety of applications. You can make new content types, access remote data, create tools that interact with your Student Information System, or add objects to the gradebook—you are limited only by your imagination. Building Blocks extensions, because they are based on a common platform, can be shared though out the Blackboard community. Building Blocks from other institutions are available from the Building Blocks catalog available at http://www.blackboard.com/extend/dev/index.aspx. You can also share your innovations with the Blackboard community by posting your Building Blocks to the Building Blocks catalog.

What's Inside

This guide starts with an explanation of the development environment. It then presents demonstrative code samples, culminating with an example of a full Building Blocks extension that uses many of the principles presented in the text. Here is an outline of this guide:

Chapter Description

Setup Your Development Environment This chapter covers installation and configuration of the development environment. The examples in this chapter use an open source Integrated Development Environment (IDE) to code, test, and debug Building Blocks.

Your First Building Block This chapter walks you through the process of creating and deploying a simple Building Block.

Photo Roster Building Block This chapter leads you through an exercise to create a fully-formed Building Block.

What You'll Need

The software used for the projects in this book (with the exception of your developer or test installation of the Blackboard Academic Suite) is available for free or at low cost for individuals. Java development is done through Eclipse™, a cross-platform, integrated development environment (IDE) and MyEclipse™ Enterprise Workbench a set of tools for development and support that plugs into Eclipse. While not free, MyEclipse Workbench is quite affordable given what it offers in time savings and package maintenance.

For those users that wish to use a completely open source development environment, Lomboz (http://www.objectlearn.com/index.jsp) and Sysdeo (http://www.sysdeo.com) are alternatives to MyEclipse Workbench, however, the examples in this guide do not cover these tools.

Using Code Examples

The best way to get started writing Building Blocks extensions is practice with real world examples and code. The code used in this guide is available in separate examples that can be modified and used to build

©2008 Blackboard Inc. Proprietary and Confidential Page 6

Page 7: Blackboard Learn Building Blocks Getting Started Guide for Release 9

your own Building Blocks. The examples can be downloaded with this guide from the Blackboard Developer Network Web site (http://www.blackboard.com/extend/dev/BbDN.htm) or Behind the Blackboard (http://www.blackboard.com/support/).

If you download this guide from one of the above Web sites, it will be packaged with a text file that includes all code samples used in the document.

We Would Like to Hear from You

Please address comments and questions concerning this guide to your Blackboard Account Manager or Support Manager.

To comment or ask technical questions about Building Blocks, send email to:

[email protected]

or join the Open Source Building Blocks LISTSERV at:

http://www.bb-opensource.org/

©2008 Blackboard Inc. Proprietary and Confidential Page 7

Page 8: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Chapter 1: Setting Up your Development Environment

This chapter reviews how to create a development environment for Building Blocks. This chapter includes the following topics:

Topic Description

Install Java and Tomcat This topic explains how to install the required versions of Java and Tomcat on your local machine.

Install and Configure Eclipse This topic provides instructions for downloading and configuring the IDE.

Test the Development Environment This topic walks through the steps for testing the IDE.

Setup the Blackboard Development Server Debugger

This topic explains how to configure your development environment to debug against an implementation of the Blackboard Academic Suite.

Local Development or Remote Development?

It is possible to write and test Building Blocks directly on a Blackboard Academic Suite server using nothing more than a text editor and the versions of Java and Tomcat used to run the Academic Suite. For most developers, the optimal development environment is a local environment that can connect to a Blackboard Academic Suite server for testing and debugging. This chapter focuses on setting up the local development environment and connecting to an existing Blackboard Academic Suite implementation for testing and debugging.

The Development Environment

The Building Block APIs do not require any specific development platform. You are free to use any operating system and any development environment. The instructions in this guide work equally well for Windows, Mac OS X, and Linux. The examples use Eclipse 3.1 as the primary IDE. Java, Tomcat, and MyEclipse (or the Sysdeo Tomcat and the Lomboz J2SE development plug-ins for Eclipse) complete the development environment.

©2008 Blackboard Inc. Proprietary and Confidential Page 8

Page 9: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Step 1 — Install Java and Tomcat

Download Java and Tomcat

Java and Tomcat installers and installation instructions are available online for Mac OS X, Microsoft Windows XP, and Linux. Blackboard Academic Suite Release 7 uses J2SE 1.5.x. Below are links for installers:

OS Java

OS X Provided with OSX or downloaded directly from Apple at: http://www.apple.com/macosx/features/java/

The environment will require the Apple Developer tools, These can be found at:

http://developer.apple.com/

XP http://java.sun.com/j2se/1.5.0/download.jsp

select the JDK link and follow the Links to the Windows installer (online or offline). If you choose the Online Install make certain to do a 'full' install.

Linux http://java.sun.com/j2se/1.5.0/download.jsp

Select the JDK link and follow the Links to the Linux installer. If you choose the Online Install make certain to do a 'full' install.

Table 1.1 Java installers.

OS Tomcat

OS X http://tomcat.apache.org/download-55.cgi Select the tar.gz link under binary distributions.

XP http://tomcat.apache.org/download-55.cgi Select the Windows Executable link under binary distributions.

Linux http://tomcat.apache.org/download-55.cgi Select the tar.gz link under binary distributions.

Table 1.2 Tomcat installers.

Download the Java SDK and Tomcat installers for your operating system. If using OS X you do not need to install Java, but make certain you have installed the Apple Developer Tools (http://developer.apple.com/).

©2008 Blackboard Inc. Proprietary and Confidential Page 9

Page 10: Blackboard Learn Building Blocks Getting Started Guide for Release 9

NOTE: These instructions assume that the Blackboard Academic Suite is not running on the local development environment. If it is, Java and Tomcat are already installed because they are required to run the Blackboard Academic Suite. Please see the Blackboard Academic Suite Setup Guide for information on using Java and Tomcat with the Blackboard Academic Suite.

Additional Resources

For more information about using Java and Tomcat please see:

OS Instructions/Documentation

OS X http://developer.apple.com/internet/java/tomcat1.html

http://mamamusings.net/archives/2004/04/28/installing_tomcat_5_on_os_x.php

http://tomcat.apache.org/tomcat-5.5-doc/index.html

XP http://www.coreservlets.com/Apache-Tomcat-Tutorial/

http://tomcat.apache.org/tomcat-5.5-doc/index.html

Linux http://www.linux-sxs.org/internet_serving/c140.html

http://tomcat.apache.org/tomcat-5.5-doc/index.html

Table 1.3: Java and Tomcat Instructions.

Install Java

Run the Java installer using the default options. If you are using OS X, Java is already installed.

Install Tomcat

For Windows, simply run the installer and accept the defaults.

For Linux and OS X un-tar the tar file you downloaded and follow the instructions for your operating system.

1. Extract the tomcat binaries into /usr/local

2. Create a symbolic link: OSX: ln -s /usr/local/jakarta-tomcat-5.5 /Library/Tomcat Linux: ln -s /usr/local/jakarta-tomcat-5.5 /usr/local/tomcat

©2008 Blackboard Inc. Proprietary and Confidential Page 10

Page 11: Blackboard Learn Building Blocks Getting Started Guide for Release 9

3. Make certain the files are executable: OSX: chmod 755 /Library/Tomcat/*.bat chmod 755 /Library/Tomcat/*.sh Linux: chmod 755 /usr/local/tomcat/*.bat chmod 755 /usr/local/tomcat/*.sh

4. Define JAVA_HOME (if it is not already defined): OSX: setenv JAVA_HOME /Library/Java/Home Linux: export JAVA_HOME=/usr/local/java

5. Define CATALINA_HOME (if it is not already defined): OSX: setenv CATALINA_HOME /Library/Tomcat Linux: export CATALINA_HOME=/usr/local/tomcat

6. Add tomcat bin to your PATH environment variable: OSX: setenv PATH $PATH;/Library/Tomcat/bin Linux: export PATH $PATH;/usr/local/tomcat/bin

Linux and OSX users may wish to add the above environment variables to their shell start up script (for example, .bashrc ) so that they are automatically set on opening new shell sessions.

Test Tomcat

You should now be able to start Tomcat by following the instructions below.

OS Instructions/Documentation

OS X Ensure that CATALINA_HOME and JAVA_HOME are correctly set. To do this, open a terminal and type the following: echo $CATALINA_HOME

echo $JAVA_HOME

If you get a blank line, or if the directory points anywhere besides where it is supposed to, you will have to correct these environment variables before continuing. If everything is set correctly, you can start Tomcat with the following command. $CATALINA_HOME/bin/startup.sh

XP Locate and open Tomcat5 procrun and click Start on the general tab.

©2008 Blackboard Inc. Proprietary and Confidential Page 11

Page 12: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Figure 1.1 Tomcat Properties

Linux Ensure that CATALINA_HOME and JAVA_HOME are correctly set. To do this, open a terminal and type the following: echo $CATALINA_HOME

echo $JAVA_HOME

If you get a blank line, or if the directory points anywhere besides where it is supposed to, you will have to correct these environment variables before continuing. If everything is set correctly, you can start Tomcat with the following command. $CATALINA_HOME/bin/startup.sh

Table 1.4 Starting Tomcat.

Once Tomcat is started, test Tomcat by opening a browser and loading http://localhost:8080. If successful, this will bring up the Tomcat 5 home page (see Figure 1.2). Next, review the Tomcat documentation listed in table 1.3 and familiarize yourself with the example servlets and JavaServer Pages samples.

©2008 Blackboard Inc. Proprietary and Confidential Page 12

Page 13: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Figure 1.2 Tomcat start up screen.

©2008 Blackboard Inc. Proprietary and Confidential Page 13

Page 14: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Step 2 — Install and Configure Eclipse

Editing and debugging will be done using Eclipse. MyEclipse provides the necessary tools for editing and debugging JSP code and interacting with the Tomcat debugger.

Eclipse

Eclipse can be downloaded from http://www.eclipse.org/. Eclipse is installed by expanding the downloaded archive to your applications directory.

The examples in this guide were done using Eclipse 3.1. While other versions of Eclipse should function similarly, be aware that there may be slight differences if you are using another version of Eclipse other than 3.1.

MyEclipse Workbench

My Eclipse Workbench is installed by downloading the installer archive for your operating system from http://www.MyEclipseIDE.com, expanding the downloaded archive, and running the installer.

Now that the components of the development environment are installed we can now test them by building a simple webapp.

©2008 Blackboard Inc. Proprietary and Confidential Page 14

Page 15: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Step 3 — Test the Development Environment

This topic introduces Eclipse and MyEclipse Workbench by showing you the steps necessary to create a Web project. To test the development environment, you will:

• Create a “HelloWorld” Web Project using Eclipse and MyEclipse

• Create a Java Servlet Page (JSP) using the JSP Wizard

• Edit the JSP using the JSP Editor

• Deploy and test the “HelloWorld” Web Project as a Web Application (webapp)

To test our development we will build a "Hello World” webapp. The webapp will consist of a JSP that calls a display class. It will run within the local tomcat institution and it will be debugged using the Eclipse and Tomcat debugger. It is outside the scope of this guide to provide a full tutorial on using Eclipse and the My Eclipse workbench, and running debugger sessions, but by working through the examples you will gain a basic understanding of these tools. For in-depth tutorials refer to the Eclipse and My Eclipse IDE websites.

Create a MyEclipse Web Project

1. Start Eclipse.

2. Open the new Web Project Wizard by selecting File > New > Project > MyEclipse > J2EE > Web Project

3. Enter HelloWorld into the Project Name field.

4. The defaults should be fine for the rest of the fields. Make certain that the Web root folder does not start with a '/'.

5. Select Finish. A dialog will appear asking if you wish to open the My Eclipse perspective for projects of this type; click Yes. If you click No, you will need to switch to the My Eclipse perspective manually for future Web Projects.

Create the Project Resources

Use the My Eclipse JSP Wizard to add the main JSP named "helloworld.jsp”

1. Right-click the WebRoot folder and select New > Other > J2EE > Web > JSP

2. Enter the following HelloWorld JSP details into the My Eclipse New JSP dialog (see Figure 1.3): File Path: /HelloWorld/WebRoot Filename: helloworld.jsp Template: Default JSP template

©2008 Blackboard Inc. Proprietary and Confidential Page 15

Page 16: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Figure 1.3:The My Eclipse new JSP dialog.

3. Select Finish to generate the helloworld.jsp. Verify that helloworld.jsp is located in the WebRoot folder.

Figure 1.4: Confirm that The new JSP is added to the project.

4. For quick reference, activate line numbering. To activate line numbering, right-click on the open helloworld.jsp window and select Preferences in the dialog, find and click Show line numbers and click OK. After line 27 “This is my JSP page. <br>” add “<%out.print("hello world"); %><br>”

5. The code should now look like:

<body> This is my JSP page. <br> <% out.print("hello world"); %><br> </body>

6. Save the file. Any errors will be detected by MyEclipse when it compiles the JSP.

Configure MyEclipse to work with the local version of Tomcat

Before the HelloWorld webapp can be deployed MyEclipse must be configured for the local Tomcat installation.

1. Set the Application Server for My Eclipse. Open Window > Preferences > MyEclipse.

2. When the preferences dialog opens click the '+' next to the MyEclipse label. Do the same for Application Servers and Tomcat 5.

3. Click Enable under Tomcat Server. Set the Tomcat directories to point to the correct Tomcat directories.

©2008 Blackboard Inc. Proprietary and Confidential Page 16

Page 17: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Windows: Tomcat Home Directory: C:\Program Files\Apache Software Foundation\Tomcat 5.0 Tomcat Base Directory: C:\Program Files\Apache Software Foundation\Tomcat 5.0 Tomcat Temp Directory: C:\Program Files\Apache Software Foundation\Tomcat 5.0\temp Mac OS X: Tomcat Home Directory: /library/tomcat Tomcat Base Directory: /library/tomcat Tomcat Temp Directory: /library/tomcat/temp Linux: Tomcat Home Directory: /usr/local/tomcat Tomcat Base Directory: /usr/local/tomcat Tomcat Temp Directory: . /usr/local/tomcat/temp

Figure 1.5: Tomcat settings in MyEclipse preferences for Windows..

4. If not previously set you also need to set the JDK for Tomcat. Click the JDK label under Tomcat 5 and then click Add on the JDK panel. Enter a name for the JDK in the JRE name field and the location of the J2SEE directory in the JRE Home directory. Although the field names include JRE, the path must point to the full SDK; a JRE will not work. Examples Windows: C:\Program Files\java\jdk1.5.0 Mac OS X: /library/java/jdk1.5.0 Linux: /usr/local/java/jdk1.5.0

Deploy the HelloWorld Webapp

Follow the steps below to deploy the HelloWorld webapp to the locally installed Tomcat 5 server.

1. Select the HelloWorld project. Then use the MyEclipse deploy icon on the toolbar (see Figure 1.6) to launch the Deployment Management Dialog.

Figure 1.6: MyEclipse deploy icon.

2. The first time the Deployment Management Dialog is opened it will look like the one in Figure 1.7.

©2008 Blackboard Inc. Proprietary and Confidential Page 17

Page 18: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Figure 1.7:MyEclipse Project Deployment Dialog. Currently there are no deployments specified for the HelloWorld project.

3. Click Add to add a deployment location.

4. Select Tomcat 5 for local deployment, confirm the path to your local Tomcat installation is correct, (see figure 1.8) and click Final.

Figure 1.8: MyEclipse New Deployment Dialog.

5. After adding a deployment server the project is deployed (see figure 1.9).This process copies the HelloWorld project files to a directory under the Web Root of the chosen deployment server. Before closing the deployment manager dialog note that the Deployment Status has been updated. MyEclipse updates the deployment with each saved file.

©2008 Blackboard Inc. Proprietary and Confidential Page 18

Page 19: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Figure 1.9: MyEclipse Deployment Management Dialog showing selected deployment for the HelloWorld project.

Start Tomcat and Test the HelloWorld Web Project

In order to take advantage of the JSP debugging features of MyEclipse, a debug enabled version of Tomcat must be used as the webapp container. My Eclipse provides the means for starting and stopping Tomcat. Select Tomcat > Start from the MyEclipse Server toolbar (see Figure 1.10). Tomcat's startup progress can be monitored in the Eclipse console. When it has completed you will see a message in the console similar to “INFO: Server startup in 15953 ms”.

Figure 1.10: MyEclipse deploy icon.

Open a Web browser to the URL: http://localhost:8080/HelloWorld/helloworld.jsp. It may take several seconds to open this page as Tomcat must first compile the helloworld.jsp page before it can be displayed. The browser window contents should be similar to that shown in figure 1.11.

Figure 1.11: Localhost delivery of HelloWorld

Eclipse includes a built-in Web Browser so you do not have to leave the environment to test in a browser. The built-in browser is accessed using the globe next to the MyEclipse Application Servers icon that is used to start and stop the local Tomcat service.

©2008 Blackboard Inc. Proprietary and Confidential Page 19

Page 20: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Step 4 — Setup the Blackboard Development Server Debugger

When testing the development environment you created the HelloWorld Webapp and then tested and deployed it against a local version of Tomcat. Debugging Building Blocks involved connecting to the Blackboard Academic Suite implementation and testing against the version of Tomcat used to support the Blackboard Academic Suite. Therefore, the Tomcat server running on the Blackboard Academic Suite test server must be configured to support debugging. This is done by changing the Blackboard application server's Tomcat startup file to enable debugging. Open the Blackboard directory on the application server and open the following file in an editor:

• Warning: These changes should only be made to a test or development implementation of the Blackboard Academic Suite. Do not make these changes on an implementation that is in production.

Windows

\blackboard\apps\tomcat\bin\blackboard-tomcat.bat

After opening the file, change the following arguments:

Change the arguments from:

# Blackboard-specific setup

JAVA_OPTS="$JAVA_OPTS -server"

JAVA_OPTS="$JAVA_OPTS -Xms32m -Xmx1024m"

to:

# Blackboard-specific setup

JAVA_OPTS="$JAVA_OPTS -server"

JAVA_OPTS="$JAVA_OPTS -Xms32m -Xmx1024m"

JAVA_OPTS="$JAVA_OPTS -Xdebug -Xrunjdp¬ :server=y,transport=dt_shmem,address=4142,suspend=n

The address variable may be different depending on the server settings. Check with the server administrator and make sure that the address is accessible through any firewalls.

UNIX

/blackboard/apps/tomcat/bin/blackboard-tomcat.sh

Change the arguments from:

# Blackboard-specific setup

JAVA_OPTS="$JAVA_OPTS -server"

JAVA_OPTS="$JAVA_OPTS -Xms32m -Xmx1024m"

(on linux)

to:

# Blackboard-specific setup

JAVA_OPTS="$JAVA_OPTS -server"

©2008 Blackboard Inc. Proprietary and Confidential Page 20

Page 21: Blackboard Learn Building Blocks Getting Started Guide for Release 9

JAVA_OPTS="$JAVA_OPTS -Xms32m -Xmx1024m"

JAVA_OPTS="$JAVA_OPTS -Xdebug -Xrunjdp¬ :server=y,transport=dt_socket,address=4142,suspend=n

The address variable may be different depending on the server settings. Check with the server administrator and make sure that the address is accessible through any firewalls.

The table below defines the arguments that are changed when configuring Tomcat for debugging.

Argument Definition

-Xdebug Starts the JVM in debug mode and listens for debugging connections.

-Xrunjdwp Provides information on how to connect for remote debugging.

server= Specifies whether to start in server mode (y) or to go out looking for a connection.

transport= Specifies whether to use sockets (unix) or shared memory (Windows).

address= Identifies the port to connect to or the shared memory address to use

suspend= Specifies whether or not to launch without waiting for the debugger.

Table 1.5: Tomcat Debugging Arguments.

Server Security

The significant difference between remote and local Blackboard installations is with the deployment issues that may arise due to remote server security. In today's world of server attacks many system administrators are justifiably concerned when it comes to opening access to their server. Given firewalls, allowed hosts, lack of FTP services, and other obstacles, accessing a server can be downright troublesome. One solution to this problem is provided by the Eclipse plug-in Deployer. Deployer enables transfer of resources to the remote server over ssh. The Developer must either own the files being written to on the remote server or be in a group that has read and write permissions on the files being deployed. The group approach is most advantageous when there are several developers working on projects simultaneously.

©2008 Blackboard Inc. Proprietary and Confidential Page 21

Page 22: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Chapter 2: Your First Building Block

The HelloWorld webapp you wrote in the previous chapter is going to serve as the basis for the development of your first Building Block. Building Blocks are based on the standard Web Application architecture, but have a couple additional requirements for deployment in the Blackboard Academic Suite that we will explain here.

Topic Description

Components of a Building Block This topic explains the parts that make up a Building Block.

HelloWorld: From Webapp to Building Block

This topic applies the structure and missing pieces to turn the HelloWorld Webapp into a Building Block.

Identify Users This topic explains how to use the Building Blocks APIs to identify users as part of a Building Block.

Identify Courses This topic explains how to use the Building Blocks APIs to identify courses as part of a Building Block.

Identify Memberships This topic explains how to use the Building Blocks APIs to identify memberships as part of a Building Block. Membership defines the relationship between a user and a course.

Components of a Building Block

A Building Block needs to provide information so that Blackboard can determine how to properly deploy the extension. This information is provided through a manifest. This manifest, a file named bb-manifest.xml, identifies the Building Block to the Blackboard Academic Suite.

Additionally, Building Blocks benefit from the use of the Building Block Tag Library. The Tag Libraries define the appearance of user interface components such as buttons, links, titles, and fields. Converting our original HelloWorld project into a Building Block is easy. To do so, we need only to add the Blackboard Tag Libraries and the bb-manifest to the project and edit the bb-manifest to represent the HelloWorld Building Block.

©2008 Blackboard Inc. Proprietary and Confidential Page 22

Page 23: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Figure 2.1:Comparing the standard HelloWorld web application (left) structure to the HelloWorld Building Block (right). Note the addition of the file Bb-manifest.xml and the tag libraries to the HelloWorld Building Block.

The Tag Libraries

One of the main features of JavaServer Pages technology is the separation of content presentation from the middle and backend tiers that manipulate or generate the content. JSP enables this through actions. The JSP 1.1 specification supports the development of resusable modules called custom actions. This is in addition to the six standard actions of the specification. JSP pages use custom tags to invoke these custom actions. The Blackboard Tag Libraries are a collection of custom tags developed by Blackboard to facilitate the presentation of content by Building Blocks. This allows developers to develop tools that integrate seamlessly with the Blackboard Academic Suite, both in function and in appearance.

To add the Blackboard Tag Libraries to the HelloWorld project first download the Tag Libraries. Follow the steps below to add the Tag Libraries:

1. Copy the taglibs directory to your Eclipse workspace.

2. Start Eclipse.

3. Open the HelloWorld project and highlight the WEB-INF folder.

4. Click File > New > Folder to create a new folder. Name the new file config.

5. Highlight the config folder you just created and follow the same process to create a folder inside the config folder named taglibs.

6. Highlight the taglibs folder and click File > New > Import. From the Import dialog box select File System and click Next.

7. Browse to your Eclipse workspace, select the taglibs directory copied in step 1, and click Finish. Your HelloWorld project should now look like the one shown in the right-half of figure 2.1.

For more information on the elements included in the Tag Libraries please see the Building Blocks TLD. The TLD is available as part of the Building Blocks SDK.

The Bb-manifest

The bb-manifest is an xml file that presents important information about the Building Block to the Blackboard Academic Suite including: the type of extension, where in the GUI the Building Block is accessed by users, Blackboard permissions, and any security permissions necessary for the Building Block to work. A bb-manifest.xml file should be created in the WebRoot/WEB-INF folder of the project. A sample bb-manifest file may be found in the code samples attached to this guide. A detailed explanation of the Building Block

©2008 Blackboard Inc. Proprietary and Confidential Page 23

Page 24: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Manifest and its XML elements can be found in the Building Blocks Developer Guide. Take a look at the manifest for the HelloWorld Building Block: <?xml version="1.0" encoding="UTF-8"?>

<manifest>

<plugin>

<name value="Getting Started Guide: HelloWorld"/>

<description value="HelloWorld Building Block from the Getting Started Guide"/>

<handle value="HelloWorld"/>

<version value="1.0.0"/>

<requires>

<bbversion value="6.2.3"/>

</requires>

<vendor>

<id value="BGSG"/>

<name value="Blackboard Building Blocks Getting Started Guide"/>

<url value="http://www.blackboard.com/buildingblocks/gettingstartedguide"/>

<description value="Getting Started Guide v1.0 02.14.06"/>

</vendor>

<http-actions>

<config value=""/>

<remove value=""/>

</http-actions>

<application-defs>

<application

handle="HelloWorld"

type="course_tool"

name="Getting Started Guide: HelloWorld">

<description lang="en_US">

HelloWorld Building Block example from the Getting Started Guide

</description>

<links>

<link>

<type value="course_tool"/>

<name value="Getting Started Guide: HelloWorld"/>

<url value="helloworld.jsp"/>

<description value="Getting Started Guide: HelloWorld starting point."/>

</link>

</links>

</application>

</application-defs>

<permissions>

<permission type="attribute" name="user.personalinfo" actions="get" />

<permission type="attribute" name="Group" actions="get"/>

©2008 Blackboard Inc. Proprietary and Confidential Page 24

Page 25: Blackboard Learn Building Blocks Getting Started Guide for Release 9

<permission type="attribute" name="GroupMembership" actions="get"/>

</permissions>

</plugin>

</manifest>

HelloWorld: From Webapp to Building Block

Creating a Building Block from the HelloWorld webapp is relatively easy because the code for the task the Building Block is to perform, display the text, “Hello World!” on the screen, is already written. Turning the webapp into a Building Block requires you to complete the following steps:

• Create the manifest

• Add the Tag Libraries

• Export the .WAR File

• Load the Building Block into the Blackboard Academic Suite

Create the HelloWorld bb-manifest

The HelloWorld bb-manifest is a well-formed XML 1.0 document consisting of elements and attributes that describe the HelloWorld Building Block. The file breaks down as follows:

Lines 1-3 identify the document and open the main element tags. 01 | <?xml version="1.0" encoding="UTF-8"?>

02 | <manifest>

03 | <plugin>

Lines 4 and 5 provide the name and description. 04 | <name value="Getting Started Guide: HelloWorld"/>

05 | <description value="HelloWorld Building Block from the Getting Started Guide"/>

Line 6 provides the handle; this is used as part of the name for the directory that houses the extension on the Blackboard server. 06 | <handle value="HelloWorld"/>

Line 7 provides the extension versioning. 07 | <version value="1.0.0"/>

Lines 8-10 provide the minimum Blackboard version in which this extension may be used. 08 | <requires>

09 | <bbversion value="6.2.3"/>

10 | </requires>

Lines 11-16 provide the vender information displayed in the user interface. The id attribute is used as part of the name for the directory that houses the extension on the Blackboard server. 11 | <vendor>

12 | <id value="BGSG"/>

13 | <name value="Blackboard Building Blocks Getting Started Guide"/>

14 | <url value="http://www.blackboard.com/buildingblocks/gettingstartedguide"/>

15 | <description value="Getting Started Guide v1.0 02.14.06"/>

16 | </vendor>

Lines 17-20 provide the links to configure and remove pages. 17 | <http-actions>

18 | <config value="admin/configure.jsp"/>

©2008 Blackboard Inc. Proprietary and Confidential Page 25

Page 26: Blackboard Learn Building Blocks Getting Started Guide for Release 9

19 | </http-actions>

Lines 20-29 provide the application description. 20 | <application-defs>

21 | <application

22 | handle="HelloWorld"

23 | type="course"

24 | name="Getting Started Guide: HelloWorld">

25 | <description lang="en_US">

26 | HelloWorld Building Block example from the Getting Started Guide

27 | </description>

28 | </application>

29 | </application-defs>

Lines 30- 34 provide permissions for reading user, group, and group membership information 30 | <permissions>

31 | <permission type="attribute" name="user.personalinfo" actions="get" />

32 | <permission type="attribute" name="Group" actions="get"/>

33 | <permission type="attribute" name="GroupMembership" actions="get"/>

34 | </permissions>

Lines 35 and 36 close the plugin and manifest tags. 35 | </plugin> 36 | </manifest>

Create the Building Blocks Package

Add a bb-manifest.xml file to WEB-INF using the code above as an example or simply import the one provided with the supplemental materials to this guide. The HelloWorld project should now look like the one shown in figure 2.2. Now that the taglibs and manifest have been added to the project all that is necessary to create the Building Block is to export a war file (by selecting the project and clicking File > Export and select J2EE WAR file and following the steps as presented (save the file to your desktop). Now add the Building Block to Blackboard and make it available (see the Blackboard Administrators Guide to learn how to manage Building Blacks through the user interface). While this results in a functional page (go to the Course Tools area of a Course Control Panel and click Getting Started Guide: HelloWorld) it will look out of place (see figure 2.3) –this is where the tag library comes in.

Figure 2.2: HelloWorld with bb-manifest.xml and tag libraries

©2008 Blackboard Inc. Proprietary and Confidential Page 26

Page 27: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Figure 2.3: HelloWorld without the use of the Tag Library for GUI formatting.

Apply Blackboard UI Elements to the HelloWorld Building Block

To make HelloWorld appear seamless within the Blackboard Academic Suite use the tags from the Tag Libraries that were added to the project.

NOTE: Short of error references displayed in the Eclipse IDE local deployment of extensions using the Tag Libraries will result in a runtime error. Local deployment of extensions using the tag libraries is beyond the scope of this guide. For the purpose of this guide you must deploy Building Blocks that use the tag libraries to your development server for viewing and debugging.

Now, revisit the helloworld.jsp and add the tags necessary to make HelloWorld look like a part of the Blackboard Academic Suite. 01 | <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

02 | <%

03 | String path = request.getContextPath();

04 | String basePath =

request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

05 | %>

06 |

07 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

08 | <html>

09 | <head>

10 | <base href="<%=basePath%>">

11 |

12 | <title>My JSP 'helloworld.jsp' : starting page</title>

13 |

14 | <meta http-equiv="pragma" content="no-cache">

15 | <meta http-equiv="cache-control" content="no-cache">

16 | <meta http-equiv="expires" content="0">

17 | <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

18 | <meta http-equiv="description" content="This is my page">

19 |

20 | <!--

©2008 Blackboard Inc. Proprietary and Confidential Page 27

Page 28: Blackboard Learn Building Blocks Getting Started Guide for Release 9

21 | <link rel="stylesheet" type="text/css" href="styles.css">

22 | -->

23 | </head>

24 | <body>

25 | This is my JSP page. <br>

26 | <% out.print("hello world"); %><br>

27 | </body>

28 | </html>

To convert HelloWorld to a Building Block, first remove code that is not needed for the Building Block. Remove lines 2-24, and 27-28. Here is what helloworld.jsp should look like:

01 | <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

02 | This is my JSP page. <br>

03 | <% out.print("hello world"); %><br>

Now add the Bb tags:

After line 1 add: <%@ taglib uri="/bbUI" prefix="bbUI" %>

<%@ taglib uri="/bbData" prefix="bbData"%>

After line 3 add: <%

String iconUrl = "/images/ci/icons/bookopen_u.gif";

String page_title = "HelloWorld: helloworld.jsp";

%>

<bbData:context id="ctx"> <bbUI:docTemplate title="<%= page_title %>">

<!-- Start Breadcrumb Navigation -->

<bbUI:breadcrumbBar environment="CTRL_PANEL" handle="control_panel">

<bbUI:breadcrumb>Hello World</bbUI:breadcrumb>

</bbUI:breadcrumbBar>

<!-- End Breadcrumb Navigation -->

<bbUI:titleBar iconUrl="<%=iconUrl%>">

<%= page_title %>

</bbUI:titleBar>

After <% out.print("hello world"); %><br> add:

<form>

<bbUI:button type="FORM_ACTION" name="back"

alt="Back" action="LINK" targetUrl="javascript:go_parent();"/>

</form>

</bbUI:docTemplate>

</bbData:context>

©2008 Blackboard Inc. Proprietary and Confidential Page 28

Page 29: Blackboard Learn Building Blocks Getting Started Guide for Release 9

The content of helloworld.jsp should now be the same as the code sample below.

01 | <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

02 | <%@ taglib uri="/bbUI" prefix="bbUI" %>

03 | <%@ taglib uri="/bbData" prefix="bbData"%>

04 | <%

05 | String iconUrl = "/images/ci/icons/bookopen_u.gif";

06 | String page_title = "HelloWorld: helloworld.jsp";

07 | %>

08 | <bbData:context id="ctx">

09 | <bbUI:docTemplate title="<%= page_title %>">

10 | <bbUI:breadcrumbBar environment="CTRL_PANEL" handle="control_panel">

11 | <bbUI:breadcrumb>HelloWorld Building Block</bbUI:breadcrumb>

12 | </bbUI:breadcrumbBar>

13 | <bbUI:titleBar iconUrl="<%=iconUrl%>">

13 | <%= page_title %>

14 | </bbUI:titleBar>

15 | This is my JSP page. <br>

16 | <% out.print("hello world"); %><br>

17 | <form>

18 | <bbUI:button type="FORM_ACTION" name="back"

19 | alt="Back" action="LINK" targetUrl="javascript:go_parent();"/>

20 | </form>

21 | </bbUI:docTemplate>

22 | </bbData:context>

After adding the above lines you will get error markers at lines 1 and 8. This is because we are attempting to use tags before we have included a reference to the descriptor files in the web.xml file. To resolve these errors add the following references to the web.xml file after the opening web app tag: <jsp-config>

<taglib>

<taglib-uri>/bbUI</taglib-uri>

<taglib-location>/WEB-INF/config/taglibs/bbUI.tld</taglib-location>

</taglib>

<taglib>

<taglib-uri>/bbData</taglib-uri>

<taglib-location>/WEB-INF/config/taglibs/bbData.tld</taglib-location>

</taglib>

</jsp-config>

Save the project and export it to a war file in the same manner as you did earlier. Before you can install this version you must first remove the HelloWorld Building Block installed earlier. This ensures a clean deployment when you add the Building Block again after making changes to the manifest or Java classes. Within the Blackboard Academic Suite, go to Administrator Panel > Manage Building Blocks, make

©2008 Blackboard Inc. Proprietary and Confidential Page 29

Page 30: Blackboard Learn Building Blocks Getting Started Guide for Release 9

HelloWorld unavailable; now you may remove the Building Block by clicking Remove. Install the HelloWorld.war you just exported, make it available and go to a course content panel to open the tool. Notice that the extension now conforms to the Blackboard 'look and feel'.

Congratulations! You have just made your first Blackboard Extension using Building Blocks. (See figure 2.4)

Figure 2.4: HelloWorld using the Tag Library to render a proper Blackboard User Interface.

In the next section you will apply functional Blackboard code to the Building Block.

Identify Users

In the previous section we introduced the bb-manifest the Tag Library. In this section we will introduce accessing User information using the Building Blocks APIs. This will be done by adding a couple of features to the HelloWorld extension developed in the previous section. Create a new My Eclipse J2SE project named HelloWorld_1, and copy the contents of HelloWorld to HelloWorld_1.

Add the Blackboard jars

In order to write Building Block applications on your local system and not have Eclipse throw class errors at every turn you must add the Blackboard Building Blocks API jars. The core jars are bb-platform, bb-taglib, and bb-cms-admin and are found on your development server in the /blackboard/systemlibs directory. Transfer these to your local system and place them in your Eclipse workspace directory in a directory named 'BbDevJars' (you may name this directory anything you like). Now add the jars to the project classpath:

1. Right-click on the project.

2. Select properties in the dialog.

3. Select Java Build Path.

4. Click the Libraries tab.

5. Click the button labeled Add External Jars.

6. Browse to your Eclipse Workspaces, open the BbDevJars directory, select bb-platform.jar and click Open.

7. Repeat steps 5 and 6 for bb-taglib.jar and bb-cms-admin.jar.

The Java Build Path should look like the one shown in figure 2.5.

©2008 Blackboard Inc. Proprietary and Confidential Page 30

Page 31: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Figure 2.5: Libraries on Java Build Path.

HelloWorld: Hello who?

Wouldn't it be nice to say hello to an individual instead of the impersonal Hello World? This is done easily enough by pulling data from the User 's blackboard session and accessing that User’s information. First a session service needs to be established - this is done by adding the Bb Session classes, creating an instance of the SessionManager, and then creating a BbSession from the page request.

Modify helloworld.jsp as shown below:

change line 1 - adding the blackboard.platform.session, blackboard.data.user, and blackboard.platform.persist classes:

<%@ page language="java"

import="java.util.*,

blackboard.platform.session.*,

blackbboard.data.user.*,

blackboard.persist.*"

pageEncoding="UTF-8"%>

Change the page_title to something a bit more useful for this example: String page_title = “HelloWorld_1a: Identifying the Session User”;

Using the page context get the User. Add after line 13 String page_title ...

<%

//Get a User instance via user context

User sessionUser = ctx.getUser();

Now that we have a User get the User's name and Id. Add at line 17:

//Get the User's Name and Id

String sessionUserName = sessionUser.getUserName();

Id sessionUserId = sessionUser.getId();

%>

to display the user name change line 30 from <% out.println( "hello world" ); %> to:

<% out.println( "hi" + sessionUserName ); %> <br>

The context returns the page context associated with the given page request and provides methods for accessing session info. Two of these are getUserId() and getUserName():

©2008 Blackboard Inc. Proprietary and Confidential Page 31

Page 32: Blackboard Learn Building Blocks Getting Started Guide for Release 9

ctx.getUserName() returns the Username of the user associated with this session.

ctx.getUserId() returns the Id of the User associated with this session.

For a complete example of the helloworld.jsp at this stage please see the sample code packaged with this guide. Save the project, export the war and reimport the extension following the steps outlined in the previous section. The Building Block should now look like the example in figure 2.6.

Figure 2.6: HelloWorld using the page context to access the session User name

The Username is not the best identifying greeting for your user; we will fix that shortly, but first a note about accessing information stored in the Blackboard data stores.

With the exception of some custom applications all data and data references used in a Blackboard system is stored in the main Blackboard data store. The Building Blocks API's provide a set of data access classes for working with the data store. These may be broken into two groups: Data Objects and Persistence Objects.

Data Objects

Data Objects are encapsulations of the data entities and attributes used by the Blackboard Academic Suite. These contain no logic and are attribute containers. There are data objects for each of the core entities used in the User interface. This Guide focuses on the User, User Info, Course, and CourseMembership data objects.

Persistence Objects

Persistence Objects provide the required logic to save and read the data objects from the data store. Persistence Objects come in two types: Loaders and Persisters. Loaders are used for reading data from a data store and converting it into an object reference. Persisters take an object reference and write or update the data store. Persisters also are used to delete data from the data store.

Access User Information

To access User Information we can use the User Data Object and Loader available to us in the Building Block API. In order to do so they must first be added to the page's import statement.

If you have not already done so add the blackboard.data.user and blackboard.persist packages to the import statement. The import statement is now: import="java.util.*,

blackboard.platform.session.*,

blackboard.data.user.*,

blackboard.persist.*”

Change the page_title to something a bit more useful for this example: String page_title = “HelloWorld_1b: Accessing User Information”;

©2008 Blackboard Inc. Proprietary and Confidential Page 32

Page 33: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Now, as in the previous example, we can instantiate a User object using the context and acquire their Username and User Id:

<%

//Get a User instance via user context

User sessionUser = ctx.getUser();

String sessionUserName = sessionUser.getUserName();

Id sessionUserId = sessionUser.getId();

%>

Now that we have a User object containing the attributes of our session user we can present a more formal greeting by displaying the User's formal name, their email and their batch_uid:

At line 20 add the following: String sessionUserGivenName = sessionUser.getGivenName();

String sessionUserFamilyName = sessionUser.getFamilyName();

String sessionUserEmailAddress = sessionUser.getEmailAddress();

String sessionUserBatchID = sessionUser.getBatchUid();

Replace line 34 <% out.println( "hi " + uName ); %> with the following:

<%

out.println( "hi " + sessionUserGivenName + " " + sessionUserFamilyName + "," );

out.println( "Your User Name is: " + sessionUserName );

out.println( "Your email address is: " + sessionUserEmailAddress );

out.println( "Your batch_uid is: " + sessionUserBatchID );

%>

Alternately, you could replace line 34 <% out.println( "hi " + uName ); %> with the following and get the same end results:

Hi <%=sessionUserGivenName%> <%=sessionUserFamilyName%>, <br>

Your User Name is: <%=sessionUserName%> <br>

Your email address is: <%=sessionUserEmailAddress%> <br>

Your batch_uid is: <%=sessionUserBatchID%> <br>

Your system role is: <%=sessionUserSystemRole%> <br>

©2008 Blackboard Inc. Proprietary and Confidential Page 33

Page 34: Blackboard Learn Building Blocks Getting Started Guide for Release 9

For a complete example of the helloworld.jsp at this stage please see the sample code packaged with this guide. Save the files and export the war, reimport the extension following the steps outlined in the previous section. The deployed Building Block should now resemble figure 2.7.

Figure 2.7: HelloWorld displaying the session User's info.

The Building Block Project Template

Now that you have built a Building Block from the ground up and understand the basic structure and requirements you can create your own projects following the same procedures outlined above. A simpler way is to start with a project shell or template. The Getting Started Guide supplemental includes a project template named "bb-project”.

Before the template is ready to use it needs to be set up for your development environment:

1. Uncompress the zip archive to your Desktop.

2. Create a new My Eclipse J2SE project and name it my-bb-project-template.

3. Right-click the new project and select Import.

4. Select File System and click Next.

5. Browse to the uncompressed template directory on your desktop, select the files, and set the import options: Select Overwrite existing resources without warning and click Create selected folders only.

6. Add the blackboard jars to the java build path like you did earlier.

Now you have a project set up for your development environment you may use it as a template whenever you wish to start a new Building Blocks project. Simply create your new project like you did in the steps above. The template files are imported into your new project and all you need to do is edit the bb-manifest to reflect the new project. Alternatively, you may copy and paste the template project renaming it in the process. This is also useful for setting up a project that is based on an earlier project. This is how we will setup for the next section: Copy HelloWorld and Paste it, renaming it to HelloWorld_2.

©2008 Blackboard Inc. Proprietary and Confidential Page 34

Page 35: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Figure 2.8: File Import settings

Identify Courses

In the previous section you learned how to access user information and display that information on a page within the Blackboard Academic Suite and you also learned how to reuse templates and earlier projects. In this section we will take a look at using the Building Blocks APIs to identify and gather information on Courses. Note that in order for this example to work you must be a member of a course, such as an Instructor, who has privileges to access the Course Control Panel.

HelloWorld_2: Where are we?

Or to put it a bit differently, how do we inform helloworld of the course context? Course information is accessed and displayed as easily as User information. Some Course attributes are very useful for display while others are required for later data requests involving a User, such as course memberships (covered in the next section). Setting up access to course information is similar to how User information access was set up in the previous section:

• Create a page context

• Create an instance of the session object you wish to get information on

• Gather the information

An alternate method is to use the persistence manager and database loaders (this same process could have been used for accessing User information):

• Create an instance of BbPersistenceManager

• Create an instance of DbLoader

• Create a Course object

Access Course Information

First, access Course information using the session context and then do the same using the Course Data Object and Loader from the Building Blocks APIs. In order to use either method the persist and data packages must be added to the page's import statement:

©2008 Blackboard Inc. Proprietary and Confidential Page 35

Page 36: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Insert the blackboard.data.course and blackboard.persist.course packages at line 8 of the helloworld.jsp. The import statement is now:

import="java.util.*,

blackboard.platform.session.*,

blackboard.data.user.*,

blackboard.persist.* ,

blackboard.persist.user.*,

blackboard.data.course.*,

blackboard.persist.course.*"

Instantiate a Course object from the session context and use it to collect information on the course. After String sessionUserSystem.RoleString (Line 31) add:

//Get a Course instance via user context

Course sessionCourse = ctx.getCourse();

Id sessionCourseId = sessionCourse.getId();

String sessionCourseBatchUID = sessionCourse.getBatchUid();

String sessionCourseCourseTitle = sessionCourse.getTitle(); String sessionCourseDescription = sessionCourse.getDescription();

Long sessionCourseUploadLimit = sessionCourse.getUploadLimit();

boolean sessionCourseIsAvailable = sessionCourse.getIsAvailable(); boolean sessionCourseAllowGuests = sessionCourse.getAllowGuests();

Now display the Course information by inserting the following at line 44:

<p>Information about this course. <br>

<%= sessionCourseCourseTitle %> [BatchUID=<%= sessionCourseBatchUID %> : CourseId<%= sessionCourseBatchUID %>] <br>

<ul> <%= sessionCourseDescription %> </ul><br>

Is this course available? <%= sessionCourseIsAvailable?”Yes”:”No” %> <br>

Guests are allowed? <%= sessionCourseAllowGuests?”Yes”:”No” %> <br>

The current upload limit is: <%= sessionCourseUploadLimit %> </p>

For a complete example of the helloworld.jsp at this stage please see the sample code packaged with this guide. Save the files and export the war, reimport the extension following the steps outlined in the previous section. Open the control panel for your course, select Hello World, and the content of your browser should now look similar to that shown in figure 2.8.

©2008 Blackboard Inc. Proprietary and Confidential Page 36

Page 37: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Figure 2.8: User and Course Information

Another way to access information is to use the persistence manager and database loaders (this same process could have been used for accessing User information):

• Create an instance of BbPersistenceManager

• Create an instance of DbLoader

• Create an object instance of the DbLoader type

Let's take a look at how this is done. Change lines 34 and 35 from: //Get the Course instance from the page context

Course sessionCourse = ctx.getCourse();

to: //Retrieve the Db persistence manager from the persistence service

BbPersistenceManager bbPm = BbServiceManager.getPersistenceService().getDbPersistenceManager();

The Course loader requires a parameter to know what terms to search on to load the data object from the data store. In the case of HelloWorld we will start with the course_id as stored on the URL by the calling page. It is important to note that this course_id is not the same as the COURSE_ID that is used in the snapshot process. Rather, it's the data store reference to the course. At line 36 insert:

// Retrieve the course identifier from the URL

String courseIdParameter = request.getParameter("course_id");

// Generate a persistence framework course Id to be used for loading the course

©2008 Blackboard Inc. Proprietary and Confidential Page 37

Page 38: Blackboard Learn Building Blocks Getting Started Guide for Release 9

// Ids are persistence framework object identifiers.

Id courseId = bbPm.generateId(Course.COURSE_DATA_TYPE, courseIdParameter);

Instantiate the Course loader - insert at line 37: CourseDbLoader courseLoader = (CourseDbLoader)bbPm.getLoader(CourseDbLoader.TYPE);

Then using the course loader get the course object - insert at line 38:

Course sessionCourse = courseLoader.loadById(courseId);

The remainder of helloworld.jsp may stay the same as when we used the context to discover the session course info.

Figure 2.9: Course Information collected using the persistence manager and DbLoader

Save the files and export the war, reimport the extension following the steps outlined in the previous section. Once the new jsp is deployed open the control panel for your course, select Getting Started Guide: Hello World, and the content of your browser should now look similar to that shown in figure 2.9 which should look the same as figure 2.8! In other words, you have accessed the same information using two different coding methods: once using the context and once using the persistence manager and DbLoader.

DbLoaders: Lightweight and Heavyweight

The loading operations of Dbloader methods are either "heavyweight” or "lightweight." Lightweight operations load only values that are the immediate properties of the loaded data objects. Heavyweight operations load not only the immediate properties of the loaded object but also the values of the objects contained by it. While heavyweight operations are optimized for efficiency, lightweight operations should be

©2008 Blackboard Inc. Proprietary and Confidential Page 38

Page 39: Blackboard Learn Building Blocks Getting Started Guide for Release 9

performed whenever possible because they require the transfer and storage of, in some cases, significantly less data.

Identify User Memberships

In the previous sections you learned how to access User information and display that information using the Tag Libraries. You also learned how to access and display Course information. In this section we will continue to expand on these concepts and:

• Learn to access a User's membership in a course, discover that User's role in the course

• Use that information to determine what the User is able to do with our extension

• Build a list of Course memberships

HelloWorld _3 - Why am I here?

You are able to access the HelloWorld Building Block within a course because you have a Course Membership with a specific Course Role. Users are members of Courses and memberships (like Users) have identifying attributes. These attributes provide information such as the User's Role in the Course, whether the membership is active, and the Data Source of the membership. Course membership information is accessed and displayed as easily as Course information and is done using the same pattern as in the previous section:

• Create an instance of BbPersistenceManager

• Create an instance of DbLoader

• Create a Course object

To get started select HelloWorld_2 and copy it to a new project named HelloWorld_3. Open the new project and open helloworld.jsp. Change the variable page_title to reflect this section:

Accessing membership information

To access Course Membership Information you need to use the Course Data Object and Loader from the Building Block API. In order to do so they must first be added to the page's import statement.

Insert the blackboard.data.course and blackboard.persist.course packages at line 8. The import statement is now: import="java.util.*,

blackboard.platform.session.*,

blackboard.data.user.*,

blackboard.persist.* ,

blackboard.persist.user.*,

blackboard.data.course.*,

blackboard.persist.course.*"

The code for instantiating a BbPersistenceManager is already in place from the previous section. If it is not, add the following:

//Retrieve the Db persistence manager from the persistence service

BbPersistenceManager bbPm = BbServiceManager.getPersistenceService().getDbPersistenceManager();

Just like with the Course and User loaders the CourseMembershipDbLoader requires a parameter to know what terms to search on to load the requested data object from the data store. In the case of HelloWorld and Course memberships we want the membership of the session User in the current course context. This is done by instantiating the loader and then loading a membership based on the Course ID and the User ID.

©2008 Blackboard Inc. Proprietary and Confidential Page 39

Page 40: Blackboard Learn Building Blocks Getting Started Guide for Release 9

The user id was previously derived from the session information using User.getId(); as shown on line 26: Id sessionUserId = sessionUser.getId();

At line 61 insert:

// get the membership data to determine the User's Role

CourseMembership cm = null;

CourseMembershipDbLoader crsMembershipLoader = null;

String errMsg = null;

crsMembershipLoader =

(CourseMembershipDbLoader) bbPm.getLoader(CourseMembershipDbLoader.TYPE);

This instantiates the Course membership Db loader. Now using the course membership loader, course memberships can be loaded. In the case of HelloWorld we will use the User's ID and the Course ID. At line 66 insert:

try {

crsMembership = crsMembershipLoader.loadByCourseAndUserId(courseId, uID);

} catch (KeyNotFoundException e) {

// There is no membership record.

errMsg = "There is no membership record. Better check this out:" + e;

} catch (PersistenceException pe) {

// There is no membership record.

errMsg = "An error occured while loading the User. Better check this out:" + pe;

}

Note that the membership 'query' is in a try/catch block. This is because the course membership methods throw keynotfound and persistence exceptions.

With the User's course membership object in hand, using the data.course.CourseMembership methods, you now have access to the attributes of the User's course membership. Insert at line 75:

CourseMembership.Role crsMembershipRole = crsMembership.getRole();

String crsMembershipRoleStr = crsMembershipRole.toString();

java.util.Calendar crsMembershipEnrollmentDate = crsMembership.getEnrollmentDate();

boolean crsMembershipIsAvailable = crsMembership.getIsAvailable();

Insert the following at line 93:

// Get date information

int enrYear = crsMembershipEnrollmentDate.get(Calendar.YEAR);

int enrMonth = crsMembershipEnrollmentDate.get(Calendar.MONTH);

int enrDay = crsMembershipEnrollmentDate.get(Calendar.DATE);

String EnrDateStr = "" + enrMonth + "/" + enrDay + "/" + enrYear);

<p>Information about this membership. <br>

The availability of this membership is:

<%= crsMembershipIsAvailable?"Available":“ "Unavailable";%> <br>

©2008 Blackboard Inc. Proprietary and Confidential Page 40

Page 41: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Date membership created: <%=EnrDateStr%> <br>

The User's Role is: <%=crsMembershipRoleStr%> </p>

For a complete example of the helloworld.jsp at this stage please see the sample code packaged with this guide. Save the files and export the war, and deploy the Building Block. Your screen should now look like the one shown in figure 2.10.

Figure 2.10: Displaying Course membership information for the session User.

Notice that the membership role strings do not look as user friendly as we would hope in a UI – they contain the class and role type information. To have a more user friendly display of the role we need to add a method to the jsp which will return a string representing the Role. Add the following at the end of the file after </bbData:context>:

<%!

static public String getRoleString(String type, Object role) {

// return a User Friendly String for the type Role passed in

String uRole = "";

if ( type.equals( "COURSE" ) ) {

// get role based on coursemembershipRole (CourseMembership.Role)

if( (CourseMembership.Role)role == CourseMembership.Role.COURSE_BUILDER ) {

©2008 Blackboard Inc. Proprietary and Confidential Page 41

Page 42: Blackboard Learn Building Blocks Getting Started Guide for Release 9

uRole="Course Builder";

} else if ( (CourseMembership.Role)role == CourseMembership.Role.DEFAULT ){

uRole="Student(Default)";

} else if ( (CourseMembership.Role)role == CourseMembership.Role.GRADER ) {

uRole="Grader";

} else if ( (CourseMembership.Role)role == CourseMembership.Role.GUEST ) {

uRole="Guest";

} else if ( (CourseMembership.Role)role

== CourseMembership.Role.INSTRUCTOR ) {

uRole="Instructor";

} else if ( (CourseMembership.Role)role == CourseMembership.Role.NONE) {

uRole="No explicit role (NONE)";

} else if ( (CourseMembership.Role)role == CourseMembership.Role.STUDENT) {

uRole="Student";

} else if ( (CourseMembership.Role)role

== CourseMembership.Role.TEACHING_ASSISTANT ) {

uRole="Teaching Assistant";

} else {

uRole = "Cannot Identify Course Membership Role";

}

} else if ( type.equals( "SYSTEM" ) ) {

// get role based on SystemRole

if( (User.SystemRole)role == User.SystemRole.ACCOUNT_ADMIN ) {

uRole="Account Administrator";

} else if ( (User.SystemRole)role == User.SystemRole.COURSE_CREATOR ) {

uRole = "Course creator";

} else if ( (User.SystemRole)role == User.SystemRole.COURSE_SUPPORT ) {

uRole = "Course support";

} else if ( (User.SystemRole)role == User.SystemRole.DEFAULT ) {

uRole = "User";

} else if ( (User.SystemRole)role == User.SystemRole.GUEST ) {

uRole = "Guest";

} else if ( (User.SystemRole)role == User.SystemRole.NONE ) {

uRole = "No explicit role (NONE)";

} else if ( (User.SystemRole)role == User.SystemRole.OBSERVER ) {

uRole = "Observer";

} else if ( (User.SystemRole)role == User.SystemRole.SYSTEM_ADMIN ) {

uRole = "System Administrator";

} else if ( (User.SystemRole)role == User.SystemRole.SYSTEM_SUPPORT ) {

uRole = "System support";

} else if ( (User.SystemRole)role == User.SystemRole.USER ) {

©2008 Blackboard Inc. Proprietary and Confidential Page 42

Page 43: Blackboard Learn Building Blocks Getting Started Guide for Release 9

uRole = "User";

} else {

uRole = "Cannot Identify User System Role";

}

} else {

uRole = "TYPE not qualified in method.";

}

return uRole;

}

%>

and change following lines:

Insert after 85 Your system role is: <%=sessionUserSystemRoleString%> <br>

<!-- return User Friendly Role -->

Your UI friendly System Role is: "<%= getRoleString( "SYSTEM", sessionUserSYSTEMRole ) %>"<br>

Insert after 113 The User's Membership Role is: <%=crsMembershipRoleStr%> <br>

<!-- return User Friendly Role -->

Your UI friendly Course Membership Role is: "<%= getRoleString("COURSE", sessionUserCourseMembershipRole ) %>"

Deploy and view - now those Role strings are User friendly!

Display the course membership list

So far we have been working only on accessing the session User and Course information which is useful in a variety of extensions. Generating a list of users who have membership in a course is also useful. This is accomplished using the now familiar pattern of setting up the persister, DbLoader, and creating the object instance. Additionally, the Bb tag library provides a tag set for rendering tables of information. To add a table containing a list of users to HelloWorld_3 we will use the course membership loader and the Building Blocks list tag. We will also add some comparators for sorting the lists for display. First, load the membership list using the current DbLoader, next add the Comparators and finally build the list display.

First load the course membership into a list - add after line 111: <p>

<%

BbList allMembershipsList =

sessionCourseMembershipLoader.loadByCourseId( courseId, null, true );

When the memberlist is populated it will not be sorted in alphabetical order. In an effort to present a nice UI, sort the list based on the member's Name. Add after line 115: Collections.sort(allMembershipsList, cmSortByFamilyName);

%>

©2008 Blackboard Inc. Proprietary and Confidential Page 43

Page 44: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Now we need to provide the comparator methods to handle the sorting. The User's name, user_id, email, and role will be included in the table. The list tag provides for a column sort using a comparator. Add at line 21:

Comparator cmSortByUsername = new Comparator() {

public int compare(Object o1, Object o2) {

CourseMembership cm1 = (CourseMembership) o1;

CourseMembership cm2 = (CourseMembership) o2;

String s1 = (String)((User)cm1.getUser()).getUserName();

String s2 = (String)((User)cm2.getUser()).getUserName();

return s1.toLowerCase().compareTo(s2.toLowerCase());

}

};

Comparator cmSortByFamilyName = new Comparator() {

public int compare(Object o1, Object o2) {

CourseMembership cm1 = (CourseMembership) o1;

CourseMembership cm2 = (CourseMembership) o2;

String s1 = (String)((User)cm1.getUser()).getFamilyName();

String s2 = (String)((User)cm2.getUser()).getFamilyName();

int compare = s1.toLowerCase().compareTo(s2.toLowerCase());

if( compare == 0 ) {

s1 = (String)((User)cm1.getUser()).getGivenName();

s2 = (String)((User)cm2.getUser()).getGivenName();

compare = s1.toLowerCase().compareTo(s2.toLowerCase());

}

return compare;

}

};

Comparator cmSortByRole = new Comparator() {

public int compare(Object o1, Object o2) {

CourseMembership cm1 = (CourseMembership) o1;

CourseMembership cm2 = (CourseMembership) o2;

String s1 = getRoleString( "COURSE", (CourseMembership.Role)cm1.getRole() );

String s2 = getRoleString( "COURSE", (CourseMembership.Role)cm2.getRole() );

int compare = s1.toLowerCase().compareTo(s2.toLowerCase());

if ( compare == 0 ) {

s1 = (String)((User)cm1.getUser()).getFamilyName();

s2 = (String)((User)cm2.getUser()).getFamilyName();

compare = s1.toLowerCase().compareTo(s2.toLowerCase());

if( compare == 0 ) {

s1 = (String)((User)cm1.getUser()).getGivenName();

s2 = (String)((User)cm2.getUser()).getGivenName();

©2008 Blackboard Inc. Proprietary and Confidential Page 44

Page 45: Blackboard Learn Building Blocks Getting Started Guide for Release 9

compare = s1.toLowerCase().compareTo(s2.toLowerCase());

}

}

return compare;

}

};

Comparator cmSortByEmailAddress = new Comparator() {

public int compare(Object o1, Object o2) {

CourseMembership cm1 = (CourseMembership) o1;

CourseMembership cm2 = (CourseMembership) o2;

String s1 = (String)((User)cm1.getUser()).getEmailAddress();

String s2 = (String)((User)cm1.getUser()).getEmailAddress();

return s1.toLowerCase().compareTo(s2.toLowerCase());

}

};

Now that we have a sorted list of course members, let's display it. The list tag is a perfect way of displaying lists of information. Add at line 174:

<bbUI:list

collection="<%= allMembershipsList %>"

collectionLabel="Users"

objectId="cm"

className="CourseMembership">

<bbUI:listElement width="10">

</bbUI:listElement>

<bbUI:listElement

label="Name"

name="Name"

comparator="<%= cmSortByFamilyName %>">

<%= cm.getUser().getGivenName() %> <%= cm.getUser().getFamilyName() %>

</bbUI:listElement>

<bbUI:listElement

label="Username"

name="Username"

comparator="<%= cmSortByUsername %>">

<%= cm.getUser().getUserName() %>

</bbUI:listElement>

<bbUI:listElement

label="Email"

name="Email"

comparator="<%= cmSortByEmailAddress %>">

<%= cm.getUser().getEmailAddress() %>

©2008 Blackboard Inc. Proprietary and Confidential Page 45

Page 46: Blackboard Learn Building Blocks Getting Started Guide for Release 9

</bbUI:listElement>

<bbUI:listElement

label="Role"

name="Role"

comparator="<%= cmSortByRole %>">

<%= getRoleString( "COURSE", cm.getRole() ) %>

</bbUI:listElement>

</bbUI:list>

</p>

There is a lot of new code here so let's break it down:

The opening tag: <bbUI:list

collection="<%= allMembershipsList %>"

objectId="cm"

className="CourseMembership">

contains the following attributes: collection – this is the collection that is passed in for processing

collectionLabel – useful for addressing multiple lists by label.

objectId - the object that is in the list

className – the classname for the object

and encloses the contents of the table comprised of columns the cells of which are specified by the listElement tags.

The listElement tag:

<bbUI:listElement

label="Name"

comparator="<%= cmSortByFamilyName %>">

<%= cm.getUser().getGivenName() %> <%= cm.getUser().getFamilyName() %>

</bbUI:listElement>

contains the following attributes: label - the optional label for the column

name – the name for the cell

comparator - optional attribute to specify the comparator used to sort the list.

So for the listElement: <bbUI:listElement

label="Name"

name="Name"

comparator="<%= cmSortByFamilyName %>">

<%= cm.getUser().getGivenName() %> <%= cm.getUser().getFamilyName() %>

</bbUI:listElement>

©2008 Blackboard Inc. Proprietary and Confidential Page 46

Page 47: Blackboard Learn Building Blocks Getting Started Guide for Release 9

we are saying create a column with the label 'Name' that contains the User's Given and Family name and is sorted using the cmSortByFamilyName comparator.

The Building Block should look similar to that shown in figure 2.11.

Figure 2.11: Displaying Course membership information for all course members in a sorted list.

©2008 Blackboard Inc. Proprietary and Confidential Page 47

Page 48: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Chapter 3: Photo Roster Building Block

In the previous sections the basic and most often used classes of the Building Block API and their use were covered - specifically the data and persistence classes for Users, Courses, and Course Memberships. Additionally the options for deploying extensions to a development server, the purpose of the Bb-manifest, and use of the tag libraries were covered. Writing HelloWorld was fine for presenting these concepts, but serves no true utility within Blackboard. In this section we will take the previously covered concepts and code, add more in the way of working with the Tag libraries, additional bb-manifest entries, and using external extension specific classes and end up with a useful application. Also covered are some best practices for managing and writing a Building Block. This will all be accomplished by writing a functional Photo Roster Extension.

Topic Description

Best Practices in Practice This topic reviews some key concepts when planning a Building Blocks development project.

Setup the Photo Roster Project This topic gives instructions for using the HelloWorld project as a new project template for the Photo Roster.

The Photo Roster Main Page This topic presents the code in the .jsp page used to create the Photo Roster.

Photo Roster Classes This topic introduces the code classes used in the Photo Roster.

Development Notes This topic covers some additional issues surrounding the Photo Roster.

The (Open Source) Photo Roster

The Photo Roster in this example is intended to provide a functional application of the concepts presented in the earlier sections. It is presented as an Open Source Project in the hope that it will grow into something of greater utility for the Bb community. As such, its design is intended to be merely a beginning point and it is small and flexible enough to easily morph into something that meets any institution's needs. If you do create a useful tool from this exercise, please share it with others through the Building Blocks catalog.

Best Practices in Practice

There are several approaches for managing software development projects. Herein are some suggestions to help make Building Blocks development go more smoothly. These are observations based on my experience; I have found these steps to work equally well in practice for a single developer as for a team of developers. These are a few basic concepts that may be as simple or complex as the project demands and will help any Building Blocks project go smoothly.

Define the Project Scope and Requirements

Gather the project principals to define the project's goals and requirements. For the Photo Roster this could read something like:

Project Description

Blackboard supports the presentation of course rosters. There is great interest on the part of the Registrar in this utility as a point for increasing adoption of Blackboard by Departments and Faculty. Also, this feature has great utility to Faculty in that it presents an up-to-date presentation of their Course enrollment. What is missing is a means of identifying the registered students. The Photo Roster Project proposes to improve the

©2008 Blackboard Inc. Proprietary and Confidential Page 48

Page 49: Blackboard Learn Building Blocks Getting Started Guide for Release 9

utility of the current Blackboard course roster tool by providing a means of displaying photos alongside the name of the student displayed in the roster.

Goals and Requirements

Goals List

Provide Course Roster consisting of a photo and course member name, email, and role

Requirements List

• The Course and sessions User information will be displayed along with a message stating that this page reflects current enrollment.

• Member photographs are accompanied by information comprised of first and last name, email, and group membership Role.

• The Campus ID system is the likely source for ID Photos, integration is necessary

• Photos may come from the Photo ID system

• Some users may not exist in Photo ID system - provide a local repository

• Provide for future changes in ID storage

Outside the current scope of this project

Currently we will endeavor to use the ID system as-is and not directly address or resolve issues regarding the functionality of the ID system.

Design the Extension: The User Interface and Technical Specifications

Once the goals and requirements are defined it is fairly easy to sketch up a User Interface. Normally I rely on relatively quick scanned pencil sketches. If you question your drawing abilities it is possible to mock up the UI in a Paint application.

Figure 3.1: User Interface mock up for Photo Roster. Note the lack of Bb elements. These will be added in the final design.

Technical specs may also be driven by the simplicity or complexity of the application. While you are learning the Building Blocks APIs it may prove useful to be fairly explicit in not only the aspects of a project that falls outside the scope of the APIs but also the more general aspects of the program. For the Photo Roster tool this may, in its simplest form, look like:

Program Flow:

• Get session information

• Identify user and get user info:

• Load user db loader, data.User, Name, System Role, Email, and Batch_uid

• Identify course and get course info:

©2008 Blackboard Inc. Proprietary and Confidential Page 49

Page 50: Blackboard Learn Building Blocks Getting Started Guide for Release 9

• Load course db loader, data.Course, CourseId, BatchUID, Title, Description, Batch_uid, UploadLimit, Availability, AllowGuests

• Get course membership

• Display session user information

• Display course information

• Display membership info one user per table row

Required Bb classes (Bb API Scope):

Sessions Info: blackboard.platform.session.*

User Data: blackboard.data.user.*

Course Data: blackboard.data.course.*

Persistence Managers: blackboard.persist.*

User DB loaders: blackboard.persist.user.*

Course DB loaders: blackboard.persist.course.*

Date: java.util.Calendar

Required Methods:

Session Info: request.getParameter

BbServiceManager.getSessionManagerService

BbSessionManagerService.getSession

BbSession.lookupUserContext

BbSession.getUserId

BbSession.getUserName

BbServiceManager.getPersistenceService.getDbPersistenceManager

UserDbLoader)BbPersistenceManager.getLoader(UserDbLoader.TYPE);

UserDbLoader.loadById

User.getUserName

User.getGivenName

User.getFamilyName

User.getEmailAddress

User.getBatchUid

User.getSystemRole.toString

BbPersistenceManager.generateId

BbPersistenceManager.getLoader

CourseDbLoader.loadById

Course.getCourseId

©2008 Blackboard Inc. Proprietary and Confidential Page 50

Page 51: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Course.getBatchUid

Course.getTitle

Course.getDescription

Course.getBatchUid

Course.getUploadLimit

Course.getIsAvailable

Course.getAllowGuests

CourseMembershipDbLoader.loadByCourseAndUserId

CourseMembership.getRole

CourseMembership.getDataSourceId

CourseMembership.getEnrollmentDate

CourseMembership.getIsAvailable

CourseMembership.getRole

External Classes

Photo Upload

input: batch_uid

input: photo jpg upload

requires write permissions on directory.

PhotoFetch

input: batch_uid

output: url to image

Bb-manifest

data read

database

file i/o

Necessary Bb tags

context

docTemplate

breadcrumb

list

listElement

button

©2008 Blackboard Inc. Proprietary and Confidential Page 51

Page 52: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Design, Define, Develop, Deploy, Rinse, Repeat until done

Think of development as a spiral that starts from the originating Requirements phase and ends with a final product. As the spiral opens, its path moves repeatedly through the same four quadrants representing the following phases: Define, Design, Develop, Deploy. As each quadrant is left observations are made on that phase and as the next quadrant is entered those observations are considered and applied. In some cases this is merely an act of confirming that things are on track. Other cases may require a revisiting of a previous phase for revisions to be applied. In the Define phase, requirements are gathered and resources are allocated; in the Design phase, decisions are made to how best meet the requirements within the project contact; during the Develop stage, code is produced (hopefully along with supporting Unit Tests); and during the Deploy phase, the application is deployed and tested. This process is completed when the final product is released.

Set up the Photo Roster project

The Photo Roster project uses the same structure and much of the same code as HelloWorld so in the spirit of reuse we are going to start with the HelloWorld project and develop it into a Photo Roster. Eclipse makes this easy to do. Select the HelloWorld project in the Eclipse project view and right-click on the project view, select copy from the popup, and again right-click on the project view and select Paste - enter the new project name OSPhotoRoster into the subsequent dialog. The new project appears in the project view and is nearly ready to deploy as-is, but before deploying the manifest will need changing to suit the new project name. Remember that included in the package with this guide is a bare bones project that can be copied into your Eclipse workspace and used as a starting point for new Building Block projects!

Photo Roster Bb-manifest Requirements

Before we deploy our working version of the Photo Roster the Bb-manifest needs amended to reflect the Photo Roster Project. Minimally, to avoid extension namespace collision, revise the plugin handle value, the version value, and the vendor id value:

<plugin>

<name value="Getting Started Guide: Photo Roster"/>

<description value="PhotoRoster Building Block from the Getting Started Guide"/>

<handle value="photoroster"/>

<version value="1.0.0"/>

...

<vendor>

<id value="bgsg"/>

Additionally, so the link in the control panel is unique change it and the link to the starting page: <link>

<type value="course_tool"/>

<name value="Getting Started Guide: Photo Roster"/>

<url value="photoroster.jsp"/>

...

Finally per the requirements of being able to upload a photo the permissions to do so need to be added to the permissions section:

<permission type="java.io.FilePermission"

name="/-"

actions="read,write,delete"/>

...

©2008 Blackboard Inc. Proprietary and Confidential Page 52

Page 53: Blackboard Learn Building Blocks Getting Started Guide for Release 9

The final manifest is listed in its entirety in the appendix (see listing 6.1).

The Photo Roster Main Page

The Photo Roster shares much of the same base code as Helloworld. The main differences are the layout of that information, the additional handling of Course memberships, and accessing the ID photos. Listing 6.2 contains the complete Photo Roster code. The following intends to highlight the added code necessary to turn the simple HelloWorld extension into the Photo Roster.

Nicely enough, since it only gathers information that is later displayed, nothing really needs to change between the beginning of the import section and the portion of the code that renders the page. After the line containing boolean sessionUserCourseMembershipIsAvailable =

change the code that renders the top of the page (above the <bbUI:list> tag) to:

<bbUI:docTemplate title="<%= page_title %>">

<!-- Start Breadcrumb Navigation -->

<bbUI:breadcrumbBar environment="CTRL_PANEL" handle="control_panel">

<bbUI:breadcrumb>Photo Roster</bbUI:breadcrumb>

</bbUI:breadcrumbBar>

<!-- End Breadcrumb Navigation -->

<bbUI:titleBar iconUrl="<%=iconUrl%>">

<%= page_title %>

</bbUI:titleBar>

<p>

Hi <%= sessionUserGivenName %> <%= sessionUserFamilyName %>

(<%= getRoleString ( "COURSE", sessionUserCourseMembershipRole ) %>) <br>

</p>

<center>

<H1>Photo Roster for <%= sessionCourseCourseTitle %></H1>

</center>

<p>

HelloWorld dealt with gathering the attributes of a single course member, specifically the session user. In the case of the PhotoRoster the entire course membership is required. This is achieved by building a list of memberships . After:

...

<H1>Photo Roster for <%= sessionCourseCourseTitle %></H1>

</center>

<p>

add

<%

BbList allMembershipsList =

sessionCourseMembershipLoader.loadByCourseId( courseId, null, true );

©2008 Blackboard Inc. Proprietary and Confidential Page 53

Page 54: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Collections.sort(allMembershipsList, cmSortByFamilyName);

%>

Note the use of the comparator to sort the incoming list on User's family name.

Now start the table that holds the photos and member information. As in HelloWorld this is done using the list and listElement tags from the bbUI tag library:

<!-- table of course members with Photo -->

<bbUI:list

collection="<%= allMembershipsList %>"

objectId="cm"

className="CourseMembership">

<bbUI:listElement width="10">

</bbUI:listElement>

<bbUI:listElement

label="Photo"

name="Photo"

align="center"

valign="top">

<!-- retrieve a URL to a photo for this User matching the User's batch_uid -->

<p>

<%

if ( PhotoRoster.isThereAPhoto( cm.getUser().getBatchUid() ) ) {

%>

<%=PhotoRoster.getScaledPhotoURL( cm.getUser().getBatchUid(), 90)%>

<%

} else {

// No photo - display placeholder and upload text

%>

<img src="images/no_photo.gif"><br>

<p>

<a href = "post.jsp?action=load&usersbatch_uid=<%=

cm.getUser().getBatchUid() %>&sessionCourseID=<%=courseIdParameter%>">

upload a photo

</a>

</p>

<%

}

%>

</p>

</bbUI:listElement>

<bbUI:listElement

©2008 Blackboard Inc. Proprietary and Confidential Page 54

Page 55: Blackboard Learn Building Blocks Getting Started Guide for Release 9

label="Name"

name="Name"

align="center"

valign="top"

comparator="<%= cmSortByFamilyName %>">

<p>

<%= cm.getUser().getGivenName() %> <%= cm.getUser().getFamilyName() %>

</p>

</bbUI:listElement>

<bbUI:listElement

label="Username"

name="Username"

align="center"

valign="top"

comparator="<%= cmSortByUsername %>">

<p>

<%= cm.getUser().getUserName() %>

</p>

</bbUI:listElement>

<bbUI:listElement

label="Email"

name="Email"

align="center"

valign="top"

comparator="<%= cmSortByEmailAddress %>">

<p>

<%= cm.getUser().getEmailAddress() %>

</p>

</bbUI:listElement>

<bbUI:listElement

label="Role"

name="Role"

align="center"

valign="top"

comparator="<%= cmSortByRole %>">

<p>

<%= getRoleString( "COURSE", cm.getRole() ) %>

</p>

</bbUI:listElement>

</bbUI:list>

©2008 Blackboard Inc. Proprietary and Confidential Page 55

Page 56: Blackboard Learn Building Blocks Getting Started Guide for Release 9

The second list element calls an external method to retrieve the photo. We must define the class and also make it accessible to the page. The latter is achieved by adding at the top of the page:

<jsp:useBean id="PhotoRoster" scope="page" class="org.bbopensrc.PhotoRoster.PhotoRoster"/>

The Photo Roster needs additional classes to provide access to photos and the ability to upload photos. These classes rely on the Jakarta File Upload Commons and IO Commons packages from:

http://jakarta.apache.org/commons/fileupload/ and http://jakarta.apache.org/commons/io/

Extract and place the resultant directories in your development library directory and then add commons-fileupload-1.1 and commons-io-1.1 to the project build path.

Also create a folder in the project name it "images" and copy the icon images from the example archive. These are used when photos are not found.

Photo Roster Classes

The PhotoRoster Class

To provide a flexible means of accessing photos, whether stored locally on the application server or remotely in an enterprise ID system, an external class is provided, which may be altered to suit the access needs. In this example photos are stored locally as .jpg files with the course member's batch_uid as the file name. The complete code for the PhotoRoster class is included with the code samples packages with this guide.

The PhotoRoster class contains three methods: String getScaledPhotoURL(String inBatch_uid, int maxDimension)

String getPhotoURL(String inBatch_uid)

String isThereAPhoto( String batch_uid )

The methods getScaledPhotoURL and getPhotoURL provide information necessary to access the photos stored on the server. The getScaledPhotoURL method returns a complete photo img src tag containing height and width attributes for scaled photos. The getPhotoURL method returns only the roof portion of the URL to which you add the <batch_uid>. jpg to complete the img src tag. The isThereAPhoto method returns a Boolean: true if there is a file stored on the server, false if not. The PhotoRoster class uses a second Files class, for managing access to the file information.

To add the PhotoRoster class to the project right-click the project and select New > Package and enter org.bbopensrc.PhotoRoster into the package name field. While the PhotoRoster package is selected, right-click to select New > Class and create a PhotoRoster file. Now open the file and copy and paste the contents of the PhotoRoster listing (listing 6.3 in the appendix). Ignore all the errors for a moment and proceed with the Files and Uploader classes.

The Photo Roster Uploader Class

The code for the Photo Roster uploader does the heavy lifting of processing a upload request. Additionally this class uses the Jakarta Commons FileUpload component to handle the uploading of files to the server. The Uploader class provided here is based on the one presented in Apache Jakarta Commons: Reusable Java™ Components, by Will Iverson, available from Prentice Hall at http://www.phptr.com/perens. A comprehensive discussion of the class is available in that document. A complete listing as used in this example is provided in the code samples.

Add the Uploader class using the same process as used to add the PhotoRoster class:

right-click the project and select New -> Package and enter org.bbopensrc into the package name field. While the org.bbopensrc package is selected, right-click to select New -> Class and create an Uploader file. Now copy and paste the contents of the Uploader listing.

©2008 Blackboard Inc. Proprietary and Confidential Page 56

Page 57: Blackboard Learn Building Blocks Getting Started Guide for Release 9

The PHOTO ROSTER Files Class

To provide information on and a means of managing the photo files an external class is used. The Files class provided here is also based on one presented in Apache Jakarta Commons: Reusable Java™ Components. A complete listing as used in this example is provided in the code samples.

Add the Files class using the same process as used to add the PhotoRoster class:

While the org.bbopensrc package is selected, right-click to select New > Class and create a Files file. Now copy and paste the contents of the Files code sample. Edit the variable String photoPath to reflect your target installation.

This completes the code necessary for accessing the course memberships and any photos associated with those memberships. If you export a war file, install it on your application server and access the Building Block in the course control panel you might see something similar to figure 3.1.

Development Notes

Figure 3.1: Viewing the photo roster before uploading post.jsp and User photos. Note that the upload a photo link is not functional.

The missing component is the photo of each course member - this is because there are no photos in the images directory matching the batch_uid. The post.jsp provides the form page used to send an upload request:

<%@ page language="java" import="java.sql.*" %>

<%@ page import="org.bbopensrc.Uploader" %>

<jsp:useBean id="PhotoRoster" scope="page" class="org.bbopensrc.PhotoRoster.PhotoRoster"/>

<%@ page language="java"

©2008 Blackboard Inc. Proprietary and Confidential Page 57

Page 58: Blackboard Learn Building Blocks Getting Started Guide for Release 9

import="java.util.*,

blackboard.base.*,

blackboard.data.*,

blackboard.data.user.*,

blackboard.data.course.*,

blackboard.persist.*,

blackboard.persist.user.*,

blackboard.persist.course.*,

blackboard.platform.*"

pageEncoding="UTF-8"

%>

<%@ taglib uri="/bbUI" prefix="bbUI" %>

<%@ taglib uri="/bbData" prefix="bbData"%>

<%

String iconUrl = "/images/ci/icons/bookopen_u.gif";

String page_title = "Getting Started Guide: Photo Roster";

String msg = "Hello";

String backTargetURL = "photoroster.jsp?course_id=";

String sessionCourseID = "";

%>

<bbData:context id="ctx">

<%

if ( request.getParameter("action")==null ) {

Uploader myUploader = new Uploader();

myUploader.doFilePost(request, application);

sessionCourseID = myUploader.getParameter("sessionCourseID");

msg = "File Uploaded.";

} else {

sessionCourseID = request.getParameter("sessionCourseID");

msg = "<form action=\"post.jsp\" method=\"post\" " +

"enctype=\"multipart/form-data\" name=\"form1\" id=\"form1\">" +

"<table width=\"100%\" border=\"0\" cellspacing=\"3\" cellpadding=\"3\">" +

"<tr> " +

"<td><input type=hidden name=\"batch_uid\" value = \""+

request.getParameter("usersbatch_uid") + "\">" +

"<input type=hidden name=\"sessionCourseID\" value = \"" +

request.getParameter("sessionCourseID") + "\">" +

"</td>" +

"</tr>" +

"<tr>" +

©2008 Blackboard Inc. Proprietary and Confidential Page 58

Page 59: Blackboard Learn Building Blocks Getting Started Guide for Release 9

"<td align=right width=\"25%\"><strong>File</strong></td>" +

"<td><input type=\"file\" name=\"file\" /></td>" +

"</tr>" +

"<tr>" +

"<td width=\"25%\">&nbsp;</td>" +

"<td><input type=\"submit\" name=\"Submit\" value=\"Upload\" /></td>" +

"</tr>" +

"</table>" +

"</form>" +

"<br>";

}

%>

<bbUI:docTemplate title="<%= page_title %>">

<!-- Start Breadcrumb Navigation -->

<bbUI:breadcrumbBar environment="CTRL_PANEL" handle="control_panel">

<bbUI:breadcrumb href="<%="photoroster.jsp?course_id=" +

sessionCourseID%>">Photo Roster</bbUI:breadcrumb>

<bbUI:breadcrumb>Photo Post</bbUI:breadcrumb>

</bbUI:breadcrumbBar>

<!-- End Breadcrumb Navigation -->

<bbUI:titleBar iconUrl="<%=iconUrl%>">

<%= page_title %>

</bbUI:titleBar>

<center>

<H1>Post a Photo to the Photo Roster</H1>

</center>

<p>

<%=msg%>

<div align="right">

<bbUI:button type="FORM_ACTION" name="back" alt="BACK" action="LINK"

targetUrl="<%="photoroster.jsp?course_id=" + sessionCourseID%>"/>

</div>

</p>

</bbUI:docTemplate>

</bbData:context>

Create a new jsp page, name it “post” and paste the above code into it. Deploy the Building Block with the new code. Now when you load the Photo Roster and click the upload photo link you should see something similar to that in figure 3.3.

©2008 Blackboard Inc. Proprietary and Confidential Page 59

Page 60: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Figure 3.3: Form generated by post.jsp used to upload photos.

Posting a couple of photos produces the display shown in Figure 3.4 when loading the Photo Roster.

Figure 3.4: Photo Roster displaying Course member photos. Note that all photos are available to all courses because the uploaded photos are stored locally to the Building Block.

©2008 Blackboard Inc. Proprietary and Confidential Page 60

Page 61: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Appendix A: Alternative Deployment Options

Deploy via Remote Deployment

How you deploy the Building Block extensions you develop depends on the level of access you have for your Blackboard server. The most certain method is what you have done so far – export the Building Block as a .WAR file and add it to the Blackboard Academic Suite through the user interface. After the initial installation through the user interface you may employ alternate methods of deploying edited files, with the exception of when you edit the bb-manifest - more on that soon, that make up the extension. It is very important before considering alternate deployment methods that the permissions on the installed Building Blocks are such that you may read and write to them, done by changing the ownership privileges through the folder properties in Windows or executing the following command on UNIX-based servers:

chgrp -R plugins/<your_plugin_directory>)

The plugin directory is defined as blackboard/content/vi/bb_bb60/plugins/ VendorID-ApplicationHandleID

One method of remote deployment is to scp to copy the files. Another is to mount your server via NFS (or other means of mounted file sharing) and use the MyEclipse Workbench to deploy to an externally launched server. The MyEclipse Workbench setup for remote deployment is similar to a local deployment - simply select ' <Externally Launched>' as the deployment location and point to the mounted server.

Another means, the one used by the author, is to use another Eclipse plugin aptly named Deployer (http://deployer.sourceforge.net/download.shtml). The installation of Deployer is as simple as downloading the archive, expanding the contents into the eclipse directory and (re)starting Eclipse.

Development of Building Blocks that are comprised solely of jsp pages only require an initial installation, then as long as the manifest is not edited the project may be edited to completion. This cycle is somewhat more complicated when the project contains java classes. When making changes to the java source it is necessary to reinstall the extension in order to replace the compiled classes on the server.

Please see the Deployer documentation for more information on using it to deploy a file to a remote server.

Deployment and the bb-manifest

When changes are made to the Bb-manifest the extension needs to be redeployed by adding the Building Block to the Blackboard Academic Suite through the user interface. The bb-manifest is read only during the installation - never by Tomcat during normal run-time, so changes are not conveyed to the Blackboard Academic Suite unless the extension is reinstalled.

©2008 Blackboard Inc. Proprietary and Confidential Page 61

Page 62: Blackboard Learn Building Blocks Getting Started Guide for Release 9

Appendix B: List of Resources

Additional Resources from Blackboard

The following is a list of materials available from Blackboard to help you develop Building Blocks. These documents are available from:

• Blackboard Developer Network (http://www.blackboard.com/extend/dev/BbDN.htm)

• Behind the Blackboard support site (http://www.blackboard.com/support/)

Resource DESCRIPTION

Introduction to the Building Blocks APIs and Runtime

Reference material about the Building Block APIs and Runtime for developers creating Building Blocks.

Building Blocks Developers Guide An overview of the Building Block framework and in-depth reference.

Module Developers Guide A quick start reference to create Building Block modules.

Building Block API Specifications The Building Block API JavaDoc; this serves as the authoritative reference for developers creating Building Blocks for the Blackboard Academic Suite. The specification identifies and describes the Java classes that developers may use to interact with the Blackboard Academic Suite.

Administrative API Specifications These APIs are designed specifically to handle the import of data from other systems. Most of the function of these Java classes is replicated in the Building Blocks APIs.

Blackboard Content System Building Blocks API Specifications

The Building Block API JavaDoc for the Blackboard Content System; this serves as the authoritative reference for developers creating Building Blocks for the Blackboard Content System.

©2008 Blackboard Inc. Proprietary and Confidential Page 62

Page 63: Blackboard Learn Building Blocks Getting Started Guide for Release 9

©2008 Blackboard Inc. Proprietary and Confidential Page 63

Community Resources

The following is a list of resources where you can communicate and share with other Building Blocks developers.

Resource

Open Source Building Blocks LISTSERV

http://www.bb-opensource.org/

Building Blocks Catalog

http://www.blackboard.com/extend/dev/index.aspx

Building Blocks Developer Network

http://www.blackboard.com/extend/dev/BbDN.htm

Blackboard Communities

http://communities.blackboard.com

Technical Resources

The following is a list of resources for Java developers that the author used when writing this guide.

Resource

Java

http://java.sun.com

Tomcat

http://tomcat.apache.org

Eclipse

http://www.eclipse.org/

MyEclipse Workbench

http://www.MyEclipseIDE.com

Lomboz

http://www.objectlearn.com/index.jsp

Sysdeo

http://www.sysdeo.com

Deployer

http://deployer.sourceforge.net/download.shtml

Apache Jakarta Commons: Reusable Java™ Components, by Will Iverson, available from Prentice Hall at http://www.phptr.com/perens