Pages

Sunday, January 30, 2011

Java EE: The dead man walking... I'm not Dead Yet!

N49 Stellar Debris
I just read Andrew Binstock's Integration Watch column with the same title as this post. The majority of the article is interesting, and tells a little history about Java Enterprise Edition (EE) over the years. He makes a comment that was very well put about Spring.
...Spring is an omnibus solution that rides on the entire Java EE stack, it does not reduce the complexity so much as mask it.
A very well put quote. I am a more casual Spring user than advocate. I think it fills in nicely where the gaps lay for me in the EE specification. I believe that we should use tools to solve problems, and this is one such tool. I think that the quote sums up our need for Spring because the specification is lacking.

His follow-on comments on the status of Java EE 6 implementations is correct about the number, but he misses the point that there are a number of folks who are working on implementations. Weblogic should be EE 6 compliant this year.  Caucho is working on a web profile compliant version, and the others will follow. They must, or will be left behind. The nice thing about specifications is that it keeps moving the bar.

The tone seems to indicate that GlassFish does not seem capable of enterprise adoption, and that we must wait for the "big" boys to come and play. This is simply not the case. GlassFish 3.0.1 is a fine solution, and most developers would suffice with the web profile as he previously noted with Apache Tomcat. If you need enterprise robustness, GlassFish 3.1 should be available in the next few months. I just checked the timeline and needs to be updated. I will just leave it at that. I have 3.1 build 38 running, and it works just fine.

I disagree with Alex Handy that Java EE is no longer the future of enterprise Java. We are not on the cusp, and this is not an end. GlassFish is innovation. Oracle has been very excited about the modularization. This has made it easier for them to incorporate in their flagship products. Innovation is clearly apparent in the number of other platforms which include the various GlassFish modules in their products.

The demise of dynamic language enthusiasm is real, but GlassFish will continue to support running these VM languages as first class citizens. My Redmine (RoR) instance on JRuby clearly demonstrates this.

The IOUC/JUG Leaders Summit at Oracle had a number of talks about the future of EE and its direction. The direction from Oracle was actually very open for EE 8. They have a number of items for EE 7 that they would like to see, and will provide JSRs for them. There is a general JSR clean-up effort on the part of Oracle. They want to deliver innovation and a path forward, but would like to finish, or close the open JSR promises to the community. That was very apparent to me.

Oracle will provide its plans on EE 7 sooner than later, and I don't want to preempt them in anyway. I would note that they are sensitive to the cloud computing environment. We discussed Amazon's Beanstalk service, and some of us expressed a desire to see GlassFish EE 6 as an option. I think that would be a win-win for both companies. We encouraged the Oracle staff present to consider it. This is not tantamount to some announcement, but a desire by those present in the room.

Andrew was correct on the path forward must include cloud computing, but we are not a dead man walking. His reference to monolithic application servers is actually old school. GlassFish is modular, and will continue towards becoming more modular along with Java SE including JSR-294.

My response to Andrew's article is simply a piece from Monty Python:

The Dead Collector: Bring out yer dead.
[a man puts a body on the cart]
Large Man with Dead Body: Here's one.
The Dead Collector: That'll be ninepence.
The Dead Body That Claims It Isn't: I'm not dead.
The Dead Collector: What?
Large Man with Dead Body: Nothing. There's your ninepence.
The Dead Body That Claims It Isn't: I'm not dead.
The Dead Collector: 'Ere, he says he's not dead.
Large Man with Dead Body: Yes he is.
The Dead Body That Claims It Isn't: I'm not.
The Dead Collector: He isn't.
Large Man with Dead Body: Well, he will be soon, he's very ill.
The Dead Body That Claims It Isn't: I'm getting better.
Large Man with Dead Body: No you're not, you'll be stone dead in a moment.
I just hope I don't get hit with a club.
Enhanced by Zemanta

