Saturday, August 20, 2011

Configure your Jboss AS7 to be accessible from the network

If you want to have the web console as well as your web application accessible from the network, you have to change the default configuration of JBoss.

1) go to standalone/configuration
2) Open the file standalone.xml (or domain.xml)
3) Look for the lines :








4) Change both IP address from 127.0.0.1 to the ip address of your network interface. Note that your complex deployment the server may have 2 ip adresses 1 for business flows and 1 for management flows.
5) Kill JBossAS and restart

The Admin console should be accessible now from your desktop computer at http://:9990/console ;-)

Sunday, August 7, 2011

Spring3 and JSF2 integration using CDI annotations

In this blog i show you how to use @Inject in your JSF managed beans to directly inject the Spring beans instead of instantiating a Spring application context and using the getBean methode from that context and also how Spring will manage your JSF beans ;-)


In order to inject Spring beans into JSF managed beans using @Inject, the following needs to be done:


1)web.xml

 
org.springframework.web.context.ContextLoaderListener


contextConfigLocation

classpath:/applicationContext.xml


org.springframework.web.context.request.RequestContextListener


2) faces-config.xml

 
org.springframework.web.jsf.el.SpringBeanFacesELResolver

3) applicationContext.xml





4) JSF Managed bean

 @ManagedBean(name="blogJSFBean")
@Controller
@ViewScoped
public class MainBean implements Serializable {
private static final long serialVersionUID = -5012655116147710604L;
@Inject
private SpringBean myBlogBean;


To keep it standard i have changed @Managedean to @Named witch is a CDI standard annotation suported by Spring also (as an alternate to @Service and @Controller)

The big problem i have found that the scope view (@ViewScoped) isn't supported by Spring (also Flash scope …) so i have developped the view scope as Spring custom scope following this article: http://cagataycivici.wordpress.com/2010/02/17/port-jsf-2-0s-viewscope-to-spring-3-0/


my bean become:

 @Named("blogJSFBean")
@Scope (value="view")
public class MainBean implements Serializable {
private static final long serialVersionUID = -5012655116147710604L;
@Inject
private SpringBean myBlogBean;


In general the big difference i have found is that Spring and JSF bean from Java EE 6 use a different scoping! Spring do not support standard scope annotation used in JSF and CDI. To get it work i have followed a workaround to import JSF/CDI bean into Spring:

http://matthiaswessendorf.wordpress.com/2010/05/06/using-cdi-scopes-with-spring-3/

Finaly with all this configuration and workarounds, i have been able to inject Spring beans into JSF using @Inject and @Named Java EE standard annotaion and a custom Spring scope to import JSF/CDI scope


Saturday, July 23, 2011

How to use JAAS to authenticate users on an LDAP directory


This article cover all JAAS authentication concept by describing a sample JAVA application "SampleLDAPLogin.java" to authenticate a user on an LDAP directory using JAAS.

So to authenticate your LDAP users using the SampleLDAPLogin application, the following steps are performed:
  1. The application instantiates a LoginContext.
  2. The LoginContext consults a Configuration (described in the sample_jaas_ldap.config login configuration file) to load the LdapLoginModule which is a LoginModule performing LDAP-based authentication.
  3. The application invokes the LoginContext's login method.
  4. The login method invokes the loaded LoginModule (LdapLoginModule) which attempt to authenticate the user against the corresponding user credentials stored in the openLDAP directory. The LdapLoginModule module requires the supplied CallbackHandler (SampleCallbackHandler.java) to support a NameCallback and a PasswordCallback.
  5. The LoginContext returns the authentication status to the application.
  6. If authentication is successful then a new LdapPrincipal is created using the user's distinguished name and a new UserPrincipal is created using the user's username and both are associated with the current Subject.

This example consists of three files: SampleLDAPLogin.java, SampleCallbackHandler.java, sample_jaas_ldap.config

The SampleLDAPLogin Class

public class SampleLDAPLogin {
public static void main(String[] args) {
LoginContext lc = null;
try {
lc = new LoginContext("SampleLDAPConfiguration", new SampleCallbackHandler());
} catch (LoginException le) {
System.err.println("Cannot create LoginContext. " + le.getMessage());
System.exit(-1);
} catch (SecurityException se) {
System.err.println("Cannot create LoginContext. " + se.getMessage());
System.exit(-1);
}
try {
// attempt authentication
lc.login();
System.out.println("Authentication succeeded!");
} catch (LoginException le) {
System.err.println("Authentication failed:\n" + le.getMessage());
}
}
}

The code for authenticating consist of just two steps:
  • Instantiate a LoginContext with two arguments :

