Tuesday, February 12, 2008

Jython Monthly Call for Articles - February 2008



Please submit new articles and/or tutorials for the Feburary 2008 distribution of Jython Monthly. Feel free to write or teach about any topic that is Jython related...the more articles the better!

Thanks in advance for your participation!

Monday, February 11, 2008

JavaFX Script - An Excellent Read

I finished reading the JavaFX Script book by James Weaver a couple of days ago. I ordered this book from Amazon last November, and it just arrived last month. I have to say that I was getting a bit impatient about the delay, but it really was worth the wait.

If you are new to JavaFX like me, then you will find this to be an excellent starting point. The book is really geared towards developers who are interested in authoring small Swing-like applications. I'd have to say that it helped to have a good background in Swing prior to reading this book...but I think that anyone could pick it up and just start from scratch. James does a great job from start to finish as he builds upon concepts as the book goes on. It really is a start-to-finish book, but at 200 pages, that is not very rough to read straight through. It really is a quick read, and quickly jumps into the basics and works up from there. I was also impressed with the example applications used in the book as they gave me a great sense of what the language is capable of doing.

This book is definitely worth the read if you are interested in learning JavaFX basics and beyond.

Thursday, January 24, 2008

EJB 3.1 - Significant Changes Sound Promising

Being a big fan of the EJB 3.0 specification, I read this new EJB 3.1 New Features article published by Serverside right away. Clearly, the current EJB spec is much simpler to use and maintain than previous generations. Building upon that logic, the upcoming EJB 3.1 specification looks even better.

Real quick, I just wanted to point two of the features I found most interesting about this article. First, it sounds like interfaces will be made optional. This could be viewed as a bonus or a downfall, depending upon the way you look at it. Certainly removing the need for interfaces will simplify the writing of EJB code immensely. However, the benefits of using the loose-coupled approach may make EJB more difficult in some circumstances. If you enjoy unit testing of EJB code, this may make a big difference. However, since the specification plans to make this an optional feature then it will leave the implementation to the coder. Therefore, this seems to be a feature that can greatly benefit those who do not wish to write EJB interfaces.

Second, the article briefly mentions support for stateful web services and EJB timer service enhancements to support scheduling and/or deployment-time timer creation. I will be interested to hear more about these.

Give the article a read if you are interested in EJB...it is worth the time.

Thursday, January 10, 2008

Oracle JDeveloper 11g Technology Preview 3 Released

I recently downloaded the new JDeveloper 11g Tech Preview 3 for my Mac, and I am impressed. While I primarily use Netbeans for Java application development, the JDeveloper IDE is great for developing PL/SQL and Java Stored Procedures.

All of the new features in this technology preview are amazing. I understand that if you develop Java applications within the JDeveloper IDE then there have been many enhancements and improvements as well. For instance, the SOA and Web Services modules have had some significant adjustments.

My primary use of the JDeveloper IDE is for PL/SQL and Java Stored Procedure development. If you are looking to create and/or maintain any PL/SQL, then this tool can help you greatly. The new editor is nice, package body and header separation is a plus, and the automatic SQL command window is nice to have. One no longer needs to open a SQL Worksheet to invoke an SQL statement, it opens automatically when a database connection is selected. Of all the great SQL IDEs available today, I do not think any are better than JDeveloper for managing Oracle Java Stored Procedures. Straightforward and easy to manage, developing Java Stored Procedures for the Oracle database has never been easier.

I recommend downloading the technology preview and giving it a try. Even if you do not develop any SQL or PL/SQL code, you may find that it has some nice features to benefit your Java development.

Tuesday, January 08, 2008

Glassfish - A Noteworthy Application Server

I've been running across quite a few blogs lately speaking about Glassfish. It appears that this great application server is being used by more people and gaining some real popularity. I've been using Glassfish since version one. Actually, prior to Project Glassfish, I used the Sun Java Application Server version 8.

I have nothing bad to say about Glassfish. It is an excellent choice for a JavaEE application server. Powerful and easy to use, this application server should not be overlooked if you are in the business of Java web development.

I have not yet tried out version 3, but I plan to do so very soon. I've been working primarily with Glassfish version 2 for the past few months. I've found it very easy to deploy JBOSS Seam applications to Glassfish even though there is no direct IDE deployment option for this setup as yet.