NetBeans IDE (I Don't Envy) Oracle Question

oRAclE by Bert Breeman
Last week I was an attendee at the IOUC/JUG Leaders Summit held at Oracle. During the course of the week, we had a couple of presentations where it was mentioned that Oracle would continue to enhance JDeveloper, and provide resources for NetBeans.

Curiously, the presenters mentioned Oracle Enterprise Pack for Eclipse (OEPE) a number of times. The disturbing part was that it was mentioned twice (I am sure of it) was that Oracle is a good friend to the Eclipse community, and sits on the Eclipse Foundation Board. The other JUG leaders also took note of it, and it was a dinner and drinks topic. The other leaders noted it, but we all decided that it was "true" so nothing more came of it.

Let us advance a couple of days...

I see a twitter message about dropping Ruby support in NetBeans. The room was probably not even clean yet from the conference when the announcement came out. Oracle had very carefully crafted the event, topics, discussions (except the un-conference), etc. It was very well done. The respective executives, directors, department heads, and technical leads were present. Every "i" dotted, and every "o" covered. A well "O"iled machine. The JUG leaders are largely NetBeans users though some use other IDEs like Eclipse, and IntelliJ IDEA. This would have been important to a number of us (including me). It IS possible that someone at Oracle missed the communications stream, and failed to mention it at a large meeting. This IS possible. I don't want to spread FUD, but if it is a major miss by Oracle communications. It is like the picture above...lacking a few letters.

Here is some information that is NOT FUD:

To maintain that objective and capitalize on the JDK 7 release
themes--multi-language support, developer productivity and
performance--it is necessary that our engineering resources are
committed to a timely and quality release of NetBeans IDE 7.0. 

Second: Although our Ruby support has historically been well received,
based on existing low usage trends we are unable to justify the
continued allocation of resources to support the feature.

The bold sections above seem to contradict the stated support by Oracle of the NetBeans team.

The Grand Canyon was started as a trickle that eroded a rock solid foundation.  Seventeen million years ago we could have have hopped the stream. Today there is no way to close the gap, and the rift continues.  My question is this the trickle?

Friday, January 28, 2011

JCP - A Question of Validity

113Image via Wikipedia
At the recent IOUC / JUG Leaders Summit I attended this week, it was announced that Sou Java's Bruno Souza is being nominated to fill the open JCP Executive Committee (EC) position vacated by the Apache Foundation. Although there is not way to fill the void filled by the loss of Apache on the JCP, Bruno's nomination is a good replacement. I hope and encourage all other JCP members to follow me and ratify his position in the upcoming special election.

Patrick Curran posted in his blog The Fine Print - For Your Eyes Only that there are a number of negative perceptions about the JCP. I couldn't agree more. I have added some comments to his post which I hope he will approve soon. I believe that the only way to fix the majority of these negative perceptions is through change. Bruno is the start of that change.

When I spoke to Patrick at the conference, he convinced me that we (JUG Leaders, and community members) can make a difference. We spoke about the transparency which he wrote very eloquently about in his blog post, and how to effect change in the JCP.

I will tell the same story here which I added as comments to Patrick's blog post. I always tell my kids that unless you ask, the answer is always "no". If you want to make a change you must be willing to ask, you may be surprised that in a lot of cases, the answer will be a "yes".

I personally am sick and tired about hearing how broken the JCP is. The JCP EC is comprised of 15 seats. Ten of the seats are nominated by Oracle and ratified by the JCP members. The remaining five seats are openly elected seats. Here is my proposal: JUGs should fill those seats via the election process, unless a qualified individual from the community nominates themselves.  This will ensure that the Java community is well represented at the JCP EC table.

I want to be very clear that individuals from the community should be given priority over JUG communities per se. I don't want the JUG Leaders and JUGs accused of being just another set of large organizations vying for positions. It is my intent to protect those openly elected seats for members of the community, or JUGs for safekeeping if no other qualified individuals step forward.

I believe that with 1/3 of the voting block in control of the community, we can make the changes necessary to bring further transparency, and legitimacy to the JCP.

Do not get me wrong, I believe that the loss of Apache Foundation and Doug Lea are terrible for the Java ecosystem. I want Apache back on the EC, but I understand their position. I want to make the changes necessary to the JCP to have them back at the table. I would be the first person to pull out a chair for them. Until that time, it is up to us to make the difference.

I will propose that the JUG Leaders take a look at my post, and we as a community can decide on how to proceed. I am willing to nominate myself for the elected position in the upcoming election, but would readily concede to another candidate that represents the community like Bruno. I just want to make sure that we do not miss out on the opportunity that presents itself before us.

Any JUG, or individual who is not a member of the JCP is encouraged to join and be a part of the solution. I see opportunity, and think it could be an exciting time to be a part of something that matters. If you are reading this blog post and have gotten this far, you need to be a participant otherwise the answer will be... "no".
Enhanced by Zemanta

Saturday, January 15, 2011

JavaOne 2010 Improvements for JavaOne 2011

I was going over my list of things to improve for JavaOne 2011 based on my experience in 2010. All things considered, it was a worthwhile conference to attend as always.

I love to see my friends, peers, colleagues, collaborators, and everyone who participates in the event that is JavaOne.

I thought I would publish this list I made last year, and see what changes are made for 2011. We can see if Oracle took some of the feedback to heart, and what improvements they will make.
  1. If you are going to advertise a scheduling application, make sure it works. It was an epic failure at a developer conference.
  2. Make it known to the attendees where sponsors are located, and pavilion areas. Ensure that attendees can get into the areas. Security was turning people back.
  3. Communicate. The lack of communication was very apparent. Use social media more to show changes, and updates. Do some house keeping at the beginning/end of keynotes.
  4. Have more entrances at the OTN party. No one knew how to get in, and the security were very unpleasant.
  5. Have the Duke Awards given out in a public venue. Don't hand them out at an event that only a select few could attend.
  6. Ensure that the labs work. The machines, and setup failed at most labs that people attended.
  7. Set up the schedules, and do not constantly change them. Confusion was the rule rather than exception.
  8. Provide accurate maps to the technical sessions. The Hilton is a maze. I would rather have it at Moscone, but if we must use hotels, have clearly displayed maps to the sessions.
  9. Deliver some content, and QUIT prefixing every presentation with "safe harbor". Face it, if you mention it at a conference, the street expects you to deliver. Get over it.
  10. Try to separate the community events sufficiently to allow attendees to go to multiple events like JUG and GlassFish events. Maybe split it into late morning/afternoon.
  11. Offer food/beverages to community event attendees to keep them in the venue.
  12. Have the Community Leaders/Technical Leads attend the JUG event so they can meet their advocates.
  13. Keep the JUG Leader/Java Champions breakfast with Oracle staff. This was extremely beneficial.
  14. Host a young developers/Lego Mindstorm/FIRST Robotics competition at the event and give the kids free passes. Start them young, and show them opportunities in the larger Java ecosystem.

Tuesday, January 11, 2011

Java Reflection getDeclaredMethod() and getDeclaredField() Examples with Primitives

George W. Hart
I recently have had to use some classes which were developed some time ago with a lot of complex methods and a number of fields. The problem was that these methods and fields are private. If they were protected, then I could subclass to gain access to them.

The example I have included below sets a field in a super class, Calendar, of GregorianCalendar. The field is also protected so I need to set its accessibility to set the field,  modify it, and reset the accessibility.

In the second example, I have a private method of the GregorianCalendar which takes two int arguments. This becomes very tricky since the getDeclaredMethod(String name, Class<?>... parameterTypes) requires Class arguments. Your initial response might suggest that you can use a wrapper class for your primitives such as Integer.class. This will not work.

There are eight Type wrappers for your Class<?> primitives including void: Integer.TYPE, Long.TYPE, Character.TYPE, Short.TYPE, Double.TYPE, Float.TYPE, Boolean.TYPE, and Void.TYPE. These are key to using the getDeclaredMethod() method. In the example I use, Integer.TYPE.

When you have your Method object, you must call the invoke(Object obj, Object... args). We use the instance of the Object we want to modify, and pass in an array of Object arguments. In this case, I use the wrapper method for Integer to wrap my primitive arguments.



/*
 *  Copyright 2011 Blue Lotus Software, LLC.
 *  Copyright 2011 John Yeary <jyeary@bluelotussoftware.com>.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */
/*
 * $Id: App.java 331 2011-01-11 13:54:06Z jyeary $
 */
package com.bluelotussoftware.example.reflection;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.GregorianCalendar;

public class App {

    public static void main(String[] args) throws NoSuchFieldException, IllegalArgumentException,
            IllegalAccessException, NoSuchMethodException, InvocationTargetException {

        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        // Field Reflection 
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        GregorianCalendar calendar = (GregorianCalendar) Calendar.getInstance();
        System.out.println("Unmodified Calendar Time (ms): " + calendar.getTimeInMillis());
        System.out.println("Unmodified Calendar Time (Date): " + calendar.getTime());

        /*
         * The field we want to modify is in the super class.
         */
        Field field = calendar.getClass().getSuperclass().getDeclaredField("time");

        /*
         * Since the field is protected we need to make it accessible since
         * our class does not extend GregorianCalendar.
         */
        field.setAccessible(true);

        /*
         * The field we are setting is in the super class, but we are using
         * the sub-class instance to set the field.
         */
        field.setLong(calendar, 4 * 60 * 60 * 1000L + 55 * 60 * 1000L); //23:55:00

        /*
         * Turn off the accessibility after our modification.
         */
        field.setAccessible(false);

        System.out.println("Modified Calendar Time (ms): " + calendar.getTimeInMillis());
        System.out.println("Modified Calendar Time (Date): " + calendar.getTime());

        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        // Method Reflection
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        String methodName = "monthLength";

        /*
         * If you are using primitives, you must use their Class.TYPE
         * such as Boolean.TYPE, Integer.TYPE, Double.TYPE, etc.
         */
        Class[] methodParameters = new Class[]{Integer.TYPE, Integer.TYPE};

        /*
         * Month is 0 based so February = 1. 2008 is a leap year.
         */
        Object[] params = new Object[]{new Integer(1), new Integer(2008)};

        Method method = calendar.getClass().getDeclaredMethod(methodName, methodParameters);

        /**
         * The Method is private so we must make it accessible to modify it.
         */
        method.setAccessible(true);
        Integer monthLength = (Integer) method.invoke(calendar, params);
        method.setAccessible(false); // Reset accessibility
        System.out.println("Month length (2/2008): " + monthLength);
    }
}

Monday, January 10, 2011

JSF 2.x Injecting @ManagedBean Instances

Here are three ways to inject a @ManagedBean into another @ManagedBean. In Java EE 6, the preferred method is to use the @ManagedProperty annotation. You can however use JSF 2.x in Java EE 5. You must simply replace the current JSF implementation with Mojarra 2.x. If this is the case,  the use of annotations is not possible. Two techniques below will work on EE5 and EE6 applications.

@ManagedProperty

The @ManagedProperty annotation will work on Java EE 6 applications as noted. To use the annotation,  you must provide the EL name of the bean you wish to access, and provide a setter for the property in your code. Note: If you forget the setter, it will not work.


@ManagedPropery(value="#{beanName}")
private Bean bean;

public void setBean(Bean bean) {
this.bean = bean;
}

<T> T getBean(String)


This version will work with Java EE5 and EE6.


/*
 *  Copyright 2011 Blue Lotus Software, LLC.
 *  Copyright 2011 John Yeary <jyeary@bluelotussoftware.com>.
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */

     /**
     * Return a reference to the bean from the {@link javax.faces.context.ExternalContext#getApplicationMap()}.
     * @param <T> type of class.
     * @param beanName name of the class to search for in {@link javax.faces.ExternalContext#getApplicationMap()}.
     * @return referenced bean.
     */
    protected <T> T getBean(String beanName) {
        return (T) FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().get(beanName);
    }
}