    lc = new LoginContext("SampleLDAPConfiguration", new SampleCallbackHandler());
  1. SampleLDAPConfiguration: The name of the entry in the JAAS login configuration file (sample_jaas_ldap.config)
  2. new SampleCallbackHandler(): A CallbackHandler instance
  • Call the LoginContext's login method: lc.login();

The SampleCallbackHandler Class

public class SampleCallbackHandler implements CallbackHandler {
public void handle(Callback[] callbacks)
throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof NameCallback) {
// prompt the user for a username
NameCallback nc = (NameCallback)callbacks[i];
System.err.print(nc.getPrompt());
System.err.flush();
nc.setName((new BufferedReader
(new InputStreamReader(System.in))).readLine());
} else if (callbacks[i] instanceof PasswordCallback) {
// prompt the user for sensitive information
PasswordCallback pc = (PasswordCallback)callbacks[i];
System.err.print(pc.getPrompt());
System.err.flush();
pc.setPassword(readPassword(System.in));
} else {
throw new UnsupportedCallbackException
(callbacks[i], "Unrecognized Callback");
}
}
}
// Reads user password from given input stream.
private char[] readPassword(InputStream in) throws IOException {
char[] lineBuffer;
char[] buf;
int i;
buf = lineBuffer = new char[128];
int room = buf.length;
int offset = 0;
int c;
loop: while (true) {
switch (c = in.read()) {
case -1:
case '\n':
break loop;
case '\r':
int c2 = in.read();
if ((c2 != '\n') && (c2 != -1)) {
if (!(in instanceof PushbackInputStream)) {
in = new PushbackInputStream(in);
}
((PushbackInputStream)in).unread(c2);
} else
break loop;
default:
if (--room < 0) {
buf = new char[offset + 128];
room = buf.length - offset - 1;
System.arraycopy(lineBuffer, 0, buf, 0, offset);
Arrays.fill(lineBuffer, ' ');
lineBuffer = buf;
}
buf[offset++] = (char) c;
break;
}
}
if (offset == 0) {
return null;
}
char[] ret = new char[offset];
System.arraycopy(buf, 0, ret, 0, offset);
Arrays.fill(buf, ' ');
return ret;
}
}

In some cases a LoginModule (in our case:LdapLoginModule) must communicate with the user to obtain authentication information.

SampleCallbackHandler handles two types of Callbacks: NameCallback to prompt the user for a user name and PasswordCallback to prompt the user for a password.

The sample_jaas_ldap.config (login configuration file)

SampleLDAPConfiguration{

com.sun.security.auth.module.LdapLoginModule REQUIRED

userProvider="ldap://ip_adress:ldap_port/ou=users,

dc=blogDomain,dc=badr,dc=org"

userFilter="uid={USERNAME}"

useSSL=false

debug=true;

};

This entry is named "SampleLDAPConfiguration" and that is the name that our sample application, SampleLDAPLogin, uses to refer to this entry. The entry specifies that the LoginModule to be used to do the user authentication is the "com.sun.security.auth.module.LdapLoginModule" and that this LdapLoginModule is required to "succeed" in order for authentication to be considered successful. The LdapLoginModule succeeds only if the name and password supplied by the user are the one it expects in the DN (Distinguished Name) openLDAP directory "ldap://ip_adress:ldap_port/ou=users,dc=blogDomain,dc=badr,dc=org"