I will post any issues or concerns with using Glassfish V3 and JBOSS Seam...

Monday, November 19, 2007

Mac OSX Leopard - Spaces Information

I love OSX Leopard, especially the spaces feature. It is really nice to have several "Spaces" with different apps open on each. However, I did find one nuance that is a bit annoying. If you open an application which allows for multiple windows (such as Firefox), you must use all of the windows within the same space. That means you cannot open Firefox in Space 1 and then go into Space 2 and open another FireFox window.

Now, there is an easy work around to this, and that is simply opening up all of your Firefox windows within the same Space and then hitting F8 to show all Spaces. Once you have all spaces showing then you can drag the windows into separate spaces as you wish. The issue I have found with this is that if you use the dock to navigate and hit the Firefox icon then spaces may go berserk. I have had spaces go back and forth between windows until I intervened with a mouse click.

This becomes frustrating if you are trying to use an technology such as Java Web Start in one Space and another Firefox window in a separate space. If the Web Start application tries to fire another window (such as a report), then Spaces will go berserk again.

Really, this is not a big issue but I thought I would point it out for anyone who was having issues with Spaces. The easiest work around in this case is to only use Firefox or other such apps within once Space only.

Monday, November 05, 2007

OSX and JavaFX Script

Recently, there has been a ton of complaining that JDK6 has not been ported over to OSX 10.5 Leopard. I am a 10.4 Tiger user, and I am currently running Apple's Java 1.5 implementation. I like the Apple JDK 5 implementation...it looks much nicer than running Swing apps on Windows. However, I do hope that JDK 6 is available soon for OSX because I'd like to start using JavaFX within my Java programs on my Mac.

Without thinking twice, I downloaded Netbeans 6.0 Beta 2 and the JavaFX plugins on my Mac. I then started writing some FX code and calling it from native Java, and realized that I cannot code against the javax.script packages in JDK 5. I am now in need of JDK 6 to move forward with JavaFX on the Mac.

This blog post is just another posting regarding the desire for JDK 6 to be ported to OSX. I hope it comes soon...until then I am stuck with Windows for writing any JavaFX apps.

Wednesday, September 26, 2007

Jython Monthly - Call for Articles

After a long hiatus, the Jython Monthly newsletter will begin distribution again this October. If you have any content that you would like to post, please do so using this link. The October edition of Jython Monthly is scheduled for distribution on 10/9.

Thanks in advance for any article or tutorial submissions!

Wednesday, September 12, 2007

Migrating SEAM Applications from Glassfish V1 to Glassfish V2

I've come up with some simple steps for migrating a JBoss SEAM application from Glassfish V1 to Glassfish V2. Actually, you can configure all SEAM applications which you plan on deploying to Glassfish in this manner, and they will be deployable on either V1 or V2.

Keep in mind that I am also integrating Ajax4Jsf into my SEAM applications.

1) Update faces-config.xml (if needed) to ensure that you are using SeamFaceletViewHandler

<view-handler>org.jboss.seam.ui.facelet.SeamFaceletViewHandler</view-handler>

2) Update web.xml

- Add context-param for org.ajax4jsf.VIEW_HANDLERS

<context-param>
<param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
<param-value>org.jboss.seam.ui.facelet.SeamFaceletViewHandler</param-value>
</context-param>


- Add SUN Faces Listener

<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>

- If using Ajax4JSF, update the filter to include dispatchers

<filter-mapping>
<filter-name>ajax4jsf</filter-name>
<url-pattern>*.seam</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>

3) Ensure that all database drivers are installed on the new server.
4) If using Ajax4Jsf, you will want to ensure that you are packaging Apache Commons 3.2

Friday, September 07, 2007

Creating RSS Reader Component Using SEAM and ROME

I've been working lately on an enterprise application which will be used for developing and maintaining an organization's website. The application is being written using JSF, JBoss SEAM 1.2.1 GA, Facelets, ROME, Ajax4Jsf, and deploying to Glassfish V1.

There was a requirement to have an RSS reader as well as the ability to create RSS feeds. I found that the Rome Project had all of the tools which I was going to require to make this function. It is a great RSS library, and if you code in Java and use RSS then I definitely recommend it.

