Monday, 6 May 2013

[How To] - Fix GlassFish not listening to port 80 after updating security group's rule on Amazon EC2 instance

In one of my projects, after I've correctly updated the security groups's rules on my Amazone Linux EC2 instance to allow incoming connections to port 80 (HTTP) and 443  (HTTPS), my requests to these 2 ports are still ignored. If you do a sudo netstat -lntp, you will see that there is a process listening on port 4848 which is your GlassFish app server but it is NOT listening to port 80 and 443! Why!!?

If you take a look at the app server's log file right after starting it, you will see the Connection refuse exception. Assuming that you've already correctly set up GlassFish's http-listeners to listen to port 80 and 443, the solution is actually pretty simple: you have to start the server using the root privilege (i.e. sudo ./<GLASSFISH-FOLDER>/bin/asadmin start-domain). These 2 special ports seem to be protected by Linux OS. You cannot listen to these 2 ports without having access to root privilege.

I hope this helps! :).. 

Thursday, 4 April 2013

[Fact] - The order of calling for Action and Listener in JSF

During the coding process, sometimes, I still mix up the order that Action and ActionListener components would be triggered in JSF. In this small post, I will make a small experiment as a reminder to both you and me :).

Our test page will contain the following button:

And this is our test bean:

The following outcome was observed from the console:


At times, I tried in vain to set a property of the backing bean using <f:setPropertyActionListener> and get it out in the method inside actionListener. Don't make the same mistake :P!

From the above outcome, the actionListener attribute of the button is always called first while the action attribute is always called last. For the others, they will be called based on the order in which you declare them inside the button.

Hope this helps! :)

Tuesday, 2 April 2013

[How To] - Redirect to original page after login in JSF

Nowadays, redirecting users to where they were before logging is a common & desired feature for any web applications. For instance, if a user was surfing a page at http://example.com/yourapp/pageX.xhtml?param1=value1, the application should be able to redirect the user to the same page and, at the same time, retain the complete query string at the end of the requestURL.

In this tutorial, I will assume that your application has a login bar on top of all pages. Based on this assumption, your application needs to handle the following 3 scenarios:
  1. The user logs in directly from the top login bar and succeed.
  2. The user entered wrong password, etc.
  3. The user was forwarded or redirected to the login.xhtml page when they tried to access a restricted resource.
For the first scenario, one very important thing to note is that when a user clicks the Login button, the requestURL for that click will not carry the original query string anymore. As a consequence, if you capture the requestURL at this point, it's too late and you will only have http://example.com/yourapp/pageX.xhtml. In other words, to get the full requestURL, you need to capture the requestURL even before the user clicks the Login button. To achieve this goal, in your templates, you need to define the following <f:event>:

This is our  @SessionScoped managed bean:

And this is the Login managed bean:

For the second scenario, users will usually arrive at the login.xhtml page where you display a big & fat error message. At this point, you might have jumped into your own trap if you have also included the above <f:event> inside your login.xhtml page. The event would be triggered and your originalURL property would be wrongly updated to the login page's URL. So, in brief, you must NOT include the above <f:event> inside your login.xhtml page.

Done? No, this is a double-trap :O!  We still need to take care of the situation in which the user didn't surf any pages before logging in.

For the third scenario, you need to understand the difference between a forward and a redirect. When a user is forwarded to the login.xhtml page, the requestURL will still be http://example.com/yourapp/pageX.xhtml?param1=value1 even though the content of the view is from the login.xhtml page. On the other hand, if the user is redirected, the requestURL will become http://example.com/yourapp/login.xhtml.

In case the user was redirected, I will assume that you're using a homegrown Filter to perform the login check and redirect users afterward. In this situation, you need to include the original requestURL as a parameter in the redirecting URL:

After that, you need to update your LoginBean#init() function to retrieve the parameter in both cases as following:

Finally, after spilling much sweat, you can enjoy your work now! :)

Sunday, 31 March 2013

[How To] - Implement Facebook login in JSF using SocialAuth