Depending on ther user/password entred You wil get different message in your console from LdapLoginModule using the TextOutputCallback !

Saturday, July 9, 2011

How to read arabic message from ressource bundles with JSF


In this article we assume that you already have an idea about configuring ressource bundles in JSF, how to use it in your pages and also how to configure jsf pages encoding ...

This blog entry is realy independante from JSF version, and it works for both JSF1 and JSF2 ;-)

We suppose that you want to write "Arabic" like "loginBean.username.label = اسم المستخدم " in the message resource bundle (properties) file and you try to save it you will get this error:
"Save couldn't be completed Some characters cannot be mapped using "ISO-85591-1" character encoding. Either change encoding or remove the character ..." because the default mechanism loading of properties files is in "ISO-8559-1-1".

If you change the file encoding to UTF-8, you will be able to save the file but you can not print your messages correctly in JSF !!

To get it work you have to change the default mechanism loading to UTF-8 by implementing a custom ressource bundle class using UTF-8 Control

public class I18nRessourceBundle extends ResourceBundle {

protected static final String BUNDLE_EXTENSION = "properties";
protected static final String CHARSET = "UTF-8";
public static final Control UTF8_CONTROL = new UTF8Control();

public I18nRessourceBundle() {
setParent(ResourceBundle.getBundle("Propety_File_Ressource",
FacesContext.getCurrentInstance().getViewRoot().getLocale(), UTF8_CONTROL));
}

@Override
protected Object handleGetObject(String key) {
return parent.getObject(key);
}

@Override
public Enumeration getKeys() {
return parent.getKeys();
}

public static class UTF8Control extends Control {
public ResourceBundle newBundle
(String baseName, Locale locale, String format, ClassLoader loader, boolean reload)
throws IllegalAccessException, InstantiationException, IOException
{
// The below code is copied from default Control#newBundle() implementation.
// Only the PropertyResourceBundle line is changed to read the file as UTF-8.

String bundleName = toBundleName(baseName, locale);
String resourceName = toResourceName(bundleName, BUNDLE_EXTENSION);
ResourceBundle bundle = null;
InputStream stream = null;
if (reload) {
URL url = loader.getResource(resourceName);
if (url != null) {
URLConnection connection = url.openConnection();
if (connection != null) {
connection.setUseCaches(false);
stream = connection.getInputStream();
}
}
} else {
stream = loader.getResourceAsStream(resourceName);
}
if (stream != null) {
try {
bundle = new PropertyResourceBundle(new InputStreamReader(stream, CHARSET));
} finally {
stream.close();
}
}
return bundle;
}
}
}


We assume that you have a properties file Propety_File_Ressource in your ressource folder

So in JSF configuration you should use:



...


package_name.I18nRessourceBundle
msgBlog

Insted of


...


Propety_File_Ressource
msgBlog




Enjoy it!

Sunday, June 26, 2011

Getting Started with JSF 2 and Primefaces

In this entry we show you how you can start using primefaces with the JSF Mojara reference implementation !

So After setting up your web project with maven and eclipse you just need to import the JSF and Primefaces namespaces into your pages to test the first integration and display some components.

PS:You also need to add primefaces maven dependencies ...

JSF Namespace
JSF namespace is necessary to add JSF tags and components to your pages.

xmlns:f="http://java.sun.com/jsf/core"

xmlns:h="http://java.sun.com/jsf/html"

Primefaces Namespace
PrimeFaces namespace is necessary to add PrimeFaces components to your pages.

xmlns:p="http://primefaces.prime.com.tr/ui"

Test Run

That's it, now you can add a test for JSF and Primefaces component to see if everything is ok.











Congratulation !! executing the application and getting the correct display means JSF and Primefaces are working fine in your web application ...