I've created an RSS reader which uses an Oracle database back end to store a table of RSS feeds to parse. There is also a table of pages in the database, and each RSS feed record is tied to one or more of the pages. The RSS web page component can go on any page...as long as the page is registered in the database. An administrator then has the ability to add RSS feeds to be read on that page. The component uses AJAX to display a news title for 10 seconds, and then read the database and parse the next RSS entry in the feed. Once the component has read all of the entries for a particular feed, it looks for more feeds registered to that page. If it finds more then it will parse all entries within that feed and so on. In the end, the RSS reader is a component which simply displays news from one or more RSS feed sources using AJAX.

The Database

create table rss_feed as(
FEED_ID NUMBER,
CONTENT_PAGE_ID NUMBER,
FEED_URL VARCHAR2(1000),
FEED_NAME VARCHAR2(500));

alter table rss_feed
add constraint rss_feed_pk
primary key(feed_id);

create sequence rssapp_rss_feed_seq
start with 1
increment by 1;

(This assumes that you have a table which stores each page name along with a unique page id)


The Code

Since we are using EJB3 technology with the SEAM framework, we will require an Entity class for persistence. We also need an EJB session bean which will contain all of the RSS logic, along with a local interface.

Entity Class - Straight forward. I use Netbeans to create the initial class from the database, and then I add the SEAM annotations.

/*
* RssAppRssFeed.java
*/

package org.jj.entity;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;

@Entity
@Scope(ScopeType.PAGE)
@Name("RssAppRssFeed")
@Table(name = "RSSAPP_RSS_FEED")
@NamedQueries( {
@NamedQuery(name = "RssAppRssFeed.findByFeedId", query = "SELECT f FROM RssAppRssFeed f WHERE f.feedId = :feedId"),
@NamedQuery(name = "RssAppRssFeed.findByContentPageId", query = "SELECT f FROM RssAppRssFeed f WHERE f.contentPageId = :contentPageId"),
@NamedQuery(name = "RssAppRssFeed.findByFeedUrl", query = "SELECT f FROM RssAppRssFeed f WHERE f.feedUrl = :feedUrl"),
@NamedQuery(name = "RssAppRssFeed.findByFeedName", query = "SELECT f FROM RssAppRssFeed f WHERE f.feedName = :feedName")
})
public class RssAppRssFeed implements Serializable {

@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,
generator="RssApp_rss_feed_seq_generator")
@SequenceGenerator(name="RssApp_rss_feed_seq_generator",sequenceName="RssApp_rss_feed_seq", allocationSize=1)
@Column(name = "FEED_ID", nullable = false)
private BigDecimal feedId;

@Column(name = "CONTENT_PAGE_ID")
private BigInteger contentPageId;

@Column(name = "FEED_URL")
private String feedUrl;

@Column(name = "FEED_NAME")
private String feedName;

/** Creates a new instance of RssAppRssFeed */
public RssAppRssFeed() {
}

/**
* Creates a new instance of RssAppRssFeed with the specified values.
* @param feedId the feedId of the RssAppRssFeed
*/
public RssAppRssFeed(BigDecimal feedId) {
this.feedId = feedId;
}

/**
* Gets the feedId of this RssAppRssFeed.
* @return the feedId
*/
public BigDecimal getFeedId() {
return this.feedId;
}

/**
* Sets the feedId of this RssAppRssFeed to the specified value.
* @param feedId the new feedId
*/
public void setFeedId(BigDecimal feedId) {
this.feedId = feedId;
}

/**
* Gets the contentPageId of this RssAppRssFeed.
* @return the contentPageId
*/
public BigInteger getContentPageId() {
return this.contentPageId;
}

/**
* Sets the contentPageId of this RssAppRssFeed to the specified value.
* @param contentPageId the new contentPageId
*/
public void setContentPageId(BigInteger contentPageId) {
this.contentPageId = contentPageId;
}

/**
* Gets the feedUrl of this RssAppRssFeed.
* @return the feedUrl
*/
public String getFeedUrl() {
return this.feedUrl;
}

/**
* Sets the feedUrl of this RssAppRssFeed to the specified value.
* @param feedUrl the new feedUrl
*/
public void setFeedUrl(String feedUrl) {
this.feedUrl = feedUrl;
}

/**
* Gets the feedName of this RssAppRssFeed.
* @return the feedName
*/
public String getFeedName() {
return this.feedName;
}

