Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Friday, 30 March 2018

JPA Calling a MySQL stored function

I have a stored function called getNextCode() that requires a string parameter and returns a string. I wish to call this from my JPA enabled application. T he following code fragment shows the use of the crateNativeQuery() method to achieve this.


    private String _getNextRollPackageCode()
    {
        String query = String.format(
                "SELECT getNextCode( '%s')",
                this.ROLL_PACKAGES_MODEL_NAME
        );

        return this.ROLL_PACKAGE_CODE_PREFIX + "-" +  (String) _entityManager.createNativeQuery(query)
                .getSingleResult();
    }

Wednesday, 28 March 2018

Ubuntu: Setting up an MQTT Server and connecting via SSL

Foreward

This has been a very frustrating story as I was asked to setup an MQTT server that would support -- every IT Manager's pride and joy -- SSL. The setup was quite smooth, thanks to the good people of Digital Ocean. Their post How to Install and Secure the Mosquitto MQTT Messaging Broker on Ubuntu 16.04, explains everything crystal clear.

I also wanted to setup the websockets protocol, so a Javascript client would continue to work. Last but not least be able to programmatically connect using programs written in Java, C# and Python 3. This blog post shows the exact setup we used to make things work, as well as minimal code samples about how to connect.

For the shake of this example, my server DNS name is supposed to be mysite.net, the MQTT server user is mqtt-user and the password we set, is my_Super_Secure_Password.

Server setup and testing

Starting with the setup, I followed Digital Oceans instructions and making a fiew slight changed ended up with this:

# MQTT Config File with websockets and SSL
# Created March - 26th -2018
#

# ----------------------------------------------------------------------------
# Log Setup
# ----------------------------------------------------------------------------
log_type error
log_type warning
log_type notice
log_type information
log_type websockets
websockets_log_level 255
log_timestamp true
# log dest is set in /etc/mosquitto/mosquitto.conf
# web sockets log level can be removed if you verify that websockets is working

# ----------------------------------------------------------------------------
# User Security Setup
# ----------------------------------------------------------------------------
allow_anonymous false
password_file /etc/mosquitto/passwd

# Do not allow non-secure connection from anywhere but the localhost
bind_address    localhost
port            1883

# ----------------------------------------------------------------------------
# This is the SSL Setup
# ----------------------------------------------------------------------------
listener        8883 
protocol        mqtt      

certfile        /etc/letsencrypt/live/mysite.net/cert.pem
cafile          /etc/letsencrypt/live/mysite.net/chain.pem
keyfile         /etc/letsencrypt/live/mysite.net/privkey.pem
require_certificate false

# ----------------------------------------------------------------------------
# Here is our SSL enabled web sockets config
# ----------------------------------------------------------------------------
listener        9993 
protocol        websockets
http_dir        /var/www/mysite.net/mqtt

certfile        /etc/letsencrypt/live/mysite.net/cert.pem
cafile          /etc/letsencrypt/live/mysite.net/chain.pem
keyfile         /etc/letsencrypt/live/mysite.net/privkey.pem
require_certificate false

This is the contents of the /etc/mosquitto/conf.d/default.conf file. To test I switched to my local console and issued the following command:

 mosquitto_sub -h mysite.net -p 8883 -t test -u mqtt_user -P my_Super_Secure_Password --capath /etc/ssl/certs

then opened a second terminal, and each time I would type

mosquitto_pub -h mysite.net -p 8883 -t test -m "Hello Sailor"  -u mqtt_user -P my_Super_Secure_Password --capath /etc/ssl/certs

I would see a Hello Sailor line on the first console screen. That more or less did it

Connecting with Code

This is the part where we completely lost it. All examples in the web show how to perform an SSL connection using your own private key pair but in our case we wanted something much simpler. Our requirement was that the connection be SSL encrypted but we would use the mqtt generated user and password pair. In the Java world, we really got mixed up with keystores, trust manager factories and the like while all it took to post a simple message was :

package com.kfator.mqttclient;

import static java.nio.charset.StandardCharsets.UTF_8;
import java.security.SecureRandom;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.SSLContext;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

public class Main {
    public static final String MQTT_URL = "ssl://mysite.net:8883";
    public static final String MQTT_USER_NAME = "mqtt_user";
    public static final String MQTT_USER_PASSWORD = "my_Super_Secure_Password";

