Chapter 18

News & Announcements

by Jerry Ablan


CONTENTS


an nounce \a-nouns'\ v: to make known publicly

Introduction

Welcome to your sixth sample intranet app. This app, like the last two, is very simple in design; however, it will provide intranet users with plenty of information to talk about at the watercooler. This is the News & Announcements app. This read-only app displays listings of company news and announcements that are stored in the database. It is useful for disseminating all types of company information like bonuses, casual days, office parties, and so on. This chapter will cover the following topics in regard to the News & Announcements app:

NOTE
This four step format will be used throughout all of the sample app chapters. Hopefully, it will provide you with valuable insight and ideas for creating your own intranet apps

app Design

This app, like the one in the last chapter, is one of the simpler apps in the tutorial. Once this app has been connected to a data source, it will present the user with a list of all the news on file. Screenshot is the proposed user interface for the News & Announcements program. Screenshot : The News & Announcements user interface. The interface will utilize a JifTextArea component to display news. This brings up an interesting point: Where is the news entered anyway? Well, right here in this program. You need this program to be dual-functioning. This means that it is read-only for some people, but lets others create new news and announcements. Figure 18.2 illustrates how this should look. Screenshot : The News & Announcements user interface with saving capabilities.

Database Design

This app is responsible for manipulating news rows. These rows should be stored in a single table. The table you're going to use in this sample app is called the News table. The information stored in the news table corresponds to the information that is to be edited as described above. Table 18.1 shows the columns you'll need to store in your news table.

Table 18.1. The layout of the News table
Description Column Name Type Can Be Null?
Default
News ID news_id number( 5 ) No
None
Date/Time of News Item news_datetime date No
System Date
News Description desc_text char( 255 ) No
None
Originator of News Item emp_id number( 5 ) Yes
None

Screenshot shows the entity relationship diagram for your database as it stands in this chapter. As you get deeper into your sample apps, you'll see your entity relationship diagram grow to encompass all the tables. Screenshot : The entity relationship diagram including our new News table.

NOTE
Entity relationship diagrams are discussed in , "Employee Files.

In addition to creating a table, you'll create a database synonym for your table. This will allow everyone to access the table with the same name without having to worry about the schema in which the table resides. While this table has a foreign key back to the employee table, it is not a dependent table. The relationship is merely informational. That is because the emp_id column in your table may be null. This allows you to ignore it completely. In fact, in the implementation of the News & Announcement program, it is not used.

TIP
, "Human Resources: Benefits Maintenance," provides some in-depth coverage of foreign keys and referential integrity.

Listing 18.1 shows the SQL commands to create the News table.


Listing 18.1. The SQL to create the News table.


/* Create the table */
create table news_t
(
 news_id number( 5 ) not null,
 news_datetime date default sysdate not null,
 desc_text char( 255 ) not null,
 emp_id number( 5 ) default null
);
/* Create a primary key */
alter table news_t
 add
 (
 primary key
 (
 news_id
 )
 );
/* Create a foreign key */
alter table news_t
 add
 (
 foreign key
 (
 emp_id
 )
 references emp_t
 );
/* Grant access for the table to the user role */
grant select,insert,delete,update on news_t to ia_user_r ;
/* Drop any existing public synonym */
drop public synonym news ;
/* Create a public synonym for our table */
create public synonym news for news_t ;



NOTE
The preceding SQL is quite generic; however, it may not work on every database. This particular SQL has been tested with Oracle.

The first SQL clause creates the table news_t. The second clause creates a primary key using the news_id column. Making this the primary key ensures that the values in the column are unique across all rows. The third SQL clause creates your foreign key. The foreign key in this table is the emp_id column. This column points back to, or references, the emp_id column in the emp_t table. Lastly, the public synonym news is created for the table news_t. After you have created this table, you are ready to start building your app.

CAUTION
You must create the emp_t (Employee) table before you can create the news_t (News) table. Otherwise, the news_t SQL will fail!

Implementation