<T> T getBean(String beanName, Class<T> beanClass)

This version will work with Java EE5 and EE6.

/*
 *  Copyright 2011 Blue Lotus Software, LLC.
 *  Copyright 2011 John Yeary <jyeary@bluelotussoftware.com>.
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */
    /**
     * Return a reference to the bean from the {@link javax.faces.context.FacesContext#getCurrentInstance()}.
     * @param <T> type of class.
     * @param beanName name of the class to search for in {@link javax.faces.context.FacesContext}.
     * @param beanClass class type of bean to return.
     * @return referenced bean.
     */
    protected synchronized static <T> T getBean(String beanName, Class<T> beanClass) {
        FacesContext context = FacesContext.getCurrentInstance();
        Application application = context.getApplication();
        return (T) application.evaluateExpressionGet(context, "#{" + beanName + "}", beanClass);
    }

Wednesday, January 05, 2011

@PersistenceUnit vs @PersistenceContext in Servlets

Duke, the Java Mascot, in the waving pose. Duk...Image via Wikipedia
Someone posted a comment that they could not use @PersistenceContext in a servlet based on a previous post Persistence Unit or Persistence Context?. Normally I would just chock it up to someone doing something wrong, and try to help them fix it. However, I thought it would be a good teaching moment. I am usually found in the JSF world,  and don't use servlets directly much anymore. That is until recently.