    public static void main(String args[])
    {
        try {
            MqttClient client = new MqttClient(
                    MQTT_URL,
                    MqttClient.generateClientId(),  // ClientId
                    new MemoryPersistence());       // Persistence

            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, null, new SecureRandom());

            MqttConnectOptions options = new MqttConnectOptions();
            options.setSocketFactory(sslContext.getSocketFactory());
            options.setUserName(MQTT_USER_NAME);
            options.setPassword(MQTT_USER_PASSWORD.toCharArray());

            client.connect(options);
            client.publish(
                "test", // topic
                "Hello from Java".getBytes(UTF_8), // payload
                2, // QoS
                false); // retained?
            client.disconnect();

            System.out.println("Connection established!");
        } catch (Exception ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

The code runs from a Netbenas 8.2 Maven project. To include the paho-mqtt libraries we (sort of) followed the instructions at MQTT Client Library Encyclopedia – Eclipse Paho Java page. the actual steps were to create an empty Mevn Projet, then right click on the dependencies Node, select the add dependency menu item and fill in the form details as show at the begining of the Paho-Java page.

The C# code using the Mqtt-Paho library for .NET goes like this:

    _clientMonitor = new MqttClient("mysite.net", 8883, true, new X509Certificate(), null, MqttSslProtocols.TLSv1_0);

... and finally, python 3 only requires the use of client.tls_set() before calling connect(). Here is the related fragment from out demo program.


client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
client.username_pw_set(MQTT_USER_NAME, MQTT_PASSWORD)

client.tls_set()
client.connect(HOST, PORT)

And the best part was, that all these worked ...

Friday, 26 February 2016

Java Swing GUI's default and cancel buttons

None of these are mine. I just copied and re-factored them from here and here in stackoverflow.com.

The code comes from a login form that needs to have it's login button clicked when enter is pressed and to be closed when user hits escape.

Other frameworks like good old VCL and WindowsForms allow this to be done by visually managing properties, but with Java you have to type something like this :

        // set default botton on ENTER
        this.getRootPane().setDefaultButton(jButtonLogin);

        // set escape to close this dialog
        KeyStroke escapeKeyPressed = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);        
        this.getRootPane().registerKeyboardAction( e -> this.dispose(), escapeKeyPressed, JComponent.WHEN_IN_FOCUSED_WINDOW);

Enjoy.

Tuesday, 13 December 2011

Java enums: A complete example

I started programming with Pascal, so I have deep feelings for enumerated types. To be honest I feel that they are a much more easy going approach to modeling that the long lists of constants we used in the C programming language or in the pre JDK5 versions of Java.

Java enums are so very flexible and the guide on the Oracle website says it all. What I wanted to do in this post is to provide a full working example, as a reference to myself and hopefully any ... lost soul, that demonstrates how to bind data with each enum type value and also how to implement the previous and next methods,

package gr.abakalidis.sample.model;

/**
 * Possible image states and relative sizes regarding the actual bitmaps
 * loaded from a Web server.
 * 
 * @author Thanassis Bakalidis
 * @version 1.0
 */
public enum ImageState {
    NOT_LOADED(0, 0), SMALL(320, 240), MEDIUM(800, 600), LARGE(1024, 768);

    private final int width;
    private final int height;

    ImageState(int width, int height)
    {
        this.width = width;
        this.height = height;
    }

    public int getHeight()
    {
        return this.height;
    }

    public int getWidth()
    {
        return this.width;
    }

    /**
     * Get the next value ion the series of enumeration 
     * 
     * @return the next value in the series or null if already at end of values
     */
    public ImageState getNext()
    {
        return this.ordinal() < ImageState.values().length - 1 
            ? ImageState.values()[this.ordinal() + 1] 
            : null;
    }
 
    /**
     * Get the previous value in the series of enumeration
     * 
     * @return the next value in the series on null if called for the first va;ue 
     */
    public ImageState getPrevious()
    {
        return this.ordinal() == 0 
            ? null 
            : ImageState.values()[this.ordinal() - 1];
    }
}

Wednesday, 15 October 2008

Oracle ADF: Verifying Master-Detail relationships and throwing exception on "beforeCommit()" events

I have found no other way to validate master detail hierarchies, than using theEntityImpl.beforeCommit(TransactionEvent transactionEvent). Writing a validateEntity() function can only prove useful when examining the fields of the current record. There are cases however where you need to verify that the entire tree is correct. Consider for instance a cases where you need to verify that all items included in an order are eligible for seeding to the user's dispatch address. For cases like this you need to examine your data just before committing and the beforeCommit() does just that.

During before commit you can practically traverse your entire M/D tree using association accessors and verify that everything meets you business rules.

If anything fails to validate then raising a JboException will prevent the actual commit and the exception error message will appear on your tag in your jspx page. There is however only one small catch:

Unless you modify your application module configuration and set the jbo.txn.handleafterpostexc to true, all exceptions thrown inside the afterCommit() method result in a roll-back which completely destroys the data hierarchy just build. As Steve Muench puts it,

When this flag is true, the framework will take an in-memory snapshot of the pending state of the application module, and then use this snapshot to reinstate that same pending state in case any of the beforeCommit() methods fail with an exception. If everything goes successfully with no errors, the in-memory snapshot is not used and will just get garbage collected.

To change the jbo.txn.handleafterpostexc parameter, right click on your application module inside the application navigator, then select Configurations... from the pop-up menu, click the Edit button from the resulting dialog box and you are there.

Tuesday, 15 July 2008

Oracle ADF: Viewlink based attributes vs Full Blown Queries

At one time or an other all of us must have dealt with an entity based View object whose SQL statement looked more or less like this :

SELECT UserInfo.USER_ID,
      UserInfo.USER_NAME,
      UserInfo.FULL_NAME,
      UserInfo.USER_ROLE,
      UserInfo.DEPARTMENT_ID,
      UserInfo.ACTIVE,
      Department.NAME,
      Department.ID
FROM USERS UserInfo, DEPARTMENTS Department
WHERE UserInfo.DEPARTMENT_ID = Department.ID (+)

This kind of VO may appear easy to create and manage when your schema contains two or three entities but things may end up pretty complicated as the number of associated entities increases. Let me show you the SQL statement of a view object displaying my version of the Service requests view in full detail.

