hidden treasures in project wonder

57
Spirit of Mike Schrag Whereabouts Unknown Channeled By Chuck Hill Global Village Consulting Hidden Treasures in Project Wonder

Upload: wo-community

Post on 10-May-2015

14.621 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Hidden Treasures in Project Wonder

Spirit of Mike SchragWhereabouts Unknown

Channeled By Chuck HillGlobal Village Consulting

Hidden Treasures in Project Wonder

Page 2: Hidden Treasures in Project Wonder

What You See

• Mike’s Step 1: Look at every damn method in Wonder.

• Mike’s Step 1a: Seriously. Every one.

• Mike’s Step 2: “Cool” = Chosen

Page 3: Hidden Treasures in Project Wonder

What You Get

• Notification of existence

• Nothing in-depth

Page 4: Hidden Treasures in Project Wonder

Type-safe pageWithName

• <T extends WOComponent> T pageWithName(Class<T> componentClass)

• ERXApplication, ERXDirectAction, ERXComponent

• less typing

• refactoring updates them

• compiler errors for speeling errors

Page 5: Hidden Treasures in Project Wonder

Type-safe pageWithNameold wayMyPage page = (MyPage)pageWithName(“MyPage”);

new wayMyPage page = (MyPage)pageWithName(MyPage.class.getName());

cool wayMyPage page = pageWithName(MyPage.class);

Page 6: Hidden Treasures in Project Wonder

IVersionManager• better control of static resource caching

• infinite expiration in Apache

• change resource url when resource changes

• pluggable versioning schemes

• “default” = WebObjects default

• “properties” = specify version numbers in properties

• your own

Page 7: Hidden Treasures in Project Wonder

PropertiesVersionManagerpropertieser.extensions.ERXResourceManager.versionManager=propertieser.extensions.ERXResourceManager.versionManager.default=10er.extensions.ERXResourceManager.versionManager.bundleName.resourceName=20

produces/WebObjects/YourApp.woa/WebServerResources/awesomeImage.png?10/WebObjects/bundleName/WebServerResources/resourceName?20

Page 8: Hidden Treasures in Project Wonder

ERXDirectAction / log4jurl/wa/ERXDirectAction/log4j?pw=somepw

propertieser.extensions.ERXLog4JPassword=somepw

Page 9: Hidden Treasures in Project Wonder

ERXDirectAction / log4j

Page 10: Hidden Treasures in Project Wonder

ERXDirectAction / eoAdaptorDebugging

url/wa/ERXDirectAction/eoAdaptorDebugging?debug=on&pw=somepw/wa/ERXDirectAction/eoAdaptorDebugging?debug=off&pw=somepw

propertieser.extensions.ERXEOAdaptorDebuggingPassword=somepw

Page 11: Hidden Treasures in Project Wonder

ERXMainRunner

• initializes all of Wonder

• runs “main” method inside of an Application context

• java -classpath ... er.extensions.appserver.ERXMainRunner -mainClass YourClass

Page 12: Hidden Treasures in Project Wonder

ERXApplication._rewriteURL

• Pretty URLs

• One generator method to rule them all

Page 13: Hidden Treasures in Project Wonder

ERXApplication._rewriteURL (simple method)

propertieser.extensions.ERXApplication.replaceApplicationPath.pattern= ↵/cgi-bin/WebObjects/YourApp.woa

er.extensions.ERXApplication.replaceApplicationPath.replace= ↵/yourapp

produceshttp://server.com/yourapp/wa/default

apache rewrite ruleRewriteRule ^/yourapp(.*)$ /cgi-bin/WebObjects/YourApp.woa$1 [PT,L]

Page 14: Hidden Treasures in Project Wonder

ERXApplication._rewriteURL (complex method)

Application subclass@Overridepublic String _rewriteURL(String url) { return convertURLWithFancyRegexOrSomething(url);}

apache rewrite rulerewrite rule has to be an inverse of your _rewriteURL implementation

Page 15: Hidden Treasures in Project Wonder

ERXRedirect

• drop-in replacement for WORedirect

• can redirect to a component instance rather than a direct action

• generates document.location.href=... in Ajax request

• https support

• api for setting query parameters

Page 16: Hidden Treasures in Project Wonder

ERXRedirectpublic WOActionResults doSomething() { ERXRedirect redirect = pageWithName(ERXRedirect.class); NextPage nextPage = pageWithName(NextPage.class); nextPage.setState(someStateFromThisPage); redirect.setComponent(nextPage); return redirect;}

Page 17: Hidden Treasures in Project Wonder

ERXSession.useSecureSessionCookies

• secure cookies are only sent across https requests