The rest of this chapter will discuss the implementation of the News & Announcements program. First, I'll discuss the user interface and how it was created. Secondly, I'll discuss the database access used in the program. Finally, I'll cover any coding pitfalls that came up during the app construction. Each sample app in this tutorial uses a different approach to developing the user interface. This variety will show you the different ways you can go about doing your own interfaces. Hopefully, you will get a nice cross-section of many different styles and choose the one that suits you best.

User Interface

To achieve the design goal presented above, you do not need special user interface components. For variety, I chose to use the GridBagLayout layout manager for this app. It uses the same hard-coded row and column heights as the Employee Files program. This provides another example of how to use this difficult layout manager. The following is the user interface construction code for the News & Announcements program:


//****************************************************************************
//* Members *
//****************************************************************************
 JifTextField news_id = new JifTextField( "" );
 JifTextField news_datetime;
 JifTextArea news_text;
 JifTextField new_news_text;
//****************************************************************************
//* Constructor *
//****************************************************************************
 public
 NewsUI( SimpleDBJiflet jiflet )
 {
 super( jiflet );
 GridBagLayout gbl = new GridBagLayout();
 int cw[] = { 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
 14, 14, 14 }; // 17
 int rh[] = { 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14 }; // 12
 double rc14_0[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 gbl.columnWidths = new int[ 17 ];
 gbl.rowHeights = new int[ 12 ];
 gbl.columnWeights = new double[ 17 ];
 gbl.rowWeights = new double[ 12 ];
 System.arraycopy( cw, 0, gbl.columnWidths, 0, 17 );
 System.arraycopy( cw, 0, gbl.rowHeights, 0, 12 );
 System.arraycopy( rc14_0, 0, gbl.columnWeights, 0, 17 );
 System.arraycopy( rc14_0, 0, gbl.rowWeights, 0, 12 );
 setLayout( gbl );
 news_text = new JifTextArea( "" );
 addWithConstraints( news_text, "x=0;y=0;width=17;height=10" );
 news_text.disable();
 new_news_text = new JifTextField( "" );
 // Don't add if read only...
 if ( jiflet.getParameter( "readOnly",
 "true" ).equalsIgnoreCase( "false" ) )
 addWithConstraints( new_news_text,
 "x=0;y=11;width=16;fill=horizontal" );
 // Add the buttons...
 saveButton.disable();
 // Don't add if read only...
 if ( jiflet.getParameter( "readOnly",
 "true" ).equalsIgnoreCase( "false" ) )
 addWithConstraints( saveButton, "x=16;y=11" );
 // Tell which are numeric...
 news_id.setNumeric( true );
 // Set the focus to the first field...
 setFocus( news_text );
 }


Set the layout to a new GridBagLayout. The JifTextArea component is created and placed in the layout. This is your news list. It is disabled so the user cannot type or edit the information.

Conditional Construction

Here's where you come to an interesting part. Query your configuration parameters with the getParameter() method to see if there is a property called readOnly. If this property exists, and is set to false, then you must allow the user to create new news items. You do this by adding a JifTextField and a saveButton to the layout if this readOnly property is set to false.

Database Access

This app communicates with the database through the use of a NewsRecord object. This DBRecord derivation knows how to create, read, update, and delete records from the news table. The following are the instance variables of this class:


//****************************************************************************
//* Constants *
//****************************************************************************
 public final static String TABLE_NAME = "news";
//****************************************************************************
//* Members *
//****************************************************************************
 // A variable for each table column...
 public int news_id = -1;
 public Date news_datetime = null;
 public String desc_text = "";



NOTE
The NewsRecord and other database classes are reused in several other apps. They have been placed in their own package along with other shared code. This package is called jif.common. It contains all the common classes between all the apps.

Retrieving the News

At startup of the app, the database needs to be queried, and the results displayed for the user. These results are data columns taken from the database. Retrieve all of the news for display:


//****************************************************************************
//* loadPanel *
//****************************************************************************
 public void
 loadPanel()
 {
 String sql = "select * from emp";
 // Clear out the old stuff...
 getUIPanel().clearScreen();
 try
 {
 if ( getConnector().getStatement().execute( sql ) )
 {
 ResultSet rs = getConnector().getStatement().getResultSet();
 int row = 0;
 while ( rs.next() )
 {
 EmployeeRecord er = new EmployeeRecord( rs );
 setDBRecord( er );
 getUIPanel().moveToScreen();
 }
 }
 } catch ( SQLException e )
 {
 errorLog( "Error during loading: " + e.toString() );
 }
 return;
 }


This issues an SQL query that returns all of the news in your news table. Each returned row is stored in a NewsRecord object. The stored row is then placed into a Vector for later use. You may notice that the news list is not populated here. That is because you've placed that code in the moveToScreen() method of your user interface class. However, there is data moved to the screen. But, before it can move data to your list, you need to tell the base class which DBRecord to use. This is done with the call to setDBRecord(). The moveToScreen() code is quite simple:


//****************************************************************************
//* moveToScreen *
//****************************************************************************
 public void
 moveToScreen()
 {
 if ( getJiflet().getDBRecord() == null )
 return;
 // Cast one off...
 NewsRecord er = ( NewsRecord )getJiflet().getDBRecord();
 String nr = er.news_datetime.toString() +
 ". " + er.desc_text +
 System.getProperty( "line.separator" );
 news_text.appendText( nr );
 }


Here, you retrieve the NewsRecord from your jiflet, concatenating the date and time with the news description. Finally, tack on a line feed and append it to the text area.

Storing the News

If the user has access to the news input area then any change in that component will signal the actual Save button to enable. This is handled by your framework. To actually save the news, you need to generate a little SQL. You do this in your main class. Here is the code:


//****************************************************************************
//* saveRecord *
//****************************************************************************
 /**
 * This overridden saveRecord() knows how to save the news...
 */
 public boolean
 saveRecord()
 {
 boolean success = true;
 // Read only?
 if ( getParameter( "readOnly", "true" ).equalsIgnoreCase( "true" ) )
 {
 MessageBox mb = new MessageBox( this, "Sorry Charlie!",
 "You are not allowed to save data!",
 MessageBox.STOP );
 mb.show();
 return( true );
 }
 try
 {
 String sql;
 int new_uid;
 // Get a new UID!
 SequenceGenerator sg = new SequenceGenerator(
 getConnector(), "news", "news_id" );
 new_uid = sg.getNextValue();
 String newNews = ( ( NewsUI )getUIPanel() ).new_news_text.getText();
 sql = "insert into news ( news_id, news_datetime, desc_text ) " +
 "values ( " + Integer.toString( new_uid ) +
 ", sysdate, Ô" + newNews + "Ô )";
 if ( !sql.equals( "" ) )
 {
 getConnector().getStatement().execute( sql );
 showStatus( "News Saved..." );
 loadPanel();
 }
 }
 catch ( SQLException e )
 {
 showStatus( "News Not Saved..." );
 getConnector().errorLog( e.toString() );
 success = false;
 }
 return( success );
 }


First ensure that the user is allowed to create news rows. If he is, then create a new news_id using the SequenceGenerator class. This is then used to construct an SQL INSERT statement. When executed, the new news row is inserted into the table. If it is successful, the news items are reread from the database and displayed.

Programming Considerations

Aside from the database access, this app is quite simple. It does little more than list the rows in the news table in an attractive manner. If you set a certain property a certain way, creating the news becomes an option for you! You needed to present an intuitive interface to the user, while making it effortless to use. You did this by using the JifTextArea class. You also needed a way to create news. This was handled by hidden fields that are placed into the layout based on configuration parameters. This allows the program to have a dual-functionality. To recap, this app introduced the following Java intranet coding topics:

Summary

This chapter introduced you to the sixth sample app in your intranet app suite: the News & Announcements. This program is responsible for updating the News table and displaying its contents. It is completely read-only to most users, while others may be granted access to save new news. This program will be useful for all of the employees. It allows them to keep tabs on what is going on at the company. In , "Product Maintenance," you will design and create an app that will allow to you create, update, and delete records of the things your company handles: products.


Java Screenshot Java Screenshot Java Screenshot Java Screenshot



Comments