If you want to deepen your JSF integration test, you can add a JSF managed bean and call it from your page !

Create a managed bean

Briefly a managed bean is a regular Java bean (simple pojo) with a fancy name. When we register the bean with JSF it becomes a managed bean, in other words, it’s now managed by the framework (JSF). For further information see learning-jsf2-managed-beans and whats-new-in-jsf-2

Now, let's create HelloMyBlog our own managed bean !

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

@ManagedBean(name = "helloMyBlog")//or just @Named only from CDI
@RequestScoped
public class HelloMyBlog {
private String webFramework;

public HelloMyBlog(){
webFramework = "JSF 2 and Primefaces";
}

public String getWebFramework() {
return webFramework;
}

public void setWebFramework(String webFramework) {
this.webFramework = webFramework;
}
}

After, we create our view helloMyBlog.xhtml witch use the managed bean HelloMyBlog by name "helloMyBlog" ( @ManagedBean(name = "helloMyBlog"), or just @Named from CDI )












Finaly, Run your application ...

Your web browser should now display the same result as our first test !

Conclusion

We covered in this article the basic test and integration for a simple JSF application with Primefaces component libraries.

Befor going ahead with JSF developpement it's highly recomended to understand the life cycle of a JSF application see JSF application lifecycle

In general JSF is great if you have time to learn it before you have to use it as your main venue for a major project ;-)

Saturday, June 25, 2011

Set up JSF 2 web project (Maven+ Eclipse)

In this entry we show you how to configure your project with Maven and eclipse to support JSF capabilities.

Set up web project with Maven

JSF Dependency

  • For Java EE Application

In most "Java EE 6" application servers, it has "build-in support for JSF 2.0", so you only need to download one JSF API for development purpose.


com.sun.faces
jsf-api
2.1.0-b03
provided


  • For simple servlet container like Tomcat

You may need to download the following dependencies:




javax.servlet
jstl
1.2
runtime



javax.servlet
servlet-api
2.5
provided



javax.servlet.jsp
jsp-api
2.1
provided



javax.el
el-api
provided
1.0



com.sun.faces
jsf-api
2.1.0-b03



com.sun.faces
jsf-impl
2.1.0-b03



JSF 2.0 Servlet Configuration

Just like any other standard web frameworks, you are required to configure the JSF stuff in web.xml file as bellow




Set up web project


index.jsp



Faces Servlet
javax.faces.webapp.FacesServlet
1



Faces Servlet
/faces/*



javax.faces.DEFAULT_SUFFIX
.xhtml



javax.faces.PROJECT_STAGE
Development



Explanation for web.xml content
  1. Define the version 2.5 for your web module "web-app_2_5", it's so important to do that befor executing your first Maven install to keep your project compliant with Dynamic Web Module 2.5 (servlet specification 2.5) and thereafter add the JSF capabilities to your eclipse project (as shown in the next chapter)

  2. Add the JSF servlet in the web.xml, define a “javax.faces.webapp.FacesServlet” mapping to "/faces/*" ( you can also add the extension (*.jsf, *.xhtml,*.faces) to your mapping.

  3. Define a default mapping "javax.faces.DEFAULT_SUFFIX" with .xhtml file extension (not mandatory)

  4. In JSF 2.0 development, it’s recommended (not mandatory) to set the “javax.faces.PROJECT_STAGE” to “Development“, it will provide many useful debugging information to let you track the bugs easily (for deployment, just change it to “Production“)

Set up web project in eclipse

After importing your maven web project into eclipse, everything looks fine except the code assist doesn't work! ie : when you presse on the “Ctrl + Space” combination keys it prompts nothing?

To resolve that: in Eclipse project, you have to make sure the project is supported the WTP and JSF capabilities. so Right click on the project, choose properties, select “Project Facets“, make sure the “JavaServer Faces” is checked.
This allow you also to open your page with "web page editor" and drag and drop JSF component ...