/**
* Sets the feedName of this RssAppRssFeed to the specified value.
* @param feedName the new feedName
*/
public void setFeedName(String feedName) {
this.feedName = feedName;
}

/**
* Returns a hash code value for the object. This implementation computes
* a hash code value based on the id fields in this object.
* @return a hash code value for this object.
*/
@Override
public int hashCode() {
int hash = 0;
hash += (this.feedId != null ? this.feedId.hashCode() : 0);
return hash;
}

/**
* Determines whether another object is equal to this RssAppRssFeed. The result is
* true if and only if the argument is not null and is a RssAppRssFeed object that
* has the same id field values as this object.
* @param object the reference object with which to compare
* @return true if this object is the same as the argument;
* false otherwise.
*/
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof RssAppRssFeed)) {
return false;
}
RssAppRssFeed other = (RssAppRssFeed)object;
if (this.feedId != other.feedId && (this.feedId == null || !this.feedId.equals(other.feedId))) return false;
return true;
}

/**
* Returns a string representation of the object. This implementation constructs
* that representation based on the id fields.
* @return a string representation of the object.
*/
@Override
public String toString() {
return "org.jj.entity.RssAppRssFeed[feedId=" + feedId + "]";
}

}

EJB Session Bean - Once again, I use Netbeans to generate the initial session bean from the entity class and I modify for SEAM. I then added all of the essential methods and logic for the RSS in working with ROME. You will notice that I did not use SEAM's @In @Out annotations on some of the variables...that is because I had issues when doing so. The code that I post here does work as expected. You will also see some doubleSubmitIndex variables...this is due to an issue I've seen with Ajax4Jsf. When I use the a4j:poll, the page seems to invoke the server method twice. It causes the RSS reader to skip entries within the feed. Therefore, I coded a work around which is kind of messy, but it works.

/*
* FeedReader.java
*/

package org.jj.beans;


import com.sun.net.ssl.SSLContext;
import com.sun.syndication.feed.synd.SyndEntryImpl;
import java.net.URL;
import java.io.InputStreamReader;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.XmlReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.ejb.Remove;
import javax.ejb.Stateful;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.jj.entity.RssAppContentPage;
import org.jj.entity.RssAppRssFeed;
import org.jj.interfaces.FeedLocal;
import org.jj.utility.RssAppCommonTasks;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.datamodel.DataModel;