  SELECT
      ServiceRequest.ID,
      ServiceRequest.REQUEST_DATE,
      TRUNC(REQUEST_DATE) AS SEARCH_DATE,
      ServiceRequest.REQUESTER_FIRST_NAME,
      upper( REQUESTER_FIRST_NAME) AS SEARCH_FIRST_NAME,
      ServiceRequest.REQUESTER_LAST_NAME,
      UPPER( REQUESTER_LAST_NAME) AS SEARCH_LAST_NAME,
      ServiceRequest.REQUESTER_TELEPHONE,
      ServiceRequest.LOCATION_STREET,
      ServiceRequest.LOCATION_NUMBER,
      ServiceRequest.LOCATION_AREA,
      ServiceRequest.LOCATION_ZIP,
      ServiceRequest.LOCATION_CITY,
      ServiceRequest.DEPARTMENT_FOR,
      Department.NAME AS DEPARTMENT_NAME,
      ServiceRequest.ASSIGNED_DATE,
      ServiceRequest.ASSIGNED_TO,
      AssignedTechnician.FULL_NAME AS TECHNICIAN_NAME,
      ServiceRequest.RESOLUTION_COMMENTS,
      ServiceRequest.REQUEST_STATUS,
      Status.NAME AS STATUS_NAME,
      ServiceRequest.PROBLEM_DESCRIPTION,
      AssignedTechnician.USER_ID,
      ServiceRequest.CREATED_BY,
      ServiceRequest.CREATED_ON,
      ServiceRequest.MODIFIED_BY,
      ServiceRequest.MODIFIED_ON,
      ServiceRequest.RESOLVED_ON,
      Department.ID AS ID1,
      Status.STATUS_ID,
      ServiceRequest.TELEPHONE_BY,
      TelephonedOperator.FULL_NAME AS TELEPHONE_OPERATOR_NAME,
      ServiceRequest.TELEPHONE_DATE,
      TelephonedOperator.USER_ID AS USER_ID1
 FROM
   SERVICE_REQUESTS ServiceRequest,
   DEPARTMENTS Department,
   STATUSES Status,
   USERS AssignedTechnician,
   USERS TelephonedOperator
 WHERE 
  (ServiceRequest.DEPARTMENT_FOR = Department.ID (+)) AND
  (ServiceRequest.REQUEST_STATUS = Status.STATUS_ID) AND
  (ServiceRequest.ASSIGNED_TO = AssignedTechnician.USER_ID(+)) AND
  (ServiceRequest.TELEPHONE_BY = TelephonedOperator.USER_ID(+))

When dealing with pure entity based view objects -- that is without a custom where clause -- then JDeveloper makes some descent effort in keeping your where clause straight. If you decide to add bind variables however, then JDeveloper completely looses it and you end up having to manage everything by hand. Where clauses have to be tampered with if you also decide that you need outer left joins and you cannot get away without using the primary keys of all the participating entities and then having to learn how to hide them.

I am never too happy when dealing with such monsters but users are always hungry for more and more information. I guess that this why every self respecting SAP table has at least 70 or more columns :-) ....

Anyway the thing that triggered my search for alternatives was the fact that on many occasions the reference fields of multi entity view objects would not update their values correctly especially after edits, until you issued a final commit, thus giving users one more reason to grumble. So instead of using the SQL query mode, I ended up using view link based transient attributes.

The idea is very simple. Create single entity based view objects containing all the relevant information. In our example Users and Departments. Then create a view link between the two and expose accessors to the client. Enable Java code generation for the primary view row. Last create a transient attribute to the source View (Users) that exposes the department name through the view link provided departments row member.

Let's follow the steps in more details....

For starters we can create two view objects UsersFullList and DepartmentsList with SQL statements like the following :

SELECT UserInfo.USER_ID,
      UserInfo.USER_NAME,
      UserInfo.FULL_NAME,
      UserInfo.USER_ROLE,
      UserInfo.DEPARTMENT_ID,
      UserInfo.ACTIVE
FROM USERS UserInfo

... for the Users View and ...

SELECT Department.ID,
      Department.NAME,
      Department.IS_TECH
FROM DEPARTMENTS Department

... for the departments. If you do not intend to edit Departments through your application, you may very well create a read only view object. Next we shall create a view link named UserAssignedToDept . Creating the view link is trivial, so I will show only you the images where we define the connection ....

and the view link properties :

The important thing to remember here is that since the view link cardinality is set to 1 → ∞ the department accessor will be of type Row instead of RowIterator. So if we next edit the UsersFullList view and create a Java class for the view row, then the code for the DepartmentInfo attribute will look exactly like this :

   /**Gets the associated Row using master-detail link DepartmentInfo
    */
   public Row getDepartmentInfo()
   {
       return (Row)getAttributeInternal(DEPARTMENTINFO);
   }

Creating a department name attribute for the the new view is now done by defining a transient attribute to the UsersFullList view

and then providing a getter method that looks like this :

   public String getDepartmentName()
   {
       String deptName;
       try {
           Row deptRow = this.getDepartmentInfo();
           deptName = (String )deptRow.getAttribute("Name");
       } catch (Exception e) {
           deptName = "";
       }
       return deptName;
   }

From the controller's side the view object looks exactly like it would if based on SQL and you don't have to hide the participating entity key attributes.

