Week ago I wrote about unusual way of handling exceptions in Filenet Workplace.
Today I found another "gem":
[java] try { invokeNamedEvent(eventName, uiModule, request, new WcmEventResponse(response, this, okToRedirect));
// If a non-null return value was returned from the invoke, check for true/false. If the // result matches "false", set the redirect flag to true indicating to cancel processing // of the page. Object result = request.getAttribute(INVOKE_RETURN_VALUE); if ( result != null result.toString().equals(String.valueOf(false)) ) sendRedirectCalled = true; } catch (Exception e) { throw e; }
[/java]
Why to catch an exception here? And why string comparison is used when Boolean has a constructor with the String parameter?
It seems that Filenet doesn't use any of code review procedures internally. Developers just hack the code all day, make no comments and only two of them really understand the whole Filenet Workplace system. Or it was written long time ago by developer, which left the company, and nobody has time and/or will to do a proper system.
Technorati Tags: filenet, source, exceptions
I was thinking about Web 2.0 and found some similarities between them and dotcoms:
dotcoms | Web 2.0 |
Generated a lot of ideas revolving around web enabling of normall stuff | Generate a lot of ideas revolving around web enabling of normall stuff |
Generated some ideas and generated a lot of copies of the same ideas | Generate some ideas and generated a lot of copies of the same ideas |
Nobody thought of generating revenue from ideas | Nobody thinks about revenue |
Most of the sites were maid to be sold to venture capitalits | Most of the sites are maid to be sold to survived dotcoms |
History repeating, huh?
Remote control with WiFi support - the way to go. The remote control should understand modern devices and be able to sense all of them and get useful metadata: song names, volumes, etc...
This one looks like very promising solution when I will need to convert normal Java beans to Filenet's property bags.
Technorati Tags: filenet, object mapping, java, library, open source
First, declare this:
[java] private Exception configureWindowIdException = null; [/java]
Then, in ConfigurePage function, do this:
[java] public void configurePage(ServletContext applicationValue, HttpServletRequest request, long windowIdMode) throws Exception { ... skipped ... configureWindowId(request);
// If configureWindowId constructed an exception, throw it. if ( configureWindowIdException != null ) { if ( !sp.isSignedIn() ) { // We attempted to propogate a window Id when not signed in // probably the result of signing out of an info page. // Don't throw. Fix the windowId to mainWindow instead. // WindowID assignedId = new WindowID(null); WindowID currentId = new WindowID(null); assignWindowId(assignedId, currentId, false); configureWindowState(); postProcessWindowId(assignedId, currentId, currentId, false, false, false, false, false); } else throw configureWindowIdException; } ... skipped ...
}
[/java]
What about good old try-catch?
There is no proper exception handling in Workplace. Should I send this piece to The Daily WTF?
While discovering internals of Filenet Workplace I decided to create a class diagram.
Here is the starting diagram:
Apparently there is something wrong with the inheritance and everything use everything else and share the data. This is not OOP, it's good old VB style of programming done by somebody, who was converted to a java programmer by management decision.
More to go...
Technorati Tags: filenet, architecture, software design, uml
Created a new web project project in Rational Software Architect and imported Workplace into it. Right after the start discovered that it fails to run on localhost. "Huh? This is strange". Looked up the source code and found that marvelous piece of code:
[java] / * Validates HostName * @param hostName The host nema to validate * @return true, if valid. / public static boolean validateHostName( String hostName ) { return !hostName.equalsIgnoreCase("localhost") !validateIP(hostName); } [/java]
What?! It just checks for localhost and validates IP of a host name. Ok, let's look into validateIP function:
[java] / * Validates a String as a valid IP address. Checks for four parts, and that * each part represents a numeric value between 0 and 255. * @param ipAddress * @return / public static boolean validateIP( String ipAddress ) { boolean isValid = false;
StringTokenizer st = new StringTokenizer(ipAddress, "."); if ( st.countTokens() == 4 ) { isValid = true; while ( isValid st.hasMoreTokens() ) isValid = validateUnsignedByte(st.nextToken()); } return isValid; }
[/java]
Apparently there is no validation of correct IP address and Workplace should work normally if it would be started using
127.0.0.1
So I commented out first part of the code and Workspace now works on my localhost with no problems.
Originally uploaded by CTPEKO3A.
This is one of my best photos. I made it more than two years ago, 11th October 2003, on Lincoln road, Miami.
I like that this image has at least three layers of reflections and still is not that messy.
The corporate policy setting on my work notebook always sets the screen saver to 15 minutes and require login password. I don't mind to have a screen save 15 minutes, but that login requirement... I just hate it! And I hate it mostly because the screen saver tab in the Display Properties dialog is disabled by the same policy!
Now I found the way to cheat on corporate policy - I created a simple .reg file, which will change one DWORD value:
HKCUSoftwarePoliciesMicrosoftWindowsControl PanelDesktopScreenSaverIsSecure = "0"
Ahh, back to work...
Everybody, who worked with Rational tools could think that there is nothing rational in them. And frustration mounts when you'll try to read the supplied documentation. The documentation is structured, but some pages are very shallow and others do not explain topics in undestandable language.
This article is very helpful. It actually shows how to structure design files, so the design will be understandable by anyone in the project.
At the end of page is a little gem: Software Architecture Document for the project, described in the article. Very very helpful!
This is a little step by step guide on how to create and register custom service with JMX interface on WebSphere:
[java]
com.ibm.websphere.runtime.CustomService
com.ibm.websphere.management.JMXManageable
[/java]
This method has a parameter, Properties, which will contain properties defined via WS Administration console. We are interested in one property: externalConfigURLKey. This property contains path to external configuration file (if any is needed).
This is how to get the path:
[java]
public void initialize(Properties configProperties) throws Exception { readConfig(configProperties.getProperty(externalConfigURLKey)); }
[/java]
shutdown() method may be left blank.
implement getType() method (inherited from JMXManageable):
[java]
public String getType() { return "MyMBean"; }
[/java]
Remember the name you returned here!
[java]
public Properties getMBeanProperties() { Properties props = new Properties(); props.put("SpecialProperty", "value"); return props; }
[/java]
I think this will return a list of properties, not declared in MBean descriptor. Read only, of course, since there is no setMBeanProperties() method.
[java]
public String getUserName() { return this.userName; }
public void setUserName(String param) { this.userName = param; }
[/java]
[xml]
[/xml]
IMPORTANT: Make sure that type matches the value you remembered on the step 4!
Compile and package. Create .jar, having descriptor in the root. Place .jar somewhere accesible for WebSphere.
Start WebSphere and open Administration console.
Go to Servers - Application Servers - yourserver - Server Infrastructure - Administration - Administration Services
Click on "Extension MBean providers"
Click on "New"
In the "Classpath" entry type the full path and name of your jar (created on step 8)
Type something memorable in two other fields and click Apply.
Click on "Extension MBeans" (on the left)
Click on "New"
Enter the name of MBean descriptor file (see step 7.)
for example:
myTest.xml
Enter the type name of your MBean. IMPORTANT: must be the same name as it was on steps 4 and 7.
Click Apply.
Go to Servers - Application Servers - yourserver - Server Infrastructure - Administration - Custom Services
Click New
Place check on "Enable service at server startup".
Enter full class name (with package) of your MBean class (the one we created on step 1) into "Classname" field.
Enter something memorable in "Display Name"
Enter fill path and file name of the jar file (step 8) into "Classpath".
If your service requires configuration file (step 2) enter full path to it into " External Configuration URL"
Click on Apply.
Click on Save (on top)
Click Save.
Restart the server.
Here are the commands, used to verify MBean from admin console:
To run console:
wsadmin.bat -conntype SOAP -port 8881
To make sure that MBean started:
$AdminControl queryNames :,type=>
Store MBean in Tcl variable:
set mybean [$AdminControl queryNames :,type=MBeanName]
See MBean description:
$Help all $mybean
See MBean attributes and values:
$AdminControl getAttributes $mybean
Set specific attribute:
$AdminControl setAttribute $mybean UserName mike
HKCUSoftwarePoliciesMicrosoftWindowsControl PanelDesktopScreenSaverIsSecure = "0"
Ahh, back to work...
The steps are:
Some sources recommended installing IBM Agent Controller, which didn't solved the problem. Other sources recommended to create additional WebSphere profile, which didn't solved the problem either, but was quite useful because it's a way to create websphere instance somewhere close to the root folder, so I don't have to go to the "C:Program FilesIBMRationalSATrial6.0runtimesbase_v6blablatwenty_more_blas" to get to the server logs...
Now my dev environment is completed and I can start normal life. websphere rational hack]]>
Place the start point in the top-left corner.
Simplify operations requiring flow charts.
Question “black-hole” activities.
Question “miracle” activities.
Reflect the previous activity by using decision points.
Avoid superfluous decision points.
Ensure that each transition leaving a decision point has a guard.
Do not overlap guards.
Ensure that guards on decision points form a complete set.
Ensure that exit transition guards and activity invariants form a complete set.
Apply an [otherwise] guard for “fall-through” logic.
Model guards only if they add value.
Ensure that forks have corresponding joins.
Ensure that a fork has only one entry transition.
Ensure that a join has only one exit transition.
Avoid superfluous forks.
Order swimlanes in a logical manner.
Apply swimlanes to linear processes.
Have less than five swimlanes.
Consider swimareas for complex diagrams.
Reorganize into smaller activity diagrams when swimareas include several activities.
Consider horizontal swimlanes for business processes.
Model the key activities in the primary swimlane.
Apply state names when an object appears several times.
Reflect the life-cycle stage of an action object in its state name.
Show only critical inputs and outputs.
Depict action objects as smaller than activities.
Strive for left-to-right ordering of messages.
Give an actor the same name as a class, if necessary.
Include a prose description of the logic.
Place proactive system actors on the left-most side of your diagram.
Place reactive system actors on the right-most side of your diagram.
Avoid modeling object destruction.
Don’t sweat activation boxes.
Name objects when you reference them in messages.
Name objects when several of the same type exist.
Apply textual stereotypes to classifiers consistently.
Apply visual stereotypes sparingly.
Focus on critical interactions.
Justify message names beside the arrowhead.
Create objects directly.
Apply operation signatures for software messages.
Apply prose for messages involving human and organization actors.
Prefer names over types for parameters.
Indicate types as parameter placeholders.
Apply the > stereotype for use case invocations.
Do not model obvious return values.
Model a return value only when you need to refer to it elsewhere on a diagram.
Justify return values beside the arrowhead.
Model return values as part of a method invocation.
Indicate types as return-value placeholders.
Indicate the actual value for simple return values.
Create class package diagrams to logically organize your design.
Create UML component diagrams to physically organize your design.
Place inheriting packages below base packages.
Vertically layer class package diagrams.
Create use case package diagrams to organize your requirements.
Include actors on use case package diagrams.
Horizontally arrange use case package diagrams.
Give packages simple, descriptive names.
Make packages cohesive.
Indicate architectural layers with stereotypes on packages.
Avoid cyclic dependencies between packages.
Reflect internal relationships in package dependencies.
Identify responsibilities on domain class models.
Indicate visibility only on design models.
Indicate language-dependent visibility with property strings.
Indicate types on analysis models only when the type is an actual requirement.
Be consistent with attribute names and types.
Model association classes on analysis diagrams.
Center the dashed line of an association class.
Use common terminology for class names.
Prefer complete singular nouns for class names.
Name operations with a strong verb.
Name attributes with a domain-based noun.
Do not model scaffolding code.
Do not model keys.
Never show classes with just two compartments.
Label uncommon class compartments.
Include an ellipsis ( . . . ) at the end of incomplete lists.
List static operations/attributes before instance operations/attributes.
List operations/attributes in decreasing visibility.
For parameters that are objects, list only their type.
Develop consistent operation and attribute signatures.
Avoid stereotypes implied by language naming conventions.
Indicate exceptions in an operation’s property string.
Reflect implementation language constraints in interface definitions.
Name interfaces according to language naming conventions.
Prefer “lollipop” notation to indicate realization of an interface.
Define interfaces separately from your classes.
Do not model the operations and attributes of interfaces in your classes.
Model collaboration between two elements only when they have a relationship.
Model a dependency when the relationship is transitory.
Tree-rout similar relationships to a common class.
Always indicate the multiplicity.
Avoid a multiplicity of “*”.
Replace relationship lines with attribute types.
Do not model implied relationships.
Do not model every dependency.
Center names on associations.
Write concise association names in active voice.
Indicate directionality to clarify an association name.
Name unidirectional associations in the same direction.
Word association names left to right.
Indicate role names when multiple associations between two classes exist.
Indicate role names on recursive associations.
Make associations bi-directional only when collaboration occurs in both directions.
Redraw inherited associations only when something changes.
Question multiplicities involving minimums and maximums.
Apply the sentence rule for inheritance.
Place subclasses below superclasses.
Beware of data-based inheritance.
A subclass should inherit everything.
Be interested in both the whole and the part.
Place the whole to the left of the part.
Apply composition to aggregates of physical items.
Apply composition when the parts share their persistence life cycle with the whole.
Don’t worry about the diamonds.
Name use cases using domain terminology.
Imply timing considerations by stacking use cases.
Place your primary actor(s) in the top-left corner of the diagram.
Draw actors on the outside edges of a use case diagram.
Name actors with singular, domain-relevant nouns.
Associate each actor with one or more use cases.
Name actors to model roles, not job titles.
Use > to indicate system actors.
Don’t allow actors to interact with one another.
Introduce an actor called “time” to initiate scheduled events.
Indicate an association between an actor and a use case if the actor appears within the use case logic.
Avoid arrowheads on actor-use case relationships.
Apply > when a use case may be invoked across several use case steps.
Apply > associations sparingly.
Generalize use cases when a single condition results in significantly new business logic.
Do not apply >, >, or >.
Avoid more than two levels of use case associations.
Place an included use case to the right of the invoking use case.
Place an extending use case below the parent use case.
Apply the “is like” rule to use case generalization.
Place an inheriting use case below the base use case.
Apply the “is like” rule to actor inheritance.
Place an inheriting actor below the parent actor.
Indicate release scope with a system boundary box.
Avoid meaningless system boundary boxes.
According to this, and that classic Struts will not be extended anymore and there will not be a Struts 2.0. But what is the next big thing? Tapestry? JSF? Cocoon?