• wosid and woinst are not secure cookies by default (and thus vulnerable to sniffing off a non-https url)

Page 18: Hidden Treasures in Project Wonder

ERXSession.useSecureSessionCookies

@Overridepublic boolean useSecureSessionCookies() { return true;}

or

er.extensions.ERXSession.useSecureSessionCookies=true

Page 19: Hidden Treasures in Project Wonder

ERXFlickrBatchNavigation• WOBatchNavigationBar looks like ass

• ERXFlickrBatchNavigation does not

• Drop-in replacement of WOBatchNavigationBar

Page 20: Hidden Treasures in Project Wonder

ERXDataHyperlink

• Like WOHyperlink but with object-based attribute passing

• Automagically calls accessor methods on pageName component

• Safe ... doesn’t leak data to user

• An example will make more sense

Page 21: Hidden Treasures in Project Wonder

ERXDataHyperlinkPersonList page<wo:ERXDataHyperlink pageName=”PersonEdit” ↵ person=”$currentPerson”> edit person</wo:ERXDataHyperlink>

PersonEdit pagepublic class PersonEdit extends WOComponent { ... public void setPerson(Person person) { _person = person; }}

Page 22: Hidden Treasures in Project Wonder

ERXInlineTemplate

• Generate a WOComponent on-the-fly

• Generate a WOComponent from a database (i.e. a CMS)

• Take over the world?

Page 23: Hidden Treasures in Project Wonder

ERXInlineTemplatebasic<wo:ERXInlineTemplate html=”$someHtmlString” wod=”$someWodString”/>(using woognl doesn’t require a wod)

cache generated component<wo:ERXInlineTemplate html=”$someHtmlString” wod=”$someWodString” cacheKey=”MyCacheKey” cacheVersion=”$computedVersionObject”/>(when cacheVersion changes, regenerate)

Page 24: Hidden Treasures in Project Wonder

ERXWOComponentContent / ERXWOTemplate

• WOComponentContent but with multiple content areas

• example: a DialogComponent has a “title” area and a “content” area

Page 25: Hidden Treasures in Project Wonder

ERXWOComponentContent / ERXWOTemplate

DialogComponent<div> <div><wo:ERXWOComponentContent templateName=”title”/></div> <div><wo:ERXWOComponentContent templateName=”content”/></div></div>

CallingComponent<wo:DialogComponent> <wo:ERXWOTemplate templateName=”title”> this is the title and you can put real components in here </wo:ERXWOTemplate> <wo:ERXWOTemplate templateName=”content”> this is the content of the dialog </wo:ERXWOTemplate></wo:DialogComponent>

Page 26: Hidden Treasures in Project Wonder

ERXLoremIpsumGenerator

• sometimes you just need fake content (test cases, load tests, mockups)

• “Lorem ipsum dolor sit amet, ...”

• ERXLoremIpsumGenerator.paragraph(3) = 3 paragraphs

• ERXLoremIpsumGenerator.sentence(1) = 1 sentence

• ERXLoremIpsumGenerator.words(10) = 10 words

Page 27: Hidden Treasures in Project Wonder

Captchas and Spam Checks

• ERXSimpleSpamCheck (ERExtensions.framework)sets a hidden field with javascript