So is it worth it you might ask. The answer is -- as usually -- yes and no depending on the size of your project the complexity of your view objects and whether or not you prefer tampering with SQL code than Java. As I explained in the beginning of this posting the main advantage of this method is that your reference attributes will always display correctly since they are composed of pointers to the actual data of the view cache instead of cached entries. On the other hand if you project contains two view objects each composed from two entities, going through all that will be like killing a fly with a machine gun.

Friday, 30 May 2008

Oracle ADF: Enriching the actions of a ViewObject

Based on the technique described two posts back regarding creation of a custom ViewObject that offers ready to drag actions, I now give you another simple yet very handy function. The showAllRows() function when added to the AB_BaseViewObject methods, allows you to create a button in a search page that removes all view criteria and executes the current query, very useful for cases when uses enter lots of view criteria and then need to display the entire contents of the entire row with a single click.

    public void showAllRows()
    {
        clearViewCriterias();
        executeQuery();
    }

Remember that in order for the action to appear in the JDeveloper Data Control Palette like in the following picture, you must include the showAllRows() function to the view objects client interface.

Wednesday, 21 May 2008

Oracle ADF: Duplicating a ViewObject's current row

I wanted to add a Create Like functionality that would allow a new row to be inserted in a ViewObject then drive the user to an edit page where he or she would make ant changes required for valid insertion of the new row to the database and avoid having to re-enter everything from scratch.

In order to accomplish this I created the following method in the ViewObject's implementation class.

import oracle.jbo.AttributeDef;
import oracle.jbo.Row;
import oracle.jbo.ReadOnlyAttrException;
import oracle.jbo.TooManyObjectsException;

. . .

    /**
     * create and insert a row similar to the current
     */
    public void createLike()
    {
        // get the current row to dublicate
        Row currentRow = getCurrentRow();
        if (currentRow == null)
            return;
            
        // create new one
        Row newRow = createRow();
        
        // get the attribute values for the current attribute
        Object[] myValues = currentRow.getAttributeValues();
        
        for (int i = 0; i < currentRow.getAttributeCount(); i++)
            try {
                AttributeDef d = getAttributeDef(i);
                    
                if (d.getUpdateableFlag() != AttributeDef.READONLY)                
                    newRow.setAttribute( i, myValues[i]);                
            }    
            catch (ReadOnlyAttrException roe) {
                continue;
            }
            catch (Exception e) {
                // it is almost certain that the primary key will be
                // violated so the user must do something in the 
                // page following execution of the method.
                if (!(e instanceof TooManyObjectsException))
                    System.out.println(e.toString());
            }
            
        insertRow(newRow);        
    }

The code works fine and copies the values all columns from the current row into a new one except that of the last column that constitutes the primary key. That way the user will have to make the appropriate changes to the new record, so it can be inserted correctly.

There are a few points worth mentioning in this apprach

  • if your view object contains attributes from multiple entity objects then the the key attributes of the referenced entities that gets inserted by the framework appear to be updatable -- hence the catch (ReadOnlyAttrException roe) line. I have brought this to the JDeveloper forum but got no suggestions.
  • Using the above technique requires that you expose the createLike() method to the ViewObject's client interface. See the previous post for details.
  • The most probable use of this method will be to place a command button into an <af:tableSelectOne> facet in order to drive your users to an edit page with values already set. On most occasions the edit page will contain a commit button that will perform the final post. My suggestion is to use a backing bean to invoke the commit action like I discuss in a previous article named ADF/JSF Avoiding uncaught exceptions after commit that will prevent the controller layer to change back to the browse page in case of any errors.

Thursday, 15 May 2008

Oracle ADF: A view object with cancelInsert and cancelEdit operations

I have already discussed the problem of providing a cancel button in an ADF/JSF edit page. Here is an alternative that allows the usage of a base view object that provides both a cancel edit and a cancel insert method.

I have come to believe that this method is the most appealing so here is a brief outline of how to use it :

First create the following class in the queries package of you model application.

package myapp.model.queries;

import oracle.jbo.Row;
import oracle.jbo.server.ViewObjectImpl;

public class AB_BaseViewObject
    extends ViewObjectImpl {

    public AB_BaseViewObject()
    {
    }
    
    /**
     * Refresh the view obejct's current row from the dataset practically 
     * undoing any changes.
     */
    public void cancelEdits() 
    {
        Row r = getCurrentRow();

        if (r != null) 
            r.refresh( Row.REFRESH_WITH_DB_FORGET_CHANGES);
    }
    
    /**
     * Undo changes and get rid of new rows
     */
    public void cancelInsert()
    {
        clearCache();      
    }
}

Next create Java Classes that extend the AB_ViewObject for all the view objects that require editing in your project. Publish the cancelXXX() methods on the view interface like in following picture.

Finally create buttons on the edit or create pages in the ViewController project that call the methods.

Wednesday, 23 April 2008

Java: Formatting a Number Using a Custom Format

