<%@ page import="java.net.*, java.text.*, java.io.*, java.util.*, com.jivesoftware.util.*, com.jivesoftware.forum.*, com.jivesoftware.forum.util.*, com.artima.website.*" errorPage="../error.jsp" %> <%@ include file="../global.jincl" %> <% // Get parameters long forumID = forumFactory.getForum(ArtimaConstants.PAVILION_ANNOUNCEMENTS_FORUM).getID(); String weblogsForumID = Long.toString(forumID); long threadID = ParamUtils.getLongParameter(request,"thread",-1L); String subject = ParamUtils.getParameter(request,"subject"); String body = ParamUtils.getParameter(request,"body"); String summary = ParamUtils.getParameter(request,"summary"); boolean fromLogin = ParamUtils.getBooleanParameter(request, "fromLogin", false); boolean isNewPost = (threadID == -1L); if (fromLogin) { if (subject == null) { subject = (String) session.getAttribute("jive.post.subject." + forumID + "." + threadID); } if (summary == null) { summary = (String) session.getAttribute("jive.post.summary." + forumID + "." + threadID); } if (body == null) { body = (String) session.getAttribute("jive.post.body." + forumID + "." + threadID); } // TODO: Dang, got to deal with the topics here... } List topics = Topic.getTopicsForForum(forumID); // The topic checkboxes boolean[] topicChecked = new boolean[topics.size()]; int i = 0; for (Iterator it = topics.iterator(); it.hasNext();) { Topic topic = (Topic) it.next(); String topicHandle = topic.getHandle(); topicChecked[i] = ParamUtils.getBooleanParameter(request, topicHandle, false); ++i; } // Trim subject and body to catch ones that consist of only spaces. subject = StringCleaner.trimAndMakeNullIfEmpty(subject); summary = StringCleaner.trimAndMakeNullIfEmpty(summary); body = StringCleaner.trimAndMakeNullIfEmpty(body); String formButton = ParamUtils.getParameter(request,"formButton"); if (pageUser == null) { // Redirect to ../login.jsp. If the subject, summary, & body are not null, post those // in the session. if (subject != null) { session.setAttribute("jive.post.subject."+forumID+"."+threadID, subject); } if (summary != null) { session.setAttribute("jive.post.summary."+forumID+"."+threadID, summary); } if (body != null) { session.setAttribute("jive.post.body."+forumID+"."+threadID, body); } // Next construct the ../login.jsp referrer (the link it will redirect to) StringBuffer url = new StringBuffer("announce/editpost.jsp"); // Set to fromPreview to true because fromPreview is used to decide whether or not to // grab subject and body from session state when coming back to post.jsp // after loggin in. url.append("?fromLogin=").append(true); if (threadID != -1) { url.append("?thread=").append(threadID); } if (formButton != null) { url.append("?formButton=").append(formButton); } // Do the redirect String redirect = "../login.jsp?novelist=true&referrer=" + URLEncoder.encode(url.toString()); response.sendRedirect(redirect); return; } Group vendorGroup = Vendor.getVendorForUser(pageUser); if (vendorGroup == null) { %>

Sorry, you can't post an announcement unless your user account is approved by a vendor. <% return; } // Get Iterators of messages for each moderation type. Start with a result // filter to grab only pending threads/messages Forum forum = forumFactory.getForum(ArtimaConstants.PAVILION_ANNOUNCEMENTS_FORUM); ForumThread threadToEdit = null; User author = null; ForumMessage newMessage = null; ColorStyle colorStyle = ColorStyle.GRAY; String theTitle = "Edit an Announcement for " + vendorGroup.getDescription(); String theButton = "Post Changes"; if (isNewPost) { newMessage = forumFactory.createMessage(pageUser); colorStyle = ColorStyle.YELLOW; theTitle = "Add a New Announcement for " + vendorGroup.getDescription(); theButton = "Post as Draft"; } else { threadToEdit = forum.getThread(threadID); author = threadToEdit.getRootMessage().getUser(); newMessage = threadToEdit.getRootMessage(); if (threadToEdit.getModerationValue() == 0) { colorStyle = ColorStyle.YELLOW; theTitle = "Edit a Draft Announcement for " + vendorGroup.getDescription(); theButton = "Post Changes as Draft"; } } String bloggerNickname = pageUser.getUsername(); // Although this page has a cancel button, it doesn't // use the FromPage session variable. So leave FromPage as is, // so if they logout form here, they'll redirect back to wherever // they came from to get here. %> <%= theTitle %>
artima.com
Please take our Snappy Survey.