/**
*
*/
@Stateful
@Scope(ScopeType.SESSION)
@Name("rssReader")
@Interceptors({org.jboss.seam.ejb.SeamInterceptor.class})
public class FeedReader implements FeedLocal {

@PersistenceContext(unitName="rssApp-ejbPU-FESSPROD")
private EntityManager em;

@DataModel
public List
feedList=null;

private List
rssFeedList = null;
private String pageName = null;

@Out(required=false)
private Feed feedBean;
private String feedText = null;
private Date feedDate = null;
private String feedTitle = null;
private int feedCounter;
private int feedEntryCounter;
private int feedIndex;
private int feedEntryIndex;
private int doubleSubmitIndex;
private int doubleSubmitFeedIndex;

private Query qry;

public void readFeed() {
pageName = RssAppCommonTasks.obtainPageName();
if (!pageName.equals("underMaintenance")){
qry = em.createQuery("select object(p) from RssAppContentPage as p " +
"where p.contentPage = :pageName")
.setParameter("pageName", pageName);
RssAppContentPage page = (RssAppContentPage) qry.getSingleResult();
qry = em.createQuery("select object(f) from RssAppRssFeed as f " +
"where f.contentPageId = :pageId")
.setParameter("pageId", page.getContentPageId());
rssFeedList = qry.getResultList();

// Parse rss feeds for page, if any
if (rssFeedList.size() > 0){
for(int index = 0; index <= rssFeedList.size()-1; index++){ boolean ok = false; int entryNumber = 0; int entryIndex = 0; RssAppRssFeed rssFeed = new RssAppRssFeed(); rssFeed = rssFeedList.get(index); System.out.println("BEGINNING RSS READ....."); if (rssFeed.getFeedUrl() != null) { try { feedList = null; URL feedUrl = new URL(rssFeed.getFeedUrl()); SyndFeedInput input = new SyndFeedInput(); SyndFeed feed = input.build(new XmlReader(feedUrl)); entryNumber = feed.getEntries().size(); initializeList(); for (entryIndex = 0; entryIndex <= entryNumber; entryIndex++){ System.out.println("Reading..."); feedBean = new Feed(); feedBean.setAuthor(feed.getAuthor()); feedBean.setDescription(feed.getDescription()); feedBean.setEntry(((SyndEntryImpl)feed.getEntries().get(entryIndex)).getTitle()); feedBean.setEntryLink(((SyndEntryImpl)feed.getEntries().get(entryIndex)).getLink()); feedBean.setEntryUpdatedDate(((SyndEntryImpl)feed.getEntries().get(entryIndex)).getPublishedDate()); feedBean.setTitle(feed.getTitle()); feedBean.setUri(feed.getUri()); feedList.add(feedBean); } ok = true; } catch (Exception ex) { ex.printStackTrace(); System.out.println("ERROR: "+ex.getMessage()); } } if (!ok) { System.out.println(); System.out.println("FeedReader reads and prints any RSS/Atom feed type."); System.out.println("The first parameter must be the URL of the feed to read."); System.out.println(); } } } } } /** * This method is invoked via ajax from the front end page in order to read * a new feed into the display. The ajax front end causes a double submit * to this method, so we need to adjust counters such that they will only update * on every other submit. We do this by using the doubleSubmitIndex numbers. */ public void updateFeed(){ if (doubleSubmitIndex > 1){
doubleSubmitIndex = 0;
}
if (doubleSubmitFeedIndex > 1){
doubleSubmitFeedIndex = 0;
}
pageName = RssAppCommonTasks.obtainPageName();

if (!pageName.equals("underMaintenance")){
qry = em.createQuery("select object(p) from RssAppContentPage as p " +
"where p.contentPage = :pageName")
.setParameter("pageName", pageName);

RssAppContentPage page = (RssAppContentPage) qry.getSingleResult();

qry = em.createQuery("select object(f) from RssAppRssFeed as f " +
"where f.contentPageId = :pageId")
.setParameter("pageId", page.getContentPageId());
rssFeedList = qry.getResultList();

/*
* Obtain a list of rss feeds for a particular web page. If feeds
* exist for that page, then enter the feed parse logic.
*/
if (rssFeedList.size() > 0){
feedCounter = rssFeedList.size();
if(this.getFeedIndex() > feedCounter - 1){
this.setFeedIndex(0);
}

boolean ok = false;

int entryIndex = 0;

/*
* Obtain all feed entries for this particular feed index
*/
RssAppRssFeed rssFeed = new RssAppRssFeed();
RssFeed = rssFeedList.get(getFeedIndex());

System.out.println("Feed Index: " + getFeedIndex() + " Entry Index: " + getFeedEntryIndex());

if (rssFeed.getFeedUrl() != null) {
try {
feedList = null;
URL feedUrl = new URL(rssFeed.getFeedUrl());
String feedEntryDateText = null;
String feedEntryText = null;
String feedEntryUrl = null;
SyndFeedInput input = new SyndFeedInput();
SyndFeed feed = input.build(new XmlReader(feedUrl));
/*
* Obtain count of all feed entries
*/
feedEntryCounter = feed.getEntries().size();
initializeList();

if(getFeedEntryIndex() > 0){
if (getFeedEntryIndex() > feedEntryCounter - 1){
setFeedEntryIndex(0);
}
}
System.out.println("Reading...");
feedBean = new Feed();
feedBean.setAuthor(feed.getAuthor());
feedBean.setDescription(feed.getDescription());
feedBean.setEntry(((SyndEntryImpl)feed.getEntries().get(getFeedEntryIndex())).getTitle());
feedBean.setEntryLink(((SyndEntryImpl)feed.getEntries().get(getFeedEntryIndex())).getLink());
feedBean.setEntryUpdatedDate(((SyndEntryImpl)feed.getEntries().get(getFeedEntryIndex())).getPublishedDate());
feedBean.setTitle(feed.getTitle());
setFeedTitle(feed.getTitle());
feedBean.setUri(feed.getUri());
feedList.add(feedBean);
this.feedDate = feedBean.getEntryUpdatedDate();
feedText = "" +
feedBean.getEntry() + "
";


ok = true;

if(doubleSubmitIndex > 0) {
this.feedEntryIndex++;
doubleSubmitIndex++;

// If all entries within current feedIndex have been read, move on
// to the next feed and start with entry zero.
if (feedEntryIndex > feedEntryCounter - 1){
this.feedIndex++;
this.feedEntryIndex = 0;
}
} else {
doubleSubmitIndex++;
}

} catch (Exception ex) {
ex.printStackTrace();
System.out.println("ERROR: "+ex.getMessage());
}
}

if (!ok) {
System.out.println();
System.out.println("FeedReader reads and prints any RSS/Atom feed type.");
System.out.println("The first parameter must be the URL of the feed to read.");
System.out.println();
}

}
}
}



private void initializeList(){
if (feedList == null){
feedList = new ArrayList();
}
}

public String getFeedText() {
return feedText;
}

public void setFeedText(String feedText) {
this.feedText = feedText;
}

public String getFeedTitle() {
return feedTitle;
}

public void setFeedTitle(String feedTitle) {
this.feedTitle = feedTitle;
}

public int getFeedIndex() {
return feedIndex;
}

public void setFeedIndex(int feedIndex) {
this.feedIndex = feedIndex;
}

public int getFeedEntryIndex() {
return feedEntryIndex;
}

public void setFeedEntryIndex(int feedEntryIndex) {
this.feedEntryIndex = feedEntryIndex;
}

public Date getFeedDate() {
return feedDate;
}

public void setFeedDate(Date feedDate) {
this.feedDate = feedDate;
}

@Remove @Destroy
public void destroy(){}


}


