Blackboard and Content Types John Knight Blackboard Inc.
Dec 14, 2015
Blackboard and Content Types
John KnightBlackboard Inc.
And now a word from our lawyers ...
Any statements in this presentation about future expectations, plans and prospects for the Company, including statements about the Company, the Building Blocks Program and other statements containing the words “believes,” “anticipates,” “plans,” “expects,” “will,” and similar expressions, constitute forward-looking statements within the meaning of The Private Securities Litigation Reform Act of 1995. Actual results may differ materially from those indicated by such forward-looking statements as a result of various important factors, including: product development, and other factors discussed in our Registration Statement filed on Form S-1 with the SEC. In addition, the forward-looking statements included in this press release represent the Company’s views as of July 26, 2004. The Company anticipates that subsequent events and developments will cause the Company’s views to change. However, while the Company may elect to update these forward-looking statements at some point in the future, the Company specifically disclaims any obligation to do so. These forward-looking statements should not be relied upon as representing the Company’s views as of any date subsequent to July 26, 2004.
Overview
Types of Content Oriented Building Block Integrations Look at Various Implementations Tips and Tricks Questions
Types of Integrations
Content-Handlers which work with internal data structures and use Building Block persisters for data storage
Content-Handlers which work with internal data structures and use other means for storage (XML, Java Property Files, etc)
Content-Handlers which simply link to an external system
Before we look at differences…
Let’s examine the commonalities….
Let’s quickly walk through our Building Block Planning Process (From the My First Building Block Presentation)
Planning
Where are you going to hook your application into Blackboard?
User Interface Integration
Content-Handlers appear under the “add other” pull down from the content areas.
Planning
Which APIs are you going to use?
API Capabilities
Building Blocks API– Announcement (read and write)– Calendar (read and write)– Content (read and write)– Gradebook (read and write)– Session (read and write)– File system (read and write)– *User (read)– *Course (read)– *Membership (read)
Structure of the Building Block
It’s a standard JAVA Web Application (Webapp) with some additional descriptive data (XML Files) that is used by Blackboard to manage registration, deployment, security and management.
Directory Structure
Package Format
A webapp is a zip file with a specific directory structure
WinZip, PkZip, or Java’s Jar utility will all create the correct package
Even though it is a zip file, the extension does not matter (.zip, .war, .bb will all work)
WEB-INF
Hidden from web Contents
– web.xml– bb-manifest.xml– Config directory– Classes directory– Lib directory
Config Directory
Hidden from web Only directory that is owned by your building block Can contain anything (hint hint) No size limit (hint hint)
Custom Code and Libraries
Classes– Stored in WEB-INF\classes
Jars– Stored in WEB-INF\lib– Automatically on classpath via custom classloader
Manifest Structure
Bb-manifest.xml– Set of directives the developer provides
• Building Blocks Configuration• Application Definitions
– Content Handlers– UI Links– Portal Modules
• Security Declarations
Let’s Take a Look at one for content …
Bb-manifest.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<manifest>
<plugin>
<name value= "Sample Content Handler"/>
<handle value= "sample-contenthandler"/>
<description value= "Sample Content Handler"/>
<version value= "1.0.0"/>
<requires>
<bbversion value="6.0.0"/>
</requires>
<vendor>
<id value="bb"/>
<name value="Blackboard Research and Development"/>
<url value="http://www.blackboard.com/" />
<description value="Blackboard Research and Development Team" />
</vendor>
<http-actions>
<config value="admin/config.jsp"/>
<remove value="admin/remove.jsp"/>
</http-actions>
Bb-manifest.xml
...
<content-handlers>
<content-handler>
<name value=“Sample Content Handler"/>
<handle value= "resource/x-bb-samplecontent"/>
<http-actions>
<create value="ch1/create.jsp"/>
<modify value="ch1/modify.jsp"/>
<remove value="ch1/remove.jsp"/>
</http-actions>
<icons>
<toolbar value="/images/add_ch1.gif"/>
<listitem value="/images/icon.gif"/>
</icons>
</content-handler>
</content-handlers>
...
Set Handler
Set Create, Modify, and Remove handlers
Bb-manifest.xml
...
<permissions>
<permission type="persist" name="Content" actions="create,modify,delete"/>
<permission type="attribute" name="user.personalinfo" actions="get"/>
<permission type="attribute" name="user.authinfo" actions="get"/>
</permissions>
</plugin>
</manifest>
Now we know the structure…
Once we have decided our directory layout and created (customized) our bb-manifest.xml file, we are ready to look at the JSP pages which comprise our webapp.
With that…
We need to setup a structure for our webapp
Deploy the skeleton
It’s far easier to deploy the skeleton webapp and then make your changes directly on your DEVELOPMENT server.
Files are located inblackboard/content/ci/bb_bb60/xxx-xxxx/webapp
Some good things to know…
Course ID and Container ID are passed to pages If you use the taglibs (BbUI and BbData) you will
always have access to the session data, user data, consistent UI widgets, etc.
You have access to read/write files to your webapps config space– Good for configuration data or application data!
Create.jsp
<%
///////////////////////////////////////////////////////////
// Filename: Create.jsp
// Desc: Part of the sample content-handler, this file
// is resonsible for displaying the form to gather
// the data for the creation of the content object.
///////////////////////////////////////////////////////////
%>
<%@ page import="
blackboard.platform.*,
blackboard.platform.plugin.*"
errorPage="/error.jsp"
%>
<%@ taglib uri="/bbUI" prefix="bbUI"%>
<%@ taglib uri="/bbData" prefix="bbData"%>
<bbData:context id="ctx">
Page Imports
Import Tag Libs
Establish Context
Create.jsp
<%
if (!PlugInUtil.authorizeForCourseControlPanel(request, response))
return;
%>
<bbUI:docTemplate title="Create Sample Content">
<bbUI:coursePage courseId="<%=PlugInUtil.getCourseId(request)%>">
<form action="create_proc.jsp" method='post' NAME='the_form' ID='the_form'>
<input type="hidden" name="course_id" value="<%=request.getParameter("course_id")%>">
<input type="hidden" name="parent_id" value="<%=request.getParameter("content_id")%>">
<bbUI:breadcrumbBar handle="control_panel" isContent="true">
<bbUI:breadcrumb> SAMPLE CONTENT HANDLER</bbUI:breadcrumb>
</bbUI:breadcrumbBar>
<bbUI:titleBar iconUrl="/images/ci/icons/tools_u.gif">Sample Content Handler - Create</bbUI:titleBar>
Check for Auth
Doc and Course Taglibs
Course and Content IDs are passed in
Breadcrumb
Create.jsp
<bbUI:step title="Content Information" number="1">
<bbUI:dataElement label="Title">
<input type="text" name="title" size='50'>
</bbUI:dataElement>
<bbUI:dataElement label="Description">
<TEXTAREA COLS="50" ROWS="15“ NAME="maindata"> </TEXTAREA>
</bbUI:dataElement>
</bbUI:step>
<bbUI:step title="Options" number="2">
<bbUI:dataElement label="Do you want to make the content visible"><FONT size="2" face="Arial, Helvetica, sans-serif"><input type="Radio" name="isAvailable" value="true" checked>Yes <input type="Radio" name="isAvailable" value="false">No </bbUI:dataElement>
<bbUI:dataElement label="Do you want to track number of views"><FONT size="2" face="Arial, Helvetica, sans-serif"><input type="Radio" name="isTrack" value="true" >Yes <input type="Radio" name="isTrack" value="false" checked>No </bbUI:dataElement>
<bbUI:dataElement label="Do you want to add Metadata?"><FONT size="2" face="Arial, Helvetica, sans-serif"><input type="Radio" name="isDescribe" value="true" >Yes <input type="Radio" name="isDescribe" value="false" checked>No </bbUI:dataElement>
</bbUI:step>
Create.jspCreate.jsp
Create.jsp
<bbUI:stepSubmit title="Submit" number="3" />
</bbUI:coursePage>
</bbUI:docTemplate>
</bbData:context>
Create.jsp
Create_proc.jsp
Just the Highlights!
// retrieve the Db persistence manager from the persistence service
BbPersistenceManager bbPm = BbServiceManager.getPersistenceService().getDbPersistenceManager();
// generate the internal IDs for the course and parent
Id courseId = bbPm.generateId(Course.COURSE_DATA_TYPE,request.getParameter("course_id"));
Id parentId = bbPm.generateId(CourseDocument.COURSE_DOCUMENT_DATA_TYPE,request.getParameter("parent_id"));
// create a new content iteam
Content courseDoc = new Content();
//set the title
courseDoc.setTitle(request.getParameter("title"));
Create_proc.jsp
// set the main data (as HTML data)
String strMainData = request.getParameter("maindata");
FormattedText text = new FormattedText(strMainData,FormattedText.Type.HTML);
courseDoc.setBody( text );
// set the parent ID
courseDoc.setParentId(parentId);
// set the content handler
courseDoc.setContentHandler( "resource/x-bb-samplecontent" );
// set the course ID
courseDoc.setCourseId( courseId );
// Set to Track the content or not
String strTracked = request.getParameter("isTrack");
if (strTracked.equalsIgnoreCase("true")) {
courseDoc.setIsTracked(true);
} else {
courseDoc.setIsTracked(false);
}
Create_proc.jsp
// validate the new content item
courseDoc.validate();
// Persist the object
ContentDbPersister contentPersister = (ContentDbPersister) bbPm.getPersister( ContentDbPersister.TYPE );
contentPersister.persist( courseDoc );
Modify and Modify_proc
Almost identical to create process. See the sample Content Handler for details Remove is optional clean up
Demonstration
We covered the most basic…
Let’s touch on more advanced topics:– Storing additional parameters– Relative Referencing of the content_id– Linking to external resources– Import/Export/Copy/Migration Issues
Storing additional parameters
What types of data do you want to store? In what do you want to store it?
– In JAVA property files– As XML?– As Serialized Java Objects?– In your own proprietary (and somewhat creative formats)
Where do you store the parameters?– In the webapp’s config directory?– In the content’s directory– In the content itself (hidden)– Externally
Storing additional parameters
Using the webapps config dir
// Get the Configuration Directory
File dir = PlugInUtil.getConfigDirectory(“bb","sample-contenthandler");
// get the config file
File cfg = new File(dir, “custom.properties");
// If it doesn't exist yet, create a blank one
if (!cfg.exists()) {
cfg.createNewFile();
FileOutputStream f = null;
try {
f = new FileOutputStream(cfg);
} catch (FileNotFoundException e){
out.println("Can't find the file");
}
Properties p = new Properties();
// Write them out to the conf file
p.setProperty(“name",“value");
p.store(f,“My Configuration File");
f.close();
}
Using the content directory
FileSystemService fileSysService; fileSysService =
(FileSystemService)BbServiceManager.lookupService( FileSystemService.class );
java.io.File fileContentDirectory = fileSysService.getContentDirectory(course, courseDocId);
Advantages– Content on file system in this directory is PORTABLE with
import/export/copy/migration– Can be referenced with the @[email protected]@X@ syntax
rather than hard coded
Storing Data in the Content
Why not use the content item itself and store your other data in the MAIN DATA blob?
Use comment blocks to mask your data Advantages: complete portability, no external
dependencies Disadvantages: ALL Data in this field is rendered by the
content engine in the user view.
Externally
You can simply insert a URL to your own content engine in the Blackboard content item.
Advantages: – Many to One relationship between content and raw data– Setup own system for management and deployment
Disadvantages:– Content is ignorant of copy/import/export/migration and all
copies will still point to the hard coded URL
Summary
We’ve seen how to create a new content-handler from scratch
We’ve seen the structure of the webapp and walked through an example of one.
We talked about the various places, structures, and methods of storing content and the advantages and disadvantages of each.