Artima Pavilion Announcements
<%= theTitle %>
<%@ include file="../loginbox.jincl" %>
<% if (formButton != null && ("Cancel".equals(formButton))) { String onCancelGoBackTo = "../" + (String) session.getAttribute("FromPage"); // When session timed out, it seems session.getAttribute(FromPage) returns // "null", not null. I don't currently understand why this would be true, // but I'm checking for "null" here just in case. - bv 2/9/2002 if (onCancelGoBackTo == null || onCancelGoBackTo.equals("null")) { if (!isNewPost) { onCancelGoBackTo = "ment.jsp?thread=" + Long.toString(threadID); } else { onCancelGoBackTo = "index.jsp?blogger=" + Long.toString(pageUser.getID()); } } session.removeAttribute("jive.post.subject."+forumID+"."+threadID); session.removeAttribute("jive.post.summary."+forumID+"."+threadID); session.removeAttribute("jive.post.body."+forumID+"."+threadID); response.sendRedirect(onCancelGoBackTo); return; } else if (formButton != null && (formButton.startsWith("Post"))) { if (pageUser == null) { %>

Look's like your session expired. You'll have to log back in and try again, after which you will be redirected back here.

<% return; } else if (!isNewPost && (pageUser.getID() != author.getID()) && !pageUser.getUsername().equals("admin")) { %>

Sorry, you can only edit your own announcements, not someone else's.

<% return; } boolean errors = false; String errorMessage = ""; if (subject == null) { errors = true; errorMessage = "Sorry, you can't post a blank subject. Type a subject and try again."; } else if (summary == null) { errors = true; errorMessage = "Sorry, you can't post a blank summary. Type a summary and try again."; } else if (summary != null && (summary.length() > ArtimaConstants.MAX_SUMMARY_LENGTH)) { errors = true; errorMessage = "Sorry, your summary is too long. Please shorten the summary and try again."; } else if (body == null) { errors = true; errorMessage = "Sorry, you can't post a blank message. Type a message and try again."; } if (errors) { %>

<%=errorMessage%> <% } else { newMessage.setSubject(subject); newMessage.setBody(body); String processedSummary = StringUtils.escapeHTMLTags(summary); newMessage.setProperty(ArtimaConstants.SUMMARY_PROPERTY, processedSummary); if (isNewPost) { newMessage.setProperty(ArtimaConstants.FIRST_DRAFT_PROPERTY, "true"); forum.addThread(forumFactory.createThread(newMessage)); } ForumThread thread = newMessage.getForumThread(); thread.setProperty(ArtimaConstants.VENDOR_PROPERTY, vendorGroup.getName()); // topic properties must be thread, not message, properties, so they // can be used in the thread results filter in index.jsp. i = 0; for (Iterator it = topics.iterator(); it.hasNext();) { Topic topic = (Topic) it.next(); String topicHandle = topic.getHandle(); if (topicChecked[i]) { thread.setProperty(ArtimaConstants.TOPIC_PROPERTY_PREFIX + topicHandle, "true"); } else { thread.deleteProperty(ArtimaConstants.TOPIC_PROPERTY_PREFIX + topicHandle); } ++i; } response.sendRedirect("ment.jsp?thread=" + thread.getID()); } } // Only let people edit their own posts if (pageUser == null) { %>

Look's like your session expired. You'll have to log back in and try again, after which you will be redirected back here.

<% return; } else if (!isNewPost && (pageUser.getID() != author.getID()) && !pageUser.getUsername().equals("admin")) { %>

Sorry, you can only edit your own announcements, not someone else's.

<% return; } if (!isNewPost) { if (summary == null) { summary = newMessage.getProperty(ArtimaConstants.SUMMARY_PROPERTY); } if (subject == null) { subject = newMessage.getSubject(); } if (body == null) { body = newMessage.getUnfilteredBody(); } i = 0; for (Iterator it = topics.iterator(); it.hasNext();) { Topic topic = (Topic) it.next(); String topicHandle = topic.getHandle(); String prop = threadToEdit.getProperty(ArtimaConstants.TOPIC_PROPERTY_PREFIX + topicHandle); if (prop != null) { topicChecked[i] = true; } else { topicChecked[i] = false; } ++i; } } %>