Local Interface - Nothing exciting in the local interface

/**
* FeedLocal.java
*/
package org.jj.interfaces;

import java.util.Date;

public interface FeedLocal {
void readFeed();

java.lang.String getFeedText();

void setFeedText(String feedText);

void updateFeed();

void destroy();

int getFeedIndex();

void setFeedIndex(int feedIndex);

Date getFeedDate();

void setFeedDate(Date feedDate);

java.lang.String getFeedTitle();

void setFeedTitle(String feedTitle);
}


Utility Class - Here is an excerpt from my utility class. This code obtains the current page name from the FacesContext.

public final class RssAppCommonTasks {

public static String obtainPageName(){

String currentPageName = null;
Query qry = null;
String tempPageName = FacesContext.getCurrentInstance().getViewRoot().getViewId();
if (tempPageName.lastIndexOf("/") > 0) {
tempPageName = tempPageName.substring(tempPageName.lastIndexOf("/") + 1).replace(".seam","").replace(".xhtml","");
currentPageName = tempPageName;
System.out.println("tempPageName: " + currentPageName);
} else {
System.out.println("view id: " + FacesContext.getCurrentInstance().getViewRoot().getViewId());
System.out.println("updated view id: " +
FacesContext.getCurrentInstance().getViewRoot().getViewId().replace("/","").replace(".seam","").replace(".xhtml",""));

currentPageName = FacesContext.getCurrentInstance().getViewRoot().getViewId().replace("/","").replace(".seam","").replace(".xhtml","");
}

return currentPageName;
}

***
}




pages.xml - Each page which contains the RSS component code will require an element within the pages.xml file to invoke server-side code.

<page id="/myPage.xhtml" action="#{rssReader.updateFeed}">

Component code in the XHTML page - I haven't yet created a separate component/tag for this code, but it should work by simply copying and pasting this code in each page which uses the reader. The back end code then determines which page is calling the code and parses the feeds in the database which are tied to that page.

<div id="autoreader">
<a4j:poll interval="10000"
reRender="autoReaderText, autoReaderDate, feedTitle"
action="#{rssReader.updateFeed}">
</a4j:poll>
<p align="center" class="sub_head_sub"><br />
<h:outputText id="feedTitle"
value="#{rssReader.feedTitle}"/>
</p>

<table id="feedList" name="feedList">
<td bgcolor="#CCFFCC" style="width: 100px">
<h:outputText id="autoReaderDate"
value="#{rssReader.feedDate}"/>
</td>
<td bgcolor="#CCFFCC" style="width: 400px">
<h:outputText id="autoReaderText"
escape="false"
value="#{rssReader.feedText}"/>
</td>
</table>
</div>

