A Groovy Way to Interface With Cascade Server
Creating a Phone Directory & Course PagesTom Wilkinson
Cuyahoga Community College
This presentation is for you if
• You have written programs in some procedural object oriented language
• You have created Data Definitions and Velocity or XSLT formats in Cascade
• You are familiar with Active Directory• You are familiar with Web Services• You need to develop interfaces to Cascade• You know or are willing to learn Groovy
About Me
• Worked at the Tri-C full time since 1974• Worked in IT since 1980• Worked with C# since 2005• Worked with HTML, CSS and JavaScript since
2008• Worked with Groovy since 2013• Married with 3 adult children, 2 grandchildren
and 3 dogs
Agenda
• About Cuyahoga Community College• About Our Project• Groovy• Phone Directory• Velocity• Workforce Training Course Pages• Structured Data Nodes• Questions
About Cuyahoga Community College
• First Community College in Ohio, opened in 1963
• 1,000 credit courses each semester• 600 non-credit courses are offered annually• 60,000 credit and non-credit students each
year• 4 campus locations and 7 other sites
Cuyahoga Community CollegeTri-C
About Cuyahoga Community CollegeStudent Profile
• Average age is 29 years old• Student ages range from 15 to 75+• 61% are women• 39% are from minority groups• 65% study part-time • 56% are seeking an associate degree or are taking courses to
prepare for transfer to a four-year institution • 30% are focusing in areas related to health careers• 17% attend only evening or weekend classes • 67% are enrolled in technical job training courses• 17% are enrolled in business programs
About Our ProjectGoals
• Create one site to serve both mobile and desktop
• Fast site with less pages, images and documents that are more timely and accurate
• A CMS platform that is easy to maintain and update
• A CMS that will allow us the flexibility to modify CSS, HTML and JavaScript quickly to meet Interactive Communications needs
About Our ProjectCurrent Status
• We plan to go live with the new site the third week of November 2014
• We had Cascade for 1.5 years but the project was delayed by non-technical reasons
• Curent site has over 2,500 pages, over 6,200 documents and over 3,400 images
GroovyWhy?
• PHP is forbidden by our Office of Safe and Secure Computing
• Works with Cascade Web Services• Easy for C# developers to understand• Less verbose then Java• Can (practically) do anything Java can do• Banner XE uses Groovy
GroovySample Code
1. package groovytest2. import groovy.sql.Sql3. class NewGroovyClass { 4. static main(args) { 5. def configFile = new File('config.groovy').toURI().toURL(); 6. def config = new ConfigSlurper().parse(configFile)7. def sql = Sql.newInstance(config.sqlConnection)8. sql.eachRow( 'select * from Status' ) { 9. println "$it.id -- ${it.Name}" 10. } 11. }12. }config.groovy: sqlConnection = 'jdbc:jtds:sqlserver://testserver/Test_DB'
Phone DirectoryOverview
Phone DirectoryProcess Part 1
• Groovy application queries Active Directory for all staff that are not hidden
• Reformats department names and locations• Creates XML document on an internal web
server
Phone DirectoryProcess Part 2
• Cascade reads in XML feed block during page publishing and a velocity script converts it to JSON and imbeds it in the Phone Directory page
• The published Phone Directory page is a Single Page Application (SPA) containing the search functionality
Phone DirectoryTool
• Gradle 1.8• IntelliJ IDEA 13.1 (or whatever you like)• Visual Studio 2013 for HTML, CSS and
JavaScript (or whatever you like)
Phone DirectoryLibraries
• Groovy 2.3.3• org.apache.directory.api 1.0.0-M24• groovy-ldap • org.slf4j 1.7.7• ch.qos.logback 1.1.2• activation 1.0.2• javax.mail 1.4.7• Jquery 1.11• Telerik Kendo UI (JavaScript Library)
Groovy LDAPwith Apache Directory LDAP API
def ret = new ArrayList<Person>()def ldap = LDAP.newInstance(uri, user, password)ldap.eachEntry ("(&(objectclass=user)(objectcategory=person)(employeeNumber=*))") { person -> def p = new Person() p.department = DepartmentFilter(person.department) p.email = person.mail p.fax = person.facsimiletelephonenumber p.isFaculty = IsFaculty(person.memberof) p.location = MakeLocation(person.businesscategory, person.streetaddress) p.name = MakeName(person.sn, person.givenname, person.middlename, person.personaltitle) p.firstName = person.givenname p.lastName = person.sn p.phone = person.telephonenumber p.room = person.physicaldeliveryofficename p.title = person.title ret << p}
Phone DirectoryGroovy Classes
Class Name DescriptionApp Setups logging, deletes old logs files, reads
configuration file, calls ADInterface to get user, calls XMLGenerater to output XML file
ADInterface Get all unhidden employees, fixes department names and locations
Person DTO from ADInterface to XMLGenerator
XMLGenerator Creates XML file with person, department and location nodes
DESCodec Decrypt AD users password from configuration file
LogUtility Delete old log files
Phone DirectoryExecution
• Extracted 269 departments• Extracted 11 locations• Extracted 3847 people• Normal end took 1 minutes, 2.314 seconds
Phone DirectoryDemo
VelocityTips
• Empty inner HTML is turn into an empty tag<a href=“#”></a> <a href=“#”/><a href=“#”> </a> <a href=“#”></a>
• #set will not work with nulls#set($x = ‘old value’)#set($x = function-that-return-null())$x is still ‘old value’
• Must manually escape \ and “ before using $_EscapeTool.javascript for JSON
Workforce Training Course PagesOverview
Workforce Training Course PagesProcess
• Retrieve all workforce courses, sections and prerequisites
• Update or Create corresponding course page• Remove any course pages not in the database
Workforce Training Course PagesTools
• Maven 3.0.5• Gradle 1.8• IntelliJ IDEA 13.1 (or whatever you like)
Workforce Training Course PagesLibraries
• Cascade Web Service generated from WSDL• axis 1.4• Jtds 1.3.1• Jsoup 1.7.3• Groovy 2.3.3• org.slf4j 1.7.7• ch.qos.logback 1.1.2• activation 1.0.2• javax.mail 1.4.7
Workforce Training Course PagesGroovy Classes
Class Description
App Sets up logging, reads configuration file, deletes old log files, setup AdvantageInterface and CascadeInterface then calls BusinessLogic
BusinessLogic Gets courses, sections and prerequisites using AdvantageInterface and updates course pages in Cascade using CascadeInterface, removes old course pages
AdvantageInterface Uses SQL Queries to get Courses, sections and prerequisites
Course DTO for courses
Prerequisite DTO for prerequisites
Section DTO for sections
CascadeInterface Lists pages, reads, updates and copies pages
LogUtility Delete old log files
Workforce Training Course PagesExecution
• Using 45 programs• Retrieved 518 courses• Retrieved 3422 sections• Retrieved 202 prerequisites• Created page course-7249• Created 1 pages and updated 517 pages• Deleted 0 pages• Normal end took 32 minutes, 16.050 seconds
StructuredDataNodeText
1. private static StructuredDataNode CreateNode(String name, String value) {
2. def node = new StructuredDataNode()3. node.type = StructuredDataType4. .fromValue(StructuredDataType._text)5. node.identifier = name6. node.text = value?.trim() ? value : null7. return node8. }
StructuredDataNodeCheckbox
1. private static StructuredDataNode CreateNodeOfCheckbox(String name, Boolean value) {
2. def final checkbox = '::CONTENT-XML-CHECKBOX::'3. def node = new StructuredDataNode()4. node.type = StructuredDataType.fromValue(StructuredDataType._text)5. node.identifier = name6. if (value) {7. node.text = "${checkbox}Yes" 8. } else {9. node.text = checkbox10. }11. return node12. }
StructuredDataNodeHTML
1. private static StructuredDataNode CreateNodeHtml(String name, String value) {
2. def node = new StructuredDataNode()3. node.type = StructuredDataType4. .fromValue(StructuredDataType._text)5. node.identifier = name6. if (value?.trim()) {7. node.text = Jsoup.clean(value, Whitelist.basic())8. } else {9. node.text = null10. }11. return node12. }
StructuredDataNodes
1. data += CreateNodeOfDate('updated', course.updated)2. for (Prerequisite p in course.prerequisites) {3. def prerequisite = []4. prerequisite += CreateNodeOfInt('id', p.id)5. prerequisite += CreateNode('code', p.code)6. prerequisite += CreateNode('number', p.number)7. prerequisite += CreateNode('name', p.name)8. prerequisite += CreateNode('comment', p.comment)9. data += CreateNodeOfNodes('prerequisites',
CreateNodes(prerequisite.toList()))10. }
ResourcesBooks
• Groovy in Action by Dierk König, Guillaume Laforge, Paul King and Cédric Champeau
• Programming Groovy 2: Dynamic Productivity for the Java Developer (Pragmatic Bookshelf) by Venkat Subramaniam
• Velocity: The Basics: Scripting with a $ here and a # to do by James Johnson
ResourcesWeb
• http://groovy.codehaus.org/• http://directory.apache.org/api/groovy-ldap.html• http://www.gradle.org/• http://www.jetbrains.com/idea/• http://www.slf4j.org/• http://logback.qos.ch/• http://www.telerik.com/kendo-ui• http://jsoup.org/• http://jtds.sourceforge.net/• https://
github.com/hannonhill/Webservices-Java-Sample-Project
Questions
• [email protected]• (216) 987-3666• Github: https://github.com/Tri-C