<% if (!isNewPost) { %> <% } %> <% int summaryTextareaCols = 60; int summaryTextareaRows = 6; %> <% int textareaCols = 90; int textareaRows = 30; %>
">Title " size="60" maxlength="75">
"> Summary
"> Body
"> Topics <% i = 0; for (Iterator it = topics.iterator(); it.hasNext();) { Topic topic = (Topic) it.next(); String topicHandle = topic.getHandle(); String topicName = topic.getName(); boolean checked = topicChecked[i]; ++i; %> id="<%= topicHandle %>"> <% } %>
   
" cellpadding="1" cellspacing="0" border="0" width="85%">
">
"> The Title is Plain Text " color="<%= JiveGlobals.getJiveProperty("skin.default.textColor") %>">
  • Please capitalize weblog post titles like book titles, with all major words capitalized, to be consistent with other titles at Artima.com. For example, use this as your title: "Distributed Computing is the Key to Happiness", not this: "Distributed computing is the key to happiness".
  • Write your title with RSS syndication in mind. The title will often appear in isolation, completely out of context, in RSS aggregators. Try to choose a title that both reveals what the post is about and sounds interesting. For example, "Comparing Strong and Weak Typing" is better than "Comparisons".
" cellpadding="1" cellspacing="0" border="0" width="85%">
">
"> The Summary is Plain Text " color="<%= JiveGlobals.getJiveProperty("skin.default.textColor") %>">
  • Write your summary with RSS syndication in mind. Like the title, the summary may appear in isolation, though usually accompanied by the title, in RSS aggregators. Think of the summary as a movie trailer. You want to both give the reader a good idea of what your post is about, and try and seduce the reader to click and read the full post.
" cellpadding="1" cellspacing="0" border="0" width="85%">
">
"> The Body is HTML " color="<%= JiveGlobals.getJiveProperty("skin.default.textColor") %>">

  • Scroll down to see a sample weblog post and its HTML formatting.


Body Formatting Guidelines

" cellpadding="1" cellspacing="0" border="0" width="100%">
"> You Type: " color="<%= JiveGlobals.getJiveProperty("skin.default.textColor") %>">

<p>Today I had a 1:00 PM appointment with Elliotte Rusty Harold, author of many books on Java and XML and the force behind the websites <a href="http://www.cafeaulait.org/">Cafe au Lait</a> and <a href="http://www.cafeconleche.org/">Cafe con Leche</a>. Rusty told me to meet him at the bookstore at the Software Developer (SD) conference. I showed up at the San Jose Convention Center shortly before 1:00, inwardly admiring myself for being so prompt and dependable. Unfortunately, SD was being held at the <i>Santa Clara</i> Convention Center. Luckily, Rusty was still waiting for me at 1:15 when I finally arrived at the correct convention center.

<p>After lunch, Rusty and I sat down for a 90 minute interview, which I'll publish on Artima.com within the next few months. Rusty recently released <a href="http://www.cafeconleche.org/XOM/">XOM</a>, which is to a great extent <a href="http://www.jdom.org">JDOM</a> refactored. In the interview, Rusty and I talked about API design in general, as well as particulars of XML processing APIs, especially JDOM and XOM.

<h1>Social Programming</h1>

<p>The very first time I interviewed James Gosling back in 1999, I asked him how the rise of the network would change software development:

<p><i> <b>James Gosling</b>: I think the biggest difference is that you can't just sit alone in a room and build stuff, because the things you're building interact with everything out there. You can't just sit alone and do whatever you want.

<p><b>Bill Venners</b>: And why is that?

<p><b>James Gosling</b>: Because you're trying to interact with other things, you have to know what the other things do. If there are multiple people doing similar kinds of things, they have to have some kind of an agreement on how these things should work. If you're designing an electrical power delivery mechanism, for example, you have to design a wall socket. And everybody has to use the same wall socket; otherwise those toasters won't be able to plug in to you.