As a matter of fact, Facebook does not provide an official library for Java developer. To make the matter worse, the provided official Javascript SDK is not very easy to use (at least for me) or to integrate with a JSF application. Luckily, there are several unofficial projects going on at the moment and in my opinon, the best of all should be either RestFB or SocialAuth. Between these two alternatives, I prefer SocialAuth because of 2 reasons. First of all, RestFB doesn't support authentication. In other words, using RestFB, we have to dive into the JavaScript SDK mess to fetch the accessToken from Facebook on our own. Another thing is that SocialAuth supports not only Facebook but also a wide range of other providers such as Google, LinkedIn, etc. So, today, I will use SocialAuth to show you how to implement Facebook login in JSF.

One thing to note is that on SocialAuth's wiki page, there is actually a step-by-step tutorial on connecting to Facebook in a JSF CDI application. I've tried the provided solution but it didn't work out for me. Somehow, I ran into the Unsatisfied dependencies for type [SocialAuth] with qualifiers [@Named] at injection point [[field] error and no one has yet to provide an answer for my question on StackOverflow. So in this post, I will show you another way that I have figured out to connect to Facebook.

In brief, there are 4 steps that you need to follow:
  1. Create an application on Facebook.
  2. Download the latest SocialAuth SDK. In this tutorial, I am using v4.0.
  3. Copy, paste and edit!
  4. Enjoy your achievement :).
Firstly, you need to create an application on Facebook.


From the above page, you need to write down your App ID and App Secret, which would be used to connect to Facebook later. Another thing to note is that the Site URL property needs to be the same as the domain where you deploy your application. So, if you want to test your application locally, simply enter http://localhost:8080/.

After downloading the latest SDK from SocialAuth, which is v4.0 at the moment of this writing, you can proceed to the most interesting part which is coding!

In order to redirect users back to where they have been before logging in, copy and paste this code inside your <f:view>:


After that, copy and paste the following snippet where you want to put your Social login buttons:


One important thing to note is that you should put the login buttons on the top most of your page where no other components can be loaded before these buttons. Otherwise, you may run into java.lang.IllegalStateException when our socialConnect() function attempts to redirect the user if part of the response has been committed. You can also edit the above snippet to add in more buttons for other providers if needed. This is the list of IDs of all providers:


The following is the socialLoginSuccess.xhtml page where users would be redirected to on successful login:


One very important thing to note is that in the above success page, I didn't have the <f:event> component. If your success page uses the same template, which contains the <f:event>, as other pages, you will run into the following exception:


The above exception occurs because the originalURL was wrongly updated to be the authenticationURL. In other words, you will be authenticated one more time.

Finally, this is our @SessionScoped managed bean:


Based on this sample for the oauth_consumer.properties file, you should be able to figure out the properties to put in the props easily. In fact, instead of using Java's Properties, there are also several other ways to load the configuration. The complete list includes:


Enjoy your work! :)

Friday, 29 March 2013

[How To] - Set up SSL certificate on GlassFish app server

Under your development environment, it may not be very important to have a signed Digital certificate. However, eventually, your application will be accessed by the world. Nowadays, all browsers have a mechanism for alerting users when they enter untrusted environment (i.e. websites with unsigned certificates). Most people will either be scared away or think that your site is not working when they see the following warning page:


So, before serving pages securely, you should configure your app server to use a signed certificate. In case you don't have one yet, entering the following lines into a Terminal should do the job:


One very important thing to note is the -alias s1as portion. You cannot randomly assign a string for this parameter. Normally, GlassFish app server uses s1as as the default Certificate Nickname. To check what your app server is actually using, open the Admin console, under Configurations section, choose server-config, then HTTP Service, then Http Listeners. You will see the Certificate Nickname under the SSL tab on the right.


Next, after creating a digital certificate, you should have it cryptographically signed, which would make it became very difficult for anyone else to forge. For sites involved in e-commerce or any other business transaction in which authentication of identity is important, a certificate can be purchased from a well-known certificate authority such as VeriSign or Thawte.

After that, open your Admin console, under Configurations section, choose server-config, then JVM Settings. Under the JVM Options tab on the right, add the following options:


The next task is to copy the keystore.jks and the cacerts.jks files that you have created earlier into the <GLASSFISH_FOLDER>/glassfish/domains/domain1/config folder.

Lastly, restart your GlassFish app server and you're done! :)

Thursday, 28 March 2013

[How To] - Fix javax.mail.NoSuchProviderException: No provider for smtp