That is all there is to it. There is a bit of code to write, but the end result is very appealing. Once complete, one can add or remove feeds from the database and have them automatically appear on the desired pages.

Thursday, August 30, 2007

Oracle Database 11g

I'm really excited about the release of Oracle database 11g...even if it is only for Linux at this time. I am almost thinking about setting up a Linux box just to try it out...but perhaps I'll wait for the release of the Windows version.

There are a significant number of new features added to this release. One of the top items that I am interested in is "hot patching". I'm also glad that PL/SQL performance has been improved, and that SQL Tuning can now be fully automated.

Check out this link for a great amount of detail. The latest edition of Oracle magazine also showcases the new release...grab a copy if you do not have one yet.

This looks to be a release that we will definitely want to invest some time into!

Thursday, July 12, 2007

JBoss Seam Configurations - JARs and Details



I've sucessfully implemented NetBeans 6.0 M10 and Netbeans 5.5.1 projects using the JBOSS Seam framework. I can successfully deploy these projects to both Glassfish V1, JBoss 4.2.0, and JBoss 4.1. This blog post is a log so that I can remember the specific JAR files and details required for each of these projects. I intend to add onto this blog as time goes on and I encounter more detailed information.

Seam 1.2.1 GA and Glassfish V1:
This project utilizes the Ajax4Jsf and RichFaces APIs. I have been unable to make this setup work with Glassfish V2 as yet. If you have figured that one out, please let me know.

Follow these steps in either NB 5.5.1 or NB 6.0 M10

1) Create new Enterprise Application, and also create the following libraries within the IDE:

Seam1.2.1-GlassfishV1
hibernate-all.jar
hibernate-annotations.jar
jboss-common.jar
jboss-seam-debug.jar
jboss-seam-pdf.jar
jboss-seam-ui.jar
jboss-seam.jar
thirdparty-all.jar
jbpm-3.1.2.jar (If you plan to use JBpm...I have not tested as yet)

Ajax4Jsf
ajax4jsf-1.1.1.jar
commons-collections.jar
oscache-2.3.2.jar
richfaces-3.0.1.jar

2) Add those two libraries to your ejb sub-project along with these others:
commons-beanutils-1.7.0.jar
commons-codec-1.3.jar
commons-digester-1.6.jar
jboss-archive-browsing.jar
jsf-facelets.jar (unless you intend to add facelets support via the ide)

3) Add the following JARs to your war sub-project:
dom4j.jar (may not need this one...)
jboss-seam-ui.jar

4) Add configuration files to your ejb sub-project:
a) Add ejb-jar.xml to src/conf
b) Create empty seam.properties within src/conf
c) Create log4j.xml within src/conf
- Easiest configuration is to copy one of the log4j.xml files contained in the
example projects within the Seam 1.2.1 GA download.
d) Create persistence.xml within src/conf
- Use NetBeans to create persistence unit by right-clicking on the ejb sub-project
and then selecting New->Persistence Unit. Follow directions to create a unit
based upon one of the existing database connections you have defined in the IDE.
I use Toplink by default, but Hibernate works just as well.

5) Add configuration files to your war sub-project
a) Configure web.xml and faces-config.xml as suggested in Carol McDonald's Blog or Brian Leonard's Blog. It is also a good idea to take a look at the web.xml file from within one of the sample projects which comes with your Seam download. You will require a Seam filter, and Ajax4Jsf context-parameter if you plan to use that technology. I almost always use the same configuration contained within the sample project web.xml files, but also add the ejb references as discussed in the blog posts above.
b) Make sure the following additional xml files reside within your WEB-INF directory:
components.xml - Copy and use the one from the glassfish example in your Seam download. You will need to update it according to your ejb project name.
pages.xml - this one can be left blank
c) You may need to add META-INF to root of web pages and place application.xml within it.

I'll add the other configurations as time goes on, but this one will get you started with Seam application development on Glassfish V1.


Friday, July 06, 2007

Seam 2.0 and Netbeans 6.0 M10

Seam 2.0 works with Netbeans 6.0 M10 and the Netbeans Seam plugin. I've spent some time preparing an application based upon some of the examples given in the Seam 2.0 documentation.

I've managed to deploy and successfully run an application on JBoss 4.2.0 using Netbeans 6.0 M10 and the seam plugin. I only used the plug-in to generate the initial application. I did not use any of the other plug-in automation.