The example comes form the The Java Developers Almanac 1.4 and I am adding it here to serve only as a quick reference note.

    // The 0 symbol shows a digit or 0 if no digit present
    NumberFormat formatter = new DecimalFormat("000000");
    String s = formatter.format(-1234.567);  // -001235
    // notice that the number was rounded up
    
    // The # symbol shows a digit or nothing if no digit present
    formatter = new DecimalFormat("##");
    s = formatter.format(-1234.567);         // -1235
    s = formatter.format(0);                 // 0
    formatter = new DecimalFormat("##00");
    s = formatter.format(0);                 // 00
    
    
    // The . symbol indicates the decimal point
    formatter = new DecimalFormat(".00");
    s = formatter.format(-.567);             // -.57
    formatter = new DecimalFormat("0.00");
    s = formatter.format(-.567);             // -0.57
    formatter = new DecimalFormat("#.#");
    s = formatter.format(-1234.567);         // -1234.6
    formatter = new DecimalFormat("#.######");
    s = formatter.format(-1234.567);         // -1234.567
    formatter = new DecimalFormat(".######");
    s = formatter.format(-1234.567);         // -1234.567
    formatter = new DecimalFormat("#.000000");
    s = formatter.format(-1234.567);         // -1234.567000
    
    
    // The , symbol is used to group numbers
    formatter = new DecimalFormat("#,###,###");
    s = formatter.format(-1234.567);         // -1,235
    s = formatter.format(-1234567.890);      // -1,234,568
    
    // The ; symbol is used to specify an alternate pattern for negative values
    formatter = new DecimalFormat("#;(#)");
    s = formatter.format(-1234.567);         // (1235)
    
    // The ' symbol is used to quote literal symbols
    formatter = new DecimalFormat("'#'#");
    s = formatter.format(-1234.567);         // -#1235
    formatter = new DecimalFormat("'abc'#");
    s = formatter.format(-1234.567);         // -abc1235

Thursday, 20 March 2008

Oracle ADF Two action listeners in one action

Some time ago, I run into a situation when I wanted to add two action listeners inside a single command element but I realized that this was just not possible. When I asked about that in the JDeveloper forums somebody told me that this could only be accomplished in code, but at that time my knowledge was just not enough

A couple of days ago I run into the same problem. I had a view page that when accessed wanted to know two things:

  • First was the ${row.rowKeyStr} of the row to display and ...
  • Next a session scope boolean parameter called #{sessionScope.returnHome} that indicated whether to return the user to the application home page or to another (the search in that case) page.

To summarize, I ended up with the a button called View record in two different pages both having a navigation case (also called view) linking to the view record page. in the application JSF diagram.

On both cases the expression #{row.rowKeyStr} had to be recorded in the JSF session scope along with a value for the returnHome flag that had to be true on one occasion and false on the other..

Following is the code I used to perform this. First the base class :

package myapp.view.backing;

import javax.faces.application.Application;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;

class backing_SRListBase {

    public backing_SRListBase()
    {
    }
    
    public String viewButtonBase_action( boolean returnHome)
    {
        // access the faces context
        FacesContext fc = FacesContext.getCurrentInstance();
        Application app = fc.getApplication();
        
        // on both case row.rowKeyStr points to the current row key
        ValueBinding vbActRowKey = app.createValueBinding("#{row.rowKeyStr}");
        String rowKey = (String )vbActRowKey.getValue(fc);
                
        // in that case we must save that in sessionScope
        ValueBinding vbSessionScopeRowKey = app.createValueBinding("#{sessionScope.rowKey}");
        vbSessionScopeRowKey.setValue( fc, rowKey);
                
        // also save the return home boolean value
        ValueBinding vbReturnHome = app.createValueBinding("#{sessionScope.returnHome}");
        vbReturnHome.setValue( fc, new Boolean( returnHome));
        
        return "view";
    }
}

Finally, the backing bean for each of the two pages looks like this

package myapp.view.backing;

public class backing_OpenSRList 
    extends backing_SRListBase {

    public backing_OpenSRList()
    {
    }

    public String viewButton_action()
    {
        return viewButtonBase_action( false);
    }
}

Friday, 11 January 2008

Java: Dates/Times and Calendars

The problem that many new Java programmers -- me included -- face when they start dealing with dates and times is : Given a java.util.Date object get month, date and year fields in separate variables.

The usual misunderstanding here is that the class java.util.Date is almost deprecated and all things you expect to be able to perform with dates are done using the java.util.Calendar; class.

Calendar is an abstract class whose javadoc can be found here. The class provides get and set methods that allow you to alter any of the fields that constitute a point in time. The following example demonstrates one way to calculate the date corresponding to the start of the current term, using the Calendar get and set functions. It also shows how to convert a Date to a Calendar and vice versa.

    private void calStartOfCurrentTerm()
    {
        // create a new Gregorian Calendar
        Calendar c = new GregorianCalendar();
        // you can synchronize a Calendar with a date by using the
        // setTime() method
        c.setTime( new Date());
        
        // once you get a Calendar extracting field information is 
        // as easy as ....
        int month = c.get( Calendar.MONTH);
        int day = c.get(Calendar.DAY_OF_MONTH);
        int year = c.get(Calendar.YEAR);
        
        // let's calculate the date that corresponds to the 
        // start of the current term
        int newMonth;
        
        switch (month) {
        case Calendar.JANUARY:
        case Calendar.FEBRUARY:
        case Calendar.MARCH:
            newMonth = Calendar.JANUARY;
            break;
        case Calendar.APRIL:
        case Calendar.MAY:
        case Calendar.JUNE:
            newMonth = Calendar.JANUARY;
            break;
        case Calendar.JULY:
        case Calendar.AUGUST:
        case Calendar.SEPTEMBER:
            newMonth = Calendar.JULY;
            break;
        default:
            newMonth = Calendar.OCTOBER;
        }
        
        // adjust the calendar to point to the new date
        c.set(Calendar.MONTH, newMonth);
        c.set(Calendar.DAY_OF_MONTH, 1);
        
        // get the information to a new date variable
        Date startOfTerm = c.getTime();
        
        // display results
        System.out.println("Day is " + day +" month is " + month + " year is " + year);
        System.out.println( startOfTerm.toString());
    }