I have attached a NetBeans 6.9.1 Java EE 6 project called MultiplePersistenceContextsServlet.zip which shows that you can use both @PersistenceUnit and @PersistenceContext in a servlet. In fact this particular servlet uses both. The application uses the default JavaDB database in GlassFish.

Note: Just because both work, does not mean it is always the best course of action. In your enterprise applications you should be using @PersistenceUnit because it is thread safe. (Thanks @alexismp for reminding me of that, and sending me Sahoo's article link.). Sahoo wrote a good article on this with a good explanation: Don't use @PersistenceContext in a web app....

It is a simple example using multiple Java EE 6 technologies. You should get this result if you run it in NetBeans 6.9.1


InjectedServlet.java



Enhanced by Zemanta

Tuesday, January 04, 2011

JSF 2.x Forwarding Request to a Servlet

The question of how to forward a JSF Request to a server was something that came up the other day. I have some legacy servlets which will handle some of the information which is being generated from my JSF pages.

So I decided to write an example of how to do it. The example is designed to go from a JSF page to a servlet which will process the headers and display the information. The alternate example passes the request to a servlet which then passes it back to another JSF page for display. The example also demonstrates using a <f:param /> to pass additional information. The project was done using NetBeans and Maven 2.

Note: The project files can be downloaded here: jsf-servlet-forwarding.zip

As you can see from the images, the forms are very simple and used for demonstration only.
JSF Request Form

index.xhtml


       <h:form id="form1">
            <h:panelGrid id="panelGrid1" columns="1">
                <h:outputLabel id="outputLabel1" for="inputText1" value="Please enter your name:"/>
                <h:inputText id="inputText1" value="#{indexBean.name}" required="true"/>
                <h:message id="message1" for="inputText1"/>
                <h:panelGroup id="panelGroup1">
                    <h:commandButton id="commandButton1" value="Forward" type="submit" action="#{indexBean.forward}"/>
                    <h:commandButton id="commandButton2" value="Process" type="submit" action="#{indexBean.forward}">
                        <f:param id="param1" name="target" value="/results.xhtml"/>
                    </h:commandButton>
                </h:panelGroup>
            </h:panelGrid>
        </h:form>

JSF -Servlet -JSF Response

results.xhtml


This file has some interesting syntax which a number of people may not be used to seeing, for example #{param['form1:inputText1']} which is using Expression Language (EL) to read the param[] and find the specific form element which is in single quotes.


    <h:body>
        <p>
            <h:outputText id="outputText1" value="TA DA!" style="font-weight: bold; font-size: larger; text-align: center;"/>
        </p>
        <p>
            <h:outputText id="outputText2" value="Hello #{param['form1:inputText1']}!"/>
        </p>
        <p>
            <h:outputText id="outputText3" value="'target' ==> #{param.target}"/>
        </p>
        <p>
            <h:outputText id="outputText4" value="'form1:inputText1' (name) ==> #{param['form1:inputText1']}"/>
        </p>
        <h:form id="form1">
            <h:commandButton id="commandButton1" type="submit" value="Back" action="index.xhtml"/>
        </h:form>
    </h:body>

Servlet Response

ProcessServlet.java



/*
 *  Copyright 2011 Blue Lotus Software, LLC.
 *  Copyright 2011 John Yeary <jyeary@bluelotussoftware.com>.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */
/*
 * $Id: ProcessServlet.java 324 2011-01-05 03:02:41Z jyeary $
 */
package com.bluelotussoftware.example.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * An example servlet which reads the {@link javax.servlet.http.HttpServletRequest} and
 * displays the values on an HTML page, or if the parameter 'target' is set, it will
 * forward the {@link javax.servlet.http.HttpServletRequest} and
 * {@link javax.servlet.http.HttpServletResponse}.
 * 
 * @author John Yeary <jyeary@bluelotussoftware.com>
 * @version 1.0
 */
public class ProcessServlet extends HttpServlet {

    private static final long serialVersionUID = -380096497389125142L;

    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        if (request.getParameter("target") != null) {
            System.out.println("TARGET: " + request.getParameter("target"));
            RequestDispatcher dispatcher = request.getRequestDispatcher(request.getParameter("target"));
            dispatcher.forward(request, response);
        } else {
            response.setContentType("text/html;charset=UTF-8");
            PrintWriter out = response.getWriter();
            try {

                out.println("<html>");
                out.println("<head>");
                out.println("<title>Servlet ProcessServlet</title>");
                out.println("</head>");
                out.println("<body>");
                out.println("<h1>Servlet ProcessServlet at " + request.getContextPath() + "</h1>");

                out.println("<h2>Headers</h2>");
                Enumeration<String> headers = request.getHeaderNames();

                while (headers.hasMoreElements()) {
                    String s = headers.nextElement();
                    out.println("<p>" + s + " : " + request.getHeader(s) + "</p>");
                }

                out.println("<h2>Attributes</h2>");
                Enumeration<String> attributes = request.getAttributeNames();

                while (attributes.hasMoreElements()) {
                    String s = attributes.nextElement();
                    out.println("<p>" + s + " : " + request.getAttribute(s) + "</p>");
                }

                out.println("<h2>Parameters</h2>");
                Enumeration<String> parameters = request.getParameterNames();

                while (parameters.hasMoreElements()) {
                    String s = parameters.nextElement();
                    out.println("<p>" + s + " : " + request.getParameter(s) + "</p>");
                }

                out.println("</body>");
                out.println("</html>");

            } finally {
                out.close();
            }
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}

IndexBean.java



/*
 *  Copyright 2011 Blue Lotus Software, LLC.
 *  Copyright 2011 John Yeary <jyeary@bluelotussoftware.com>.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */
/*
 * $Id: IndexBean.java 324 2011-01-05 03:02:41Z jyeary $
 */
package com.bluelotussoftware.example.jsf.bean;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * {@link javax.faces.bean.ManagedBean} for the {@literal index.xhtml} which is
 * used for demonstration of forwarding {@link javax.servlet.http.HttpServletRequest}
 * and {@link javax.servlet.http.HttpServletResponse} to an external servlet.
 *
 * @author John Yeary <jyeary@bluelotussoftware.com>
 * @version 1.0
 */
@ManagedBean
@RequestScoped
public class IndexBean {

    /**
     * Field for name.
     */
    private String name;

    /**
     * Default Constructor
     */
    public IndexBean() {
    }

    /**
     * Getter for name field
     * @return name provided.
     */
    public String getName() {
        return name;
    }

    /**
     * Setter for name field.
     * @param name value provided.
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * Forwards the {@link javax.servlet.http.HttpServletRequest} and
     * {@link javax.servlet.http.HttpServletResponse} to a servlet URL
     * pattern called {@literal /process}, and sets the {@link javax.faces.context.FacesContext#responseComplete()}.
     */
    public void forward() {
        try {
            FacesContext ctx = FacesContext.getCurrentInstance();
            ExternalContext ectx = ctx.getExternalContext();
            HttpServletRequest request = (HttpServletRequest) ectx.getRequest();
            HttpServletResponse response = (HttpServletResponse) ectx.getResponse();
            RequestDispatcher dispatcher = request.getRequestDispatcher("/process");
            dispatcher.forward(request, response);
            ctx.responseComplete();
        } catch (ServletException ex) {
            Logger.getLogger(IndexBean.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(IndexBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

Sunday, January 02, 2011

JSF 2.x ComponentSystemEvent UML Class Diagram

I have been working on creating examples of how to use the ComponentSystemEvent model. As a result, I reverse engineered the model in NetBeans and thought someone may find it useful. Once I have the examples completed, I will publish them.

Saturday, January 01, 2011

JSF 2.x Component prerender() (PreRenderComponentEvent)

In Project Woodstock (Visual JSF), the page bean had a number of methods which could be overridden to provide additional functionality by adding convenient interception points in the JSF life cycle. This additional functionality was one of the selling points of Woodstock (Project Rave). If you are using JSF 1.2, it is still compelling.

One method which was very important was the prerender() method. This method was invoked prior to the page being rendered on the client. The com.sun.rave.web.ui.appbase.AbstractPageBean has a very complete explanation:


/**
* Callback method that is called just before rendering takes place.
* This method will only be called for the page that
* will actually be rendered (and not, for example, on a page that
* handled a postback and then navigated to a different page). Customize
* this method to allocate resources that will be required for rendering
* this page.
*/

This allowed for late binding of the component. This functionality has been added to JSF 2.0 in the SystemEvent facility. It is captured in two interfaces: PreRenderComponentEvent and PreRenderViewEvent. I will focus on the first interface, and provide an example for you.

This functionality is accomplished using the <f:event/> tag.  In this series of examples we have an <h:outputText/> which has its value injected displaying the event which was called, and a second more useful example which pre-populates <f:selectItems/> for use in an <h:selectOneListbox/> which also includes <f:ajax/> to display the selected value.

event.xhtml



<?xml version="1.0" encoding="UTF-8"?>
<!--
 Copyright 2010 Blue Lotus Software, LLC.
 Copyright 2010 John Yeary <jyeary@bluelotussoftware.com>.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 under the License.
-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <title>&lt;f;event/&gt;</title>
    </h:head>
    <h:body>
        <h:form id="form1">
            <h:panelGrid id="panelGrid1" columns="1">
                <h:outputText id="outputText1">
                    <f:event id="event1" type="javax.faces.event.PreRenderComponentEvent" listener="#{eventBean.preRenderComponent}"/>
                </h:outputText>
                <h:selectOneListbox id="selectOneListbox" value="#{eventBean.selectedItem}">
                    <f:event id="event2" type="javax.faces.event.PreRenderComponentEvent" listener="#{eventBean.updateSelectItems}"/>
                    <f:ajax id="ajax1" render="outputText2"/>
                </h:selectOneListbox>
                <h:outputText id="outputText2" value="#{eventBean.selection}"/>
            </h:panelGrid>
        </h:form>
    </h:body>
</html>

EventBean.java



/*
 *  Copyright 2010 Blue Lotus Software, LLC.
 *  Copyright 2010 John Yeary <jyeary@bluelotussoftware.com>.
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */
/*
 * $Id:$
 */
package com.bluelotussoftware.example.jsf;

import java.util.ArrayList;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.component.UIOutput;
import javax.faces.component.UISelectItems;
import javax.faces.component.UISelectOne;
import javax.faces.event.ComponentSystemEvent;
import javax.faces.model.SelectItem;

/**
 * This is the {@link javax.faces.bean.ManagedBean} for the {@literal event.xhtml}
 * page. It is provided to demonstrate the {@literal <f:event/>} tag and its usage
 * in handling {@link javax.faces.event.PreRenderComponentEvent} events to populate
 * the representative components with values.
 * 
 * @author John Yeary <jyeary@bluelotussoftware.com>
 * @version 1.0
 */
@ManagedBean
@RequestScoped
public class EventBean {

    /**
     * value holder for the selected {@link javax.faces.component.html.HtmlSelectOneListbox}.
     */
    private String selectedItem;

    /**
     * Default constructor.
     */
    public EventBean() {
    }

    /**
     * Getter for the selected {@link javax.faces.component.html.HtmlSelectOneListbox}.
     * @return selected value.
     */
    public String getSelectedItem() {
        return selectedItem;
    }

    /**
     * Setter for the selected {@link javax.faces.component.html.HtmlSelectOneListbox}.
     * @param selectedItem set the component value.
     */
    public void setSelectedItem(String selectedItem) {
        this.selectedItem = selectedItem;
    }

    /**
     * Event Handler for {@link javax.faces.event.ComponentSystemEvent}. The usage here captures
     * the higher level event, but we are using it to capture {@link javax.faces.event.PreRenderComponentEvent}
     * and set the appropriate values.
     * @param event triggering component event to handle.
     */
    public void preRenderComponent(ComponentSystemEvent event) {
        UIOutput output = (UIOutput) event.getComponent();
        output.setValue(event.getClass().getName() + " fired.");
    }

    /**
     * Event Handler for {@link javax.faces.event.ComponentSystemEvent}. This method
     * sets the {@link javax.faces.component.UISelectItems} prior to the component being
     * rendered.
     * @param event triggering component event to handle.
     */
    public void updateSelectItems(ComponentSystemEvent event) {
        ArrayList<SelectItem> items = new ArrayList<SelectItem>();
        items.add(new SelectItem("Tuna", "Tuna"));
        items.add(new SelectItem("Salmon", "Salmon"));
        items.add(new SelectItem("Mojarra", "Mojarra", "A delicious fish, and UI framework."));
        items.add(new SelectItem("Tilapia", "Tilapia", null, true));
        UISelectItems selectItems = new UISelectItems();
        selectItems.setId("selectItems1");
        selectItems.setValue(items);

        UISelectOne uISelectOne = (UISelectOne) event.getComponent();
        uISelectOne.getChildren().add(selectItems);
    }

    /**
     * Returns the selected value.
     * @return selected value.
     */
    public String getSelection() {
        if (selectedItem != null) {
            return selectedItem;
        }
        return "Nothing Selected";
    }
}
}

Here is the result:

JSF 2.0 with Events and AJAX