Monday, July 02, 2007

Saw It, Got It, Using It

Netbeans 6.0 M10 is now available to the community. There are quite a few enhancements in this milestone.

I'll blog more about the M10 release as needed as time goes on. I've been using it all day with the Netbeans Seam plugin and Facelets plugin...and haven't experienced any issues thus far.

Friday, June 29, 2007

JBoss Seam + Netbeans Update 2

The good news is that the Seam plugin for Netbeans deploys without any issues to JBoss 4.0.5 server. I've also added a Postgresql database into the mix and successfully generated entity classes and deployed to 4.0.5 successfully!

The bad news is that I ran into an issue with M9. At least, it is an issue with M9 and the Facelets plugin (on my workstation). I cannot tell if this issue is a bug with M9, or just my slow workstation, but the IDE literally locks up if I try to edit XHTML files with the Facelets plugin installed. I just found this out this morning when trying to add a new Facelets page to my Seam Plugin app. It would not work...I restarted the M9 application several times.

Needless to say, I've reverted to Netbeans 5.5.1 and have been using the Facelets code without issue.

In summary: Netbeans 5.5.1, Seam Framework Plugin, Facelets Plugin, and Postgresql database create an easy CRUD application without issue...and in just a few minutes!

As stated in previous posts, I will try to make a mini-application using this model. I then wish to port it to Glassfish as well just to see how difficult that step will be. It may take me a while...but I will post my results.

Saturday, June 23, 2007

JBoss Seam + Netbeans 6.0 M9 Update

I've not had much time lately to play with Seam and get some good development going. However, I've been trying to make the Seam plugin work with Netbeans 6.0 M9...and it does quite nicely. Follow the link to the blog by Michael Yuanto see how you should set up your environment. This is tested and functional with Netbeans 6.0 M9.

I tried to make this work with JBoss 4.2, but I never quite made it. The issue is that I need to run JBoss on a different port other than the default 8080. I cannot make this happen with JBoss 4.2 within the Netbeans 6.0 M9 environment. When I register the server with Netbeans, it automatically defaults to 8080...I do not like this. I've also tried to change all references to 8080 within the JBoss 4.2 home to something else...no luck. The good thing is that with JBoss 4.0.5, you can simply adjust the server.xml within the server\default\deploy\jbossweb-tomcat55.sar directory. This then registers with Netbeans 6.0 on the specified port without issue.

I am hopeful to hear more about the Netbeans Seam plugin soon...the initial release is very good...

Saturday, June 09, 2007

JBoss SEAM 1.2.1 GA and Glassfish V2

I've just followed the excellent write-up by Roger Kitain and built the glassfish example for Seam on Glassfish v2. If you follow Roger's blog instructions, it works without any issues using Seam 1.2.1 GA.

Now...onto the Netbeans 6.0 M9 integration. I hope to install the Seam plug-in (or minimally the Facelets plug-in) for Netbeans to M9 and deploy to Glassfish...I'll blog on my results.

Friday, June 08, 2007

Netbeans 6.0 - Great Information Resource

I am a little bit behind...but I've just recently read the article in the Netbeans Magazine May 2007 edition regarding Netbeans 6.0. It is an excellent article. If you are looking for a good resource to learn the newest features of the IDE then I definitely recommend giving it a read!

Also, another excellent resource is always Roumen's Weblog. I listen to each of the Netbeans podcasts, and I visit his site often...always has great information regarding Netbeans. He also has some good Flash Demos available.

Check it out Netbeans users!

Tuesday, May 29, 2007

Good Java Reference

Just wanted to post the link to a good Java reference I ran across today. This may be old, but it is still a good reference while trying to port applications to different platforms. Read How to avoid pitfalls in your Java application development for some quick, yet decent material.

JFXBuilder...I'm Impressed

You've heard of JavaFX, right? Of course you have...unless you have not paid any attention to the Java world in the past couple of months. I'm interested in the upcoming technology and all that it will cover. I've read through a few tutorials and played around a bit and I do like the syntax of the FX scripting language. I was impressed when I checked out java.net this morning and saw that ReportMill has already released a WYSIWYG editor for JavaFX. I took a brief trial run and it looks good so far! Give it a test run at http://www.reportmill.com/jfx/ and you will also be impressed!