Here is a slightly different version that returns an object of type oracle.jbo.domain.Date

import java.sql.Timestamp;

import java.util.Calendar;
import java.util.GregorianCalendar;

import oracle.jbo.domain.Date;

  private Date getStartOfTerm()
  {
    // create a new Gregorian Calendar
    Calendar c = new GregorianCalendar();

    // once you get a Calendar extracting field information is 
    // as easy as ....
    int month = c.get(Calendar.MONTH);

    // let's calculate the date that corresponds to the 
    // start of the current term
    int newMonth;

    switch (month) {
      case Calendar.JANUARY:
      case Calendar.FEBRUARY:
      case Calendar.MARCH:
        newMonth = Calendar.JANUARY;
        break;
      case Calendar.APRIL:
      case Calendar.MAY:
      case Calendar.JUNE:
        newMonth = Calendar.JANUARY;
        break;
      case Calendar.JULY:
      case Calendar.AUGUST:
      case Calendar.SEPTEMBER:
        newMonth = Calendar.JULY;
        break;
      default:
        newMonth = Calendar.OCTOBER;
    }

    // adjust the calendar to point to the new date
    c.set(Calendar.MONTH, newMonth);
    c.set(Calendar.DAY_OF_MONTH, 1);
    c.set(Calendar.HOUR_OF_DAY, 0);
    c.set(Calendar.MINUTE, 0);
    c.set(Calendar.SECOND, 0);
    c.set(Calendar.MILLISECOND, 0);
    
    // get the information to a new date variable
    java.util.Date javaDate = c.getTime();
    Timestamp st = new Timestamp(javaDate.getTime());
    return new Date(st);
  }

PS:. Finally There is one last thing I have to get used to. "Copy as HTML" on JDeveloper 10g, does not work on openSUSE 10.2.

Friday, 9 November 2007

ADF/JSF Getting the current row with code executed from a table bucking bean

The following code comes from the JDeveloper Forums courtesy of Frank Nimphus. If added to any event listener fired from "inside" an ADF Table, it prints the row's 1'st attribute and the rowKey.

        FacesContext fctx = FacesContext.getCurrentInstance();
        ValueBinding vb = (ValueBinding) fctx.getApplication().createValueBinding("#{row}");
        JUCtrlValueBindingRef rwbinding = (JUCtrlValueBindingRef) vb.getValue(fctx);
        System.out.println("--- Key as String --"+rwbinding.getRow().getKey().toStringFormat(true));
        System.out.println("--- First Attribute ---"+rwbinding.getRow().getAttribute(1));

Thanks again Frank

ADF/JSF Avoiding uncought exeptions after commit.

When using Oracle JDeveloper 10.1.3.x, you can find it very tempting to create "Create/Edit Record" pages by dropping an ADF Form on a blank JSF page and then adding commit and rollback buttons in the place of the ok and cancel buttons with an action property that returns your users to the browse page.

So let's assume that your faces-config file contains a navigation case labeled "return", that leads from you edit page back to your browse page. In cases like these, the code for the commit button will more or less look like this

                      <af:commandButton 
                                     actionListener="#{bindings.Commit.execute}"
                                     text="Ok" 
                                     action="return"
                                     id="commitButton"
                                     disabled="false"/>

This approach, presents a very serious hazard, which is a bug in Oracle's JSF implementation. If any exception is thrown after commit, the framework moves to the page designated by the navigation case and the error messages are not being displayed at all.

To make matters worse, you end up with on open transaction and nothing else entered in this manner ever gets stored in your database while you users have no way to realize that something has gone wrong. I had raised an SR for this that ended up in a one off patch (5630740) for JDeveloper 10.1.3.2.

I run into this problem again in am application that I developed recently using JDeveloper 10.1.3.3. And then it hit me. The solution was as simple as the Egg of Columbus. The only thing that needs to be done is to bind the commit button action in a backing bean. JDeveloper will then change the button tag into something like :

                      <af:commandButton 
                                    text="Accept"
                                    id="commitButton"
                                    disabled="false"
                                    action="#{backing_Edit.commitButton_action}"/>

... create the following code :

    public String commitButton_action()
    {
        BindingContainer bindings = getBindings();
        OperationBinding operationBinding =
            bindings.getOperationBinding("Commit");
        Object result = operationBinding.execute();
        if (!operationBinding.getErrors().isEmpty()) {
            return null;
        }
        return "return";
    }

... and that does it. Commit exception messages are displayed correctly and everyone is happy.

In case you have many edit pages with different navigation case labels then you might wish to create a solution that is a little more sophisticated and closer to the OO paradigm. In a case like this I suggest that you create a base class to be the parent of all your page backing beans and add the following method.