<p>It becomes an environment where people have to be much more socially involved. It really is a community thing.</i>

<p>From: <a href=" http://www.artima.com/intv/gosling18.html">http://www.artima.com/intv/gosling18.html</a>

<p>For years I have assumed that "social programming" of the kind envisioned by James Gosling would require strict adherence to contracts defined in thorough specifications. Without strict adherence to contracts clearly delineated in specifications, how could a distributed system being put together by lots of different parties ever work together?

<p>I imagined such systems would work like this: People define specifications of APIs, data structures (such as XML schemas), and protocols. People use those specifications to guide them in 1) creating software that provides the specified services or data structures, and 2) creating software that uses or consumes the APIs or data structures. People bring providers and consumers together and everything works, because everyone adhered strictly to the agreed upon specifications.

<h1>Attempting to Corner Rusty</h1>

<p>One thing I had heard XML enthusiasts, including Rusty Harold, highlight as an advantage of XML is that because XML elements are individually tagged, invalid documents can often still be processed. This attitude has long grated against my strict-contracts personality. I figured this interview would be a good opportunity to try and convince Rusty and, via the interview, other XML enthusiasts that invalid documents should be rejected, not processed.

<p>But Rusty threw me off balance with his first example: RSS. He suggested that a huge percentage of the documents that purport to adhere to one of the four RSS standards actually don't. This threw me because I am planning to very soon write an application that consumes RSS feeds. I realized that if 99% of the RSS feeds on the Internet turn out in practice to be valid, then it makes sense for my application to reject invalid RSS documents. But if only 50% of the RSS feeds are valid, then I should surely try and handle the invalid documents as best I can. But then, anyone writing applications that consume RSS feeds would make the same decision. For the most part, RSS consumers would all deal with invalid RSS documents. And if that's the case, what is the incentive for RSS producers to create valid documents?

<p>A good example of that kind of sloppy services/forgiving clients system is websites and browsers, in which the point of agreement is the HTML specification. In practice, a great percentage of web pages on the Internet have HTML errors in them. Because of that, browsers try hard to figure out what the intent of the HTML author was. The browsers are forgiving of those errors. As a result, websites don't really need to create valid HTML documents. And they don't. In fact, I probably don't to a significant extent. The way I verify the webpages here at Artima.com is not by running them through an HTML verifier, but by looking at them in various browsers on various platforms.

<p>A good example from the other end of the strict adherence spectrum is the Java class file. The JVM specification includes a chapter that formally and thoroughly specifies the format of the Java class file. It also says that JVMs must reject malformed (invalid) class files. JVMs are not forgiving of errors in class files. As a result, the producers of Java class files are very careful to only produce valid well-formed Java class files.

<h1>Conclusion</h1>

<p>My intuition tells me that for social programming to work, specifications must b strictly adhered to by both providers and consumers, like the Java class file. But then I see some systems that seem to work in practice with loose adherence to specifications, systems in which sloppy providers and forgiving consumers are the norm. Rusty and I explored this topic at the end of our interview, but we didn't really nail it down. Here are some questions I'd enjoy hearing your opinion on:

<p>1. What is it that makes some systems, like HTML and maybe RSS, become sloppy provider / forgiving consumer kinds of systems? What allows other systems, such as the Java class file format, to maintain strict adherence to the specification by all parties?

<p>2. How important is strict adherence to specifications in social programming systems? In what kinds of situations is strict adherence important? When is strict adherence not so important?

<p>3. To what extent is the level of adherence to specifications a manifestation of the "culture" of each particular social programming system?

<dingbat>

<a name="resources"> <H1>Resources</H1> </a>

<P>Cafe au Lait, Elliotte Rusty Harold's site about Java:<BR> <a href="http://www.cafeaulait.org/">http://www.cafeaulait.org/</a>

<P>Cafe con Leche, Elliotte Rusty Harold's site about Java:<BR> <a href="http://www.cafeconleche.org/">http://www.cafeconleche.org/</a>

<P>XOM, Elliotte Rusty Harold's new open source XML processing API for Java:<BR> <a href="http://www.cafeconleche.org/XOM/">http://www.cafeconleche.org/XOM/</a>