At times, you may run into the above Exception even though you're absolutely sure that your sendEmail function is working normally on another project. This Exception happened to me after I updated my project to Use dedicated folder for storing libraries.

The solution in my case was pretty simple.
  1. First, you need to go to Oracle's site to download JavaMail API
  2. After that, add the mail.jar file to your Project's libraries. 
  3. Lastly, right click on your Project, choose Properties, under the Packaging section, you need to check the Package required JARs in EJB jar option.

Hope this helps! :)

[How To] - Change the context root of your EAR project

In your EAR project, normally, you will have a WAR project named yourproject-war, which would also be the context-root of your application if you don't make necessary changes. I have seen many tutorials on the Internet instructing people to update their WAR project's glassfish-web.xml or sun-web.xml file and add the following line:


The above solution will NOT work without deploying the WAR project directly!

What you should do, instead, is to update your EAR project's application.xml file which should be found inside your EAR project's Configuration Files folder in NetBeans.


If the file is not there, simply right-click on your EAR project, choose New and create a Standard Deployment Descriptor.


After opening the application.xml file, the next task is straight-forward.


Good luck! :)

Wednesday, 27 March 2013

[How To] - Handle Unicode contents obtained using PrimeFaces

At times, when you try to persist Unicode contents (e.g. Chinese characters), that are obtained using PrimeFaces's components, to the database and read back, you will see tons of question marks on your browser. For a detailed discussion on the root cause of this problem, please refer to the following answer of BalusC on StackOverflow.

To fix this issue, you need to make the following changes:
  • Add these 2 properties to your JDBC connection.
  • Re-configure the server to use UTF-8 instead of ISO-8859-1 as default coding. Using GlassFish, you simply need to add the following line to your project's glassfish-web.xml file:
Note: To have a better understanding of how to properly handle Unicode characters in JSF, please refer to the following article by BalusC: Unicode - How to get the character right?

[How To] - Fix Flash player cover other components

At times, you may run into a situation in which some components of your page get buried under the Flash player as following:


This is a well-known z-index issue caused by the Flash player. In brief, instead of being rendered within the browser, the Flash player is rendered in a new window (a bit like an i-frame) that is put on top of your browser. Because of this weird rendering, the Flash player will always stay on top of other components on your pages.

Luckily, the solution to this problem is pretty simple :). You simply need to set the wmode parameter of the Flash player to opaque.

With JSF and PrimeFaces's p:media component, you can easily achieve the above goal as following:

Tuesday, 26 March 2013

[How To] - Make non-secure cookie default for all kinds of connection

In a JavaEE application, JSESSIONID cookies' cookieSecure property can have one of the following values:

- true: All JSESSIONID cookies created by the container on behalf of the web application will be marked as secure.
- false: All JSESSIONID cookies created by the container on behalf of the web application will be marked as non-secure.
- dynamic (default):  A JSESSIONID cookie created by the container on behalf of the web application will inherit its security setting from the request that initiated the correspoding session: If the session was initiated by an HTTPS request, its JSESSIONID cookie will be marked as secure, and will remain non-secure otherwise.

Since the default value is dynamic, if the 1st page a user goes to is a HTTPS page (e.g. Login page), the cookie given to the user will be marked as secure. As a result, in many cases, subsequent non-secure HTTP pages may not be able to use the obtained cookie and thus, the user would be asked to log in one more time.

To overcome this issue, one way is to override the cookieSecure property's default value and change it to false. You can achieve this goal by updating the glassfish-web.xml file to include the following lines:



Note:
  1. If cookie settings are defined declaratively in the web.xml file, the cookie properties defined here will take precedence.
  2. If cookie settings are defined programmatically using javax.servlet.SessionCookieConfig methods, those cookie settings will take precedence over the cookie properties defined here.

[How To] - Fix "Offending RSA key" error

Occasionally, when you try to SSH to some server, you may run into the following Offending RSA key error:


To fix this issue, you simply need to edit the file ~/.ssh/known_hosts and remove the particular line that caused the error. In the above example, the following line is crucial:


It means that the offending key is in line 10 of the known_hosts file. So just open the file, delete everything on line 10, save the file and you're done :). 

Try the SSH command again! Everything should be working normally now.