public class MyBackingBase
{
    protected String executeCommit( BindingContainer bindings, String successValue)
    {
        OperationBinding commitBinding =
            bindings.getOperationBinding("Commit");
        
        commitBinding.execute();
                
        return commitBinding.getErrors().isEmpty() ? successValue : null;
    }
 }

Having done that the actual backing bean code could be something as simple as

    public String commitButton_action()
    {
        return executeCommit( getBindings(), "return");
    }

... and one more thing. The Copy as HTML function is not available again. I guess I 'll have to start looking why .. :-(

Wednesday, 3 October 2007

Java: How to tell if an LDAP user is member of a group

Here is a Java class that I use in order to determine if a user of an LDAP server is a member of a group. The class uses the Mozilla LDAP SDK available for download from Mozilla

In many JSF applications this class lies in the heart of my UserInfo managed beans allowing or f orbiting access to various parts of the application.

Things you need to fill before using it are :

  • server name or IP address
  • Server port
  • A user name and a password that will allow your code to execute queries on the LDAP Server
  • The base DN to start the search at

The usual place to find these values is the LDAP server itself. If you server is an Oracle IAS 10.2 infrastructure then check the file $ORACLE_HOME/install/portlist.ini.


package ab.util.ldap;

import java.util.Enumeration;

import netscape.ldap.LDAPAttribute;
import netscape.ldap.LDAPConnection;
import netscape.ldap.LDAPEntry;
import netscape.ldap.LDAPException;
import netscape.ldap.LDAPReferralException;
import netscape.ldap.LDAPSearchResults;

public class MyLDAP 
{
    public static final String ldapHost = "ldap.shelman.int";
    public static final int ldapPort = 3060;
    private static final String authid = "cn=orcladmin";
    private static final String authpw = "my_password";
    private static final String base = "cn=groups,dc=shelman,dc=int";

    /**
     * isGroupMember -- determine if user belongs to an LDAP group
     *
     * #param group name of group to examine
     * #param user name user to search for emembership+-
     */
    public static boolean isGroupMember(String group, String user) 
    {
        String member = "cn=" + user.toLowerCase();
        String filter = "(cn=" + group + ")";
        String[] attrs = { "uniquemember" };
        boolean result = false;

        LDAPConnection ld = new LDAPConnection();
        // System.out.println("Attempting to connect :"  + today.toString());
        try {
            // connect to server and authenticate
            ld.connect(ldapHost, ldapPort, authid, authpw);
            // issue the search request
            LDAPSearchResults res =
                ld.search(base, ld.SCOPE_SUB, filter, attrs, false);
            // loop on results until complete
            while (res.hasMoreElements()) {
                try {
                    LDAPEntry entry = res.next();
                    LDAPAttribute atr = entry.getAttribute(attrs[0]);
                    Enumeration enumVals = atr.getStringValues();

                    while (enumVals != null && enumVals.hasMoreElements()) {
                        String val = (String)enumVals.nextElement();
                        // convert to lower case
                        val = val.toLowerCase();

                        if (val.indexOf(member) >= 0) {
                            result = true;
                            break;
                        }
                    }

                } catch (LDAPReferralException ex) {
                    // ignore referal exceptions
                    continue;
                } catch (LDAPException ex) {
                    System.out.println(ex.toString());
                    continue;
                }
            }
        } catch (Exception ex) {
            System.out.println("Error communicating with LDAP Server " +
                               ldapHost + " Port " + ldapPort);
            System.out.println(ex.toString());
        }

        // finished searching. try to disconnect
        if (ld != null && ld.isConnected()) {
            try {
                ld.disconnect();
            } catch (LDAPException ex) {
                System.out.println(ex.toString());
            }
        }

        // return whatever found
        return result;
    }
}

The package ldapjdk-4.17-38 is included in the distribution of all openSUSE systems. For openSUSE 10.2 the package is available for download from here.

Thursday, 30 August 2007

JSF Basics Access the HTTP Session from a backing bean

Here is something I always seem to forget and never realy got to use :-)
Code to gain access to the HTTP session from a inside backing bean :

FacesContext fc = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest)fc.getExternalContext().getRequest();
HttpSession session = request.getSession();

Wednesday, 27 June 2007

JSF Basics Getting the value of an EL expression in code

You can use the following code to get the value of any EL expression defined inside your JSF page For example the following checks the value of the expression #{requestScope.requestRowKey}

        // access the faces context
        FacesContext fc = FacesContext.getCurrentInstance();

        ValueBinding vb = fc.getApplication().createValueBinding("#{requestScope.requestRowKey}");
        String rowKey = (String )vb.getValue(fc);

Assigning a new value can be preformed by using vb.setValue( Object o)

Tuesday, 15 May 2007

Oracle ADF Committing master and relevant detail rows simultaneously

There is no doubt that using a trigger to provide unique id's from a database sequence is the best way to handle primary keys. (By the way, I wonder which version of Oracle database will provide an auto-increment data type like MySQL?) There are cases however that require you to create master and detail records in the application server memory and then commit everything simultaneously like in the case of an e-shop where you have to keep both the order header and lines uncommitted until the user finally decides to place the order.

In cases like these, using the DBSequence type for the corresponding entity object attribute might get you into trouble, like I did just yesterday. Theory says that the value of a DBSequence key attribute is a (unique) negative number that later becomes the value assigned by the database trigger. What I did, was try to create detail rows programatically but the master attribute reference for these rows became the negative DBSequence value assigned to the header line at the start of the transaction. So when I tried to do the final commit I got a very clear error explaining that the foreign key constraint for the detail rows was violated.