• ERReCaptcha (ERCaptcha.framework)reCAPTCHA wrapper (http://www.google.com/recaptcha)

• ERAkismet (ERCaptcha.framework)Akismet wrapper (http://akismet.com); spam checks blog comments

Page 28: Hidden Treasures in Project Wonder

Captchas and Spam Checks

• calls validationFailedWithException on failure

• sets “valid” binding accordingly

Page 29: Hidden Treasures in Project Wonder

Captchas and Spam Checks

<wo:form> <wo:ERXSimpleSpamCheck />

<wo:WOTextField value=”$firstName” /> <wo:WOSubmitButton action=”$doSomething” /></wo:form>

Page 30: Hidden Treasures in Project Wonder

ERXRssPage• quickly produce RSS feeds

• feedTitle, feedUrl, feedDescription

• list : list of items to show in the feed

• item : repetition item

• itemGuid, itemTitle, itemLink, itemPubDate, itemAuthor

• description from WOComponentContent

Page 31: Hidden Treasures in Project Wonder

ERXRssPage<wo:ERXRssPage feedTitle=”RSS of People” feedUrl=”http://yourhost.com” feedDescription=”This is my list of people!” list=”$people” item=”$person” itemGuid=”$person.primaryKey” itemTitle=”$person.fullName” itemLink=”$someURLToThePerson” itemPubDate=”$person.creationDate” />

Page 32: Hidden Treasures in Project Wonder

ERXWORepetition

• WORepetition relies on repetition item indexes

• changing item order = you just clicked “delete” on the wrong row ... whoops

• uses key instead of index

• small risk of collision, but unlikely in tests (use uniqueKey binding to prevent)

Page 33: Hidden Treasures in Project Wonder

ERXWORepetitionproperties# use hash codes of objects instead of indexer.extensions.ERXWORepetition.checkHashCodes=true

# throw an exception if a match isn’t founder.extensions.ERXWORepetition.raiseOnUnmatchedObject=true

unique keys# use item PKs instead of hash codes<wo:ERXWORepetition uniqueKey=”$person.primaryKey”> ...

Page 34: Hidden Treasures in Project Wonder

External Services

• ERXGoogleSpell.correct(String)

• spelling correction like Google’s “did you mean”

• ERXYahooContentAnalysisService.termExtraction(..)

• extracts important terms from text

• useful for guessing ERTaggable tags

• Access keys required, read Javadoc for details

Page 35: Hidden Treasures in Project Wonder

ERXEnterpriseObjectCache

• caches EO’s based on a keypath

• optionally filter with qualifier (dynamically updates!)example: two caches -- published=true, published=false

• optional timed expiration

Page 36: Hidden Treasures in Project Wonder

ERXEnterpriseObjectCache

• use this constructor and shouldRetainObjects=true!

public ERXEnterpriseObjectCache(String entityName, String keyPath, EOQualifier qualifier, long timeout, boolean shouldRetainObjects, boolean shouldFetchInitialValues)

Page 37: Hidden Treasures in Project Wonder

ERXEnterpriseObjectCache

# cache any CMSPage objects by their “name” key # that are published=true# expire them after 60 secondsERXEnterpriseObjectCache cache = new ERXEnterpriseObjectCache( CMSPage.ENTITY_NAME, CMSPage.NAME_KEY, CMSPage.PUBLISHED.isTrue(), 60 * 1000);

EOEditingContext editingContext = ERXEC.newEditingContext();CMSPage homePage = cache.objectForKey(editingContext, “HomePage”);homePage.setPublished(false);editingContext.saveChanges();# published = false, so it is dynamically removed from the cache

Page 38: Hidden Treasures in Project Wonder

ERXEOControlUtilities

• ERXEOControlUtilities.convertEOtoGID / convertGIDtoEOrecursively convert data structures from EO’s to GID’s (NSDictionary of String to NSArray of EO’s becomes NSDictionary of String to NSArray of GID’s, etc) and the corresponding inverse method

Page 39: Hidden Treasures in Project Wonder

ERXEOControlUtilities

• ERXEOControlUtilities.eoEqualscompare two EO’s, returning true if their GID’s match, regardless of the EOEditingContext that contains both of them

• ERXEOControlUtilities.aggregateFunctionWithQualifierperform MIN/MAX/AVG/etc database functions on attributes of an entity without writing custom SQL

Page 40: Hidden Treasures in Project Wonder

Automatic Batch Faulting• Common problem: Fetch array of Person

objects, show them in a table, for each row, show the person.company().name()

• Common solution: Manually batch fetch “company.name” on the Person objects.

• Bad-ass solution:er.extensions.ERXDatabaseContextDelegate.autoBatchFetchSize=50

• Automatically batch fetches faulted relationships on all EO’s that were fetched from the same query

Page 41: Hidden Treasures in Project Wonder

Automatic Batch FaultingNSArray<Person> people = ec.objectsWithFetchSpecification(fspec);

# this automatically faults all the companies for # the person objects in the “people” array (up to # your 50 max specified in the property)Company comp = people.objectAtIndex(0).company();String name = comp.name();

# this automatically faults all the employees for # all the companies that were just batch fetched # above -- it’s magic and recursiveNSArray<Person> employees = comp.employees();

# restricts to only the visible objects if attached # to a display group

Page 42: Hidden Treasures in Project Wonder

ERXUnitAwareDecimalFormat

• automatically format bytes/meters/grams/seconds in metric decimal form

• scales to appropriate unit based on size

• 1234567890 bytes becomes “1.15GB”

NumberFormat formatter = new ERXUnitAwareDecimalFormat(ERXUnitAwareDecimalFormat.BYTE);formatter.setMaximumFractionDigits(2);formatter.format(1234567890.0);

Page 43: Hidden Treasures in Project Wonder

ERXJDBCAdaptor

• fixes double connection bug from jdbcInfo

• should just be the default

• er.extensions.ERXJDBCAdaptor.className = er.extensions.jdbc.ERXJDBCAdaptor

Page 44: Hidden Treasures in Project Wonder

ERXMutableURL

• java.net.URL is garbage. ERXMutableURL is not.

• mutable interface to a URL object

• add query parameters one-by-one

• supports weird “urls” like “javascript:” and incomplete “/wa/something”

Page 45: Hidden Treasures in Project Wonder

ERXMutableURLERXMutableURL url = new ERXMutableURL( "http://yourhost.com:80/tutorial/index.html?key1=value1#someref");url.setRef(null);url.removeQueryParameter("key1");url.addQueryParameter("key2", “value2”);url.addQueryParameters(“key3=value3&key4=value4”);

java.net.URL javaneturl = url.toURL();String urlString = url.toExternalForm();

Page 46: Hidden Treasures in Project Wonder

ERXThreadStorage

• a ThreadLocal dictionary that resets for each request

• Object obj = ERXThreadStorage.valueForKey(String)

• ERXThreadStorage.takeValueForKey(Object, String)

• common uses: current user, current session, current context

Page 47: Hidden Treasures in Project Wonder

ERXValueUtilities• convert objects to various common types

including “default” form

• example:booleanValue(Object) / booleanValueWithDefault(Object, boolean def)

• supports boolean, Boolean, int, Integer, float, Float, double, Double, long, Long, array, set, dictionary, data, bigDecimal, enum

• converts from every possible form for you -- handy for bindings

Page 48: Hidden Treasures in Project Wonder

ERMemoryAdaptor

• acts like a database, but just talking to dictionaries

• great for test cases

• no SQL support -- don’t try to get tricky

• Include JavaMemoryAdaptor.framework

• dbConnectAdaptorGLOBAL=Memoryor[ModelName].adaptor=Memory

Page 49: Hidden Treasures in Project Wonder

ERPDFWrapper

• Turn any HTML+CSS page into a PDF

• Include ERPDFGeneration.framework

• <wo:ERPDFWrapper><html> ...</wo:ERPDFWrapper>

• Done. That’s just cool.

Page 50: Hidden Treasures in Project Wonder

PFProfiler / SESnapshotExplorer

• These are in another talk.

• They’re cool, though.

• Pay attention during that talk.

Page 51: Hidden Treasures in Project Wonder

ERXResponseRewriter.Delegate

• intercept all resource insertions, optionally replacing (or denying) them

• example:you have your own prototype.js and you want to replace Ajax.framework’s version with yours

• via properties (for simple cases) or via custom delegate

• responseRewriterWillAddResource

Page 52: Hidden Treasures in Project Wonder

ERXResponseRewriter.Delegate

propertieser.extensions.ERXResponseRewriter.resource.[framework].[filename]=[newFramework].[newFileName]er.extensions.ERXResponseRewriter.resource.Ajax.prototype.js= app.myprototype.js

delegate (example replaces EVERY file with myfile.png -- be smarter)ERXResponseRewriter.setDelegate(new ERXResponseRewriter.Delegate() { public boolean responseRewriterShouldAddResource( String framework, String fileName) { return true; }

public ERXResponseRewriter.Resource responseRewriterWillAddResource( String framework, String fileName) { return new ERXResponseRewriter.Resource(“app”, “myfile.png”);});

Page 53: Hidden Treasures in Project Wonder

applyRestrictingQualifierOnInsert

• er.extensions.ERXEnterpriseObject.applyRestrictingQualifierOnInsert=true

• makes new objects automatically match their entity’s restricting qualifier

• i.e. if Employee is “personType = 5”, a new Employee will automatically have personType = 5 set on it

• no more awakeFromInsertion junk

Page 54: Hidden Treasures in Project Wonder

secureDisabled

• You use DirectConnect

• You don’t have SSL in dev

• You want to run your app

• er.extensions.ERXRequest.secureDisabled=true

• Turns off all https URL generation -- only works in dev

Page 55: Hidden Treasures in Project Wonder

ERXAdaptorChannelDelegate

• conditionally log slow SQL execution (and some other cool debugging stuff)

• took 100ms, log.info the expression

• took 1000ms, log.warn the expression

• etc ...

Page 56: Hidden Treasures in Project Wonder

ERXAdaptorChannelDelegate

propertieser.extensions.ERXAdaptorChannelDelegate.enabled=trueer.extensions.ERXAdaptorChannelDelegate.trace.milliSeconds.debug=0er.extensions.ERXAdaptorChannelDelegate.trace.milliSeconds.info=100er.extensions.ERXAdaptorChannelDelegate.trace.milliSeconds.warn=1000er.extensions.ERXAdaptorChannelDelegate.trace.milliSeconds.error=5000

Page 57: Hidden Treasures in Project Wonder

Q&ASpirit of Mike SchragWhereabouts Unknown

Channeled By Chuck HillGlobal Village Consulting