<P>JDOM, the popular open source XML processing API, originally written by Jason Hunter and Brett McLaughlin:<BR> <a href="http://www.jdom.org">http://www.jdom.org</a>

" cellpadding="1" cellspacing="0" border="0" width="100%">
"> You Get: " color="<%= JiveGlobals.getJiveProperty("skin.default.textColor") %>">

Today I had a 1:00 PM appointment with Elliotte Rusty Harold, author of many books on Java and XML and the force behind the websites Cafe au Lait and Cafe con Leche. Rusty told me to meet him at the bookstore at the Software Developer (SD) conference. I showed up at the San Jose Convention Center shortly before 1:00, inwardly admiring myself for being so prompt and dependable. Unfortunately, SD was being held at the Santa Clara Convention Center. Luckily, Rusty was still waiting for me at 1:15 when I finally arrived at the correct convention center.

After lunch, Rusty and I sat down for a 90 minute interview, which I'll publish on Artima.com within the next few months. Rusty recently released XOM, which is to a great extent JDOM refactored. In the interview, Rusty and I talked about API design in general, as well as particulars of XML processing APIs, especially JDOM and XOM.

Social Programming

The very first time I interviewed James Gosling back in 1999, I asked him how the rise of the network would change software development:

James Gosling: I think the biggest difference is that you can't just sit alone in a room and build stuff, because the things you're building interact with everything out there. You can't just sit alone and do whatever you want.

Bill Venners: And why is that?

James Gosling: Because you're trying to interact with other things, you have to know what the other things do. If there are multiple people doing similar kinds of things, they have to have some kind of an agreement on how these things should work. If you're designing an electrical power delivery mechanism, for example, you have to design a wall socket. And everybody has to use the same wall socket; otherwise those toasters won't be able to plug in to you.

It becomes an environment where people have to be much more socially involved. It really is a community thing.

From: http://www.artima.com/intv/gosling18.html

For years I have assumed that "social programming" of the kind envisioned by James Gosling would require strict adherence to contracts defined in thorough specifications. Without strict adherence to contracts clearly delineated in specifications, how could a distributed system being put together by lots of different parties ever work together?

I imagined such systems would work like this: People define specifications of APIs, data structures (such as XML schemas), and protocols. People use those specifications to guide them in 1) creating software that provides the specified services or data structures, and 2) creating software that uses or consumes the APIs or data structures. People bring providers and consumers together and everything works, because everyone adhered strictly to the agreed upon specifications.

Attempting to Corner Rusty

One thing I had heard XML enthusiasts, including Rusty Harold, highlight as an advantage of XML is that because XML elements are individually tagged, invalid documents can often still be processed. This attitude has long grated against my strict-contracts personality. I figured this interview would be a good opportunity to try and convince Rusty and, via the interview, other XML enthusiasts that invalid documents should be rejected, not processed.

But Rusty threw me off balance with his first example: RSS. He suggested that a huge percentage of the documents that purport to adhere to one of the four RSS standards actually don't. This threw me because I am planning to very soon write an application that consumes RSS feeds. I realized that if 99% of the RSS feeds on the Internet turn out in practice to be valid, then it makes sense for my application to reject invalid RSS documents. But if only 50% of the RSS feeds are valid, then I should surely try and handle the invalid documents as best I can. But then, anyone writing applications that consume RSS feeds would make the same decision. For the most part, RSS consumers would all deal with invalid RSS documents. And if that's the case, what is the incentive for RSS producers to create valid documents?

A good example of that kind of sloppy services/forgiving clients system is websites and browsers, in which the point of agreement is the HTML specification. In practice, a great percentage of web pages on the Internet have HTML errors in them. Because of that, browsers try hard to figure out what the intent of the HTML author was. The browsers are forgiving of those errors. As a result, websites don't really need to create valid HTML documents. And they don't. In fact, I probably don't to a significant extent. The way I verify the webpages here at Artima.com is not by running them through an HTML verifier, but by looking at them in various browsers on various platforms.

A good example from the other end of the strict adherence spectrum is the Java class file. The JVM specification includes a chapter that formally and thoroughly specifies the format of the Java class file. It also says that JVMs must reject malformed (invalid) class files. JVMs are not forgiving of errors in class files. As a result, the producers of Java class files are very careful to only produce valid well-formed Java class files.