The only reliable way I found to get myself out of this was to turn back to my old JDeveloper 10g Handbook (published back in 2004) and dig out the following code to allow my entities to obtain an id value directly from the database sequence, thus moving the trigger code from the DB to the application server. So overriding the create method for my custom order header entity object gave me something like this :


import oracle.jbo.server.SequenceImpl;

  ...

  /**
   * Provide a new order id from the SQ_ORDERS database sequence.
   */
  protected void create(AttributeList attributeList)
  {
      super.create(attributeList);
    
      // get a new sequence value for the order ID
      SequenceImpl sqOrders = new SequenceImpl("SQ_ORDERS", getDBTransaction());
      setOrderId( sqOrders.getSequenceNumber());
  }

Friday, 11 May 2007

Oracle ADF How to get the Date after n days and calculate the difference between two dates

I have used this little code fragment many times and each time I try to remember where -- and in which file -- was the last.

I guess that if I put it here, I will limit my search space significantly :-)

import oracle.jbo.domain.Date;
import oracle.jbo.domain.Number;
import java.sql.Timestamp;

...
static final long MILI_SECONDS_PER_DAY = 86400000;

    /**
     * @param startDate initial date to start counting from
     * @param nDays number of days can be begative
     * @return a Date object nDays after startdate
     */
    public static Date dateAfterNDays( Date startDate, int nDays)
    {
       if (startDate == null)
           startDate = new Date(Date.getCurrentDate());  // assume today

       Timestamp ts = startDate.timestampValue();
       long nextDatesSecs = ts.getTime() + (MILI_SECONDS_PER_DAY * nDays);
       return new Date( new Timestamp(nextDatesSecs));
    }

Here is an other example that calculates the number of days between two dates. The parameter dates are oracle.jbo.domain.Date and the return type is an oracle.jbo.domain.Number.

    /**
     * return the number of days between two dates
     */

    private Number dateDifference(InDays Date startDate, Date endDate)
    {
       if (startDate == null)
           startDate = new Date(Date.getCurrentDate()); // assume today

       if (endDate == null)
            endDate = new Date(Date.getCurrentDate());  // asume today again

       Timestamp tsStart = startDate.timestampValue();
       Timestamp tsEnd = endDate.timestampValue();

       long ndays = (tsEnd.getTime() - tsStart.getTime()) / MILI_SECONDS_PER_DAY;

       return new Number(ndays);
    }

Monday, 12 March 2007

Sending mail using Java Mail

In addition to the previous article, I shall provide here a slightly changed version of Sudhir Ancha's code as presented in his Sending Email From Your Application Using Java Mail article at javacomerice.com.

The only notable difference is the Charset = .. addition to the setContent() method of the message class, that allows sending the message using the iso8859-7 Greek character set.

package utils.mail;

import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;


/**
 * @class SendMail
 * Encapsulates a simple mail sending using a specific SMTP Server
 */
public class SendMail {
    // put you server here
    public static final String SMTP_HOST = "smtp.mydomain.com";

    public void post(String to, // recipient for the message
        String subject,         // subject
        String message,         // actual mesage text
        String from)            // address of sender
        throws MessagingException 
    {

        String[] recipients = new String[1];
        recipients[0] = to;

        postToMany(recipients, subject, message, from);
    }

    public void postToMany( String[] recipients, // list of recipients for the message
        String subject, // subject
        String message, // actual mesage text
        String from) // address of sender
        throws MessagingException 
    {
        boolean debug = false;

        //Set the host smtp address
        Properties props = new Properties();
        props.put("mail.smtp.host", SMTP_HOST);

        // create some properties and get the default Session
        Session session = Session.getDefaultInstance(props, null);
        session.setDebug(debug);

        // create a message
        Message msg = new MimeMessage(session);

        // set the from and to address
        InternetAddress addressFrom = new InternetAddress(from);
        msg.setFrom(addressFrom);

        InternetAddress[] addressTo = new InternetAddress[recipients.length];
        for (int i = 0; i < recipients.length; i++) 
            addressTo[i] = new InternetAddress(recipients[i]);
        
        msg.setRecipients(Message.RecipientType.TO, addressTo);

        // Content-type: text/html; charset=utf-8\r\n
        // Optional : You can also set your custom headers in the Email if you Want
        // msg.addHeader("Content-type", "text/html; charset=utf-8");

        // Setting the Subject and Content Type
        msg.setSubject(subject);
        msg.setContent(message, "text/plain; Charset=iso8859-7");
        Transport.send(msg);
    }

    private static final String emailMsgTxt = "Δοκιμαστικό μύνημα σταλμένο από Java.";
    private static final String emailSubjectTxt = "EMail from Java";
    private static final String emailFromAddress = "me@mydomain.gr";
    private static final String[] emailList = {
            "he@hisdomain.com",
            "she@herdomain.gr" 
    };
    

    public static void main(String[] args) throws Exception 
    {
        SendMail smtpMailSender = new SendMail();
        smtpMailSender.post("me@mydomain.om", emailSubjectTxt, emailMsgTxt,
                            emailFromAddress);
        System.out.println("Sucessfully Sent mail to All Users");
    }
}