Conclusion

My intuition tells me that for social programming to work, specifications must b strictly adhered to by both providers and consumers, like the Java class file. But then I see some systems that seem to work in practice with loose adherence to specifications, systems in which sloppy providers and forgiving consumers are the norm. Rusty and I explored this topic at the end of our interview, but we didn't really nail it down. Here are some questions I'd enjoy hearing your opinion on:

1. What is it that makes some systems, like HTML and maybe RSS, become sloppy provider / forgiving consumer kinds of systems? What allows other systems, such as the Java class file format, to maintain strict adherence to the specification by all parties?

2. How important is strict adherence to specifications in social programming systems? In what kinds of situations is strict adherence important? When is strict adherence not so important?

3. To what extent is the level of adherence to specifications a manifestation of the "culture" of each particular social programming system?

Resources

Cafe au Lait, Elliotte Rusty Harold's site about Java:
http://www.cafeaulait.org/

Cafe con Leche, Elliotte Rusty Harold's site about Java:
http://www.cafeconleche.org/

XOM, Elliotte Rusty Harold's new open source XML processing API for Java:
http://www.cafeconleche.org/XOM/

JDOM, the popular open source XML processing API, originally written by Jason Hunter and Brett McLaughlin:
http://www.jdom.org

" cellpadding="1" cellspacing="0" border="0" width="100%">
">
"> Aim for the Look and Feel of Artima.com Articles: " color="<%= JiveGlobals.getJiveProperty("skin.default.textColor") %>">
  • Please use <h1> for level one subheads, and <h2> for level two subheads in your weblog posts. Artima.com's style sheet will size them appropriately. <h1> and <h2> are used on all Artima.com articles, and on the Talk Back! and About the Blogger subheads at the bottom of your post, so if you use them too, your weblog post will be consistent with the rest of the site. Also, using <h1> and <h2> helps search engines realize that the subhead text is a bit more important than the surrounding text.
  • If your weblog post has an article-like feel, consider terminating the main content with <dingbat>. This is not HTML, of course, but will be replaced with HTML that places an Artima.com "dingbat" () in-line. This little icon is a visual cue throughout Artima.com that indicates to readers that the main content of an article (or blog) is finished. Put this at the end of the last paragraph, before any boilerplate material such as footnotes or resources.
  • If you want to include some links at the end of your post, please put them under a "Resources" subhead and format them as shown in the example post shown to the left. (You can cut and paste from the example's resources, then replace the text and URL.) Your Resources section will then be consistent with the rest of Artima.com. The URLs are displayed explicitly in the resources section so they show up on paper when printed.

"> Most Artima.com Articles Are Composed of Only a Few Basic HTML Elements: " color="<%= JiveGlobals.getJiveProperty("skin.default.textColor") %>">

  • Paragraphs: Mark paragraphs with <p>.
  • Hard Returns: Mark hard returns with <br>.
  • Less/Greater Than Signs: For less than signs (<), use &lt;. For greater than signs (>), use &gt;.
  • Bold: Text between <b> and </b> will appear in bold face.
  • Italics: Text between <i> and </i> will appear in italic face.
  • Code Font: Text between <code> and </code> will appear in-line in code font.
  • Code Examples: Text between <pre> and </pre> will appear in code font exactly as you format it. For example, surround multi-line code examples with<pre> and </pre> tags.
  • Level 1 Subheads: Text between <h1> and </h1> will appear as Artima.com level 1 subheads.
  • Level 2 Subheads: Text between <h2> and </h2> will appear as Artima.com level 2 subheads.
  • Block Quotes: Text between <blockquote> and </blockquote> will appear offset and indented.
  • Lists: Surround bullet lists with <ul> and </ul>, numbered lists with <ol> and </ol>, with each list item denoted by a single <li>.
  • Links: Text formatted as <a href="http://www.artima.com">Artima Home</a> will appear as a hyperlink, as in Artima Home.
  • For more information, see How to Post in the Artima Weblogs.

Copyright © 1996-2003 Artima Software, Inc. All Rights Reserved.
Artima.com is created by Bill Venners