Google is going to offer Sun's Star Office for free as a part of Google Pack. Also, Sun will now be traded under the Symbol JAVA replacing the old symbol SUNW.
Thursday, August 23, 2007
Monday, August 20, 2007
Handling Security with Ajax, DWR and Acegi
This is an extension of a previous post that described how to secure your method calls using Acegi security. Here, I will go through how to secure your Asynchronous calls, using the same example with some modifications to include Ajax calls using Direct Web Remoting (DWR).
- Create the example project as shown in "Spring security with Acegi Security Framework". This will be the starting point.
- Create the SecureDAO object.
package test;
public class SecureDAO {
public String create() {
System.out.println("Create");
return "create";
}
public String read() {
System.out.println("read");
return "read";
}
public String update() {
System.out.println("update");
return "update";
}
} - Update the applicationContext.xml file to include the security definitions by adding the following bean definitions as shown below
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
</value>
</property>
</bean>
<bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"/>
<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
<constructor-arg value="/index.jsp"/>
<constructor-arg>
<list>
<ref bean="rememberMeServices"/>
<bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
</bean>
<bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationFailureUrl" value="/login.jsp?errorId=1"/>
<property name="defaultTargetUrl" value="/"/>
<property name="filterProcessesUrl" value="/j_acegi_security_check"/>
<property name="rememberMeServices" ref="rememberMeServices"/>
</bean>
<bean id="securityContextHolderAwareRequestFilter" class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter"/>
<bean id="rememberMeProcessingFilter" class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="rememberMeServices" ref="rememberMeServices"/>
</bean>
<bean id="anonymousProcessingFilter" class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
<property name="key" value="changeThis"/>
<property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS"/>
</bean>
<bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
<property name="authenticationEntryPoint">
<bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl" value="/login.jsp"/>
<property name="forceHttps" value="false"/>
</bean>
</property>
<property name="accessDeniedHandler">
<bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
<property name="errorPage" value="/denied.jsp"/>
</bean>
</property>
</bean>
<bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager">
<bean class="org.acegisecurity.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false"/>
<property name="decisionVoters">
<list>
<bean class="org.acegisecurity.vote.RoleVoter"/>
<bean class="org.acegisecurity.vote.AuthenticatedVoter"/>
</list>
</property>
</bean>
</property>
<property name="objectDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/secure/admin/**=ROLE_ADMIN
/secure/**=IS_AUTHENTICATED_REMEMBERED
/**=IS_AUTHENTICATED_ANONYMOUSLY
</value>
</property>
</bean>
<bean id="rememberMeServices" class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="userDetailsService"/>
<property name="tokenValiditySeconds" value="1800"></property>
<property name="key" value="changeThis"/>
</bean>
<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
<ref local="daoAuthenticationProvider"/>
<bean class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
<property name="key" value="changeThis"/>
</bean>
<bean class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
<property name="key" value="changeThis"/>
</bean>
</list>
</property>
</bean>
<bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="userDetailsService"/>
<property name="userCache">
<bean class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
<property name="cache">
<bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager">
<bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>
</property>
<property name="cacheName" value="userCache"/>
</bean>
</property>
</bean>
</property>
</bean>
<bean id="userDetailsService" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
<property name="userProperties">
<bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="/WEB-INF/users.properties"/>
</bean>
</property>
</bean>
<bean id="loggerListener" class="org.acegisecurity.event.authentication.LoggerListener"/>
<bean id="methodSecurityInterceptor" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
<property name="authenticationManager">
<ref bean="authenticationManager" />
</property>
<property name="accessDecisionManager">
<bean class="org.acegisecurity.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false" />
<property name="decisionVoters">
<list>
<bean class="org.acegisecurity.vote.RoleVoter" />
<bean class="org.acegisecurity.vote.AuthenticatedVoter" />
</list>
</property>
</bean>
</property>
<property name="objectDefinitionSource">
<value>
test.SecureDAO.*=IS_AUTHENTICATED_REMEMBERED
test.SecureDAO.u=ROLE_ADMIN
</value>
</property>
</bean>
<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="interceptorNames">
<list>
<value>methodSecurityInterceptor</value>
</list>
</property>
<property name="beanNames">
<list>
<value>secureDAO</value>
</list>
</property>
</bean>
<bean id="secureDAO" class="test.SecureDAO" />
</beans> - Update the Web deployment descriptor to forward DWR requests to the DWR Servlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>DWRSpring</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<display-name>SpringListener</display-name>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
<init-param>
<param-name>targetClass</param-name>
<param-value>org.acegisecurity.util.FilterChainProxy</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app> - In the DWR configuration file, set the creator to Spring
<!DOCTYPE dwr PUBLIC
Note:
"-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"
"http://www.getahead.ltd.uk/dwr/dwr10.dtd">
<dwr>
<allow>
<convert match="java.lang.Exception" converter="exception"/>
<create creator="spring" javascript="secureDAO">
<param name="beanName" value="secureDAO"/>
</create>
</allow>
</dwr>- The converter is used to convert the Java exception to Javascript exception.
- The main change will be made to the secure/authenticatedusers.jsp file. This will use DWR to make Ajax requests. Here is the code for the file
<%@ page import="org.acegisecurity.context.SecurityContextHolder"%>
Note:
<html>
<head>
<script type='text/javascript' src='/DWRSpring/dwr/interface/secureDAO.js'></script>
<script type="text/javascript" src="../dwr/engine.js"> </script>
<script type="text/javascript" src="../dwr/util.js"> </script>
<script>
dwr.engine.setErrorHandler(errorHandlerFn);
function update() {
var name = dwr.util.getValue("method");
switch(name) {
case "create":
secureDAO.create(callBackFn)
break;
case "read":
secureDAO.read(callBackFn);
break;
case "update":
secureDAO.update(callBackFn);
break;
}
}
function callBackFn(str) {
dwr.util.setValue("selectedAction","Server Returned : " + str);
}
function errorHandlerFn(message, exception) {
dwr.util.setValue("selectedAction", "Error : " + message);
}
</script>
</head>
<body>
<h1>Welcome: <%=SecurityContextHolder.getContext().getAuthentication().getName()%></h1>
<p><a href="../">Home</a>
<form name="testForm" action=""><select name="method" onchange="update()">
<option value=""></option>
<option value="create">create</option>
<option value="read">read</option>
<option value="update">update</option>
</select></form>
<div id="selectedAction"></div>
<p><a href="../j_acegi_logout">Logout</a></p>
</body>
</html>- The classes that are exposed through DWR will be available through the /WEB_APP_NAME/dwr/interface/JAVASCRIPT_NAME.js files.
<script type='text/javascript' src='/DWRSpring/dwr/interface/secureDAO.js'></script>
- The setErrorhandler call sets the global error handling function.
dwr.engine.setErrorHandler(errorHandlerFn);
Alternatively, the error handling function can be set for individual method calls (as described in DWR documentationaRemote.method(params, {
callback:function(data) { ... },
errorHandler:function(errorString, exception) { ... }
}); - util.js file contains utility functions for getting and setting values for the document elements.
- The classes that are exposed through DWR will be available through the /WEB_APP_NAME/dwr/interface/JAVASCRIPT_NAME.js files.
- Make sure you have the following Jar files in your classpath:
- acegi-security-1.0.3.jar
- ant-junit.jar
- cglib-nodep-2.1_3.jar
- commons-codec-1.3.jar
- commons-logging.jar
- dwr.jar
- ehcache-1.2.3.jar
- jstl.jar
- spring.jar
- standard.jar
Wednesday, May 09, 2007
OpenJDK and JavaFX
Java is now completely open source. The JDK source code is now available through the OpenJDK project. According to the marketing manager of the OpenJDK project Rich Sands, Developers can,
On a related note, Sun has announced the new JavaFX product family. Following Adobe's Flex, and Microsoft's Silverlight, JavaFX script is another product for building rich internet applicaitons. JavaFX Mobile is a complete mobile operating and application environment built around Java and Linux. JavaFX Mobile includes support for Java ME applications and other standard Java APIs.
... learn how the JDK is put together, fix that bug that's beenIt's good to see that the governing body consists of not just Sun employees.
driving you nuts, join the conversations in the mailing lists,
start or participate in projects to improve the implementation.
On a related note, Sun has announced the new JavaFX product family. Following Adobe's Flex, and Microsoft's Silverlight, JavaFX script is another product for building rich internet applicaitons. JavaFX Mobile is a complete mobile operating and application environment built around Java and Linux. JavaFX Mobile includes support for Java ME applications and other standard Java APIs.
Monday, May 07, 2007
Securing EJB 3.0 Beans
The Java EE 5 Security services are provided by the container and can be implemented using declarative or programmatic techniques. In addition to declarative and programmatic ways to implement security (in J2EE), Java EE 5 supports the use of metadata annotations for security. This post will describe how to secure EJB 3.0 beans. The post consists of a simple EJB, with a web client. In order to run the example, follow these steps.
Create Users in Glassfish
The EJB Component
The Web Client
For a little bit more detail explanation on the Web Application, see the previous post Securing Java EE 5 Web Applications
Create Users in Glassfish
- Go to Configuration->Security->Realms->file in the Glassfish admin console.
- In the file realm, click on manage users.
- Add new users by clicking on add there.
The EJB Component
- Start with a Simple Java project in Eclipse.
- Remote Interface
package ejb;
import javax.ejb.Remote;
@Remote
public interface DABean {
public String create();
public String read();
public String update();
public String delete();
}ejb/DABean.java - The Bean:
package ejb;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
import javax.ejb.Stateless;
@Stateless (mappedName = "ejb/secureEJB")
@DeclareRoles({"emp","guest"})
public class SecureEJB implements DABean {
@RolesAllowed({"emp","guest"})
public String create() {
return "create";
}
@RolesAllowed({"emp","guest"})
public String read() {
return "read";
}
@RolesAllowed("emp")
public String update() {
return "update";
}
@RolesAllowed("emp")
public String delete() {
return "delete";
}
}ejb/SecureEJB.java - The declaredRoles and RolesAllowed annotations take a string array as a parameter.
- Deployment descriptor:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 EJB 3.0//EN" "http://www.sun.com/software/appserver/dtds/sun-ejb-jar_3_0-0.dtd">
<sun-ejb-jar>
<security-role-mapping>
<role-name>guest</role-name>
<group-name>guest</group-name>
</security-role-mapping>
<security-role-mapping>
<role-name>emp</role-name>
<group-name>employee</group-name>
</security-role-mapping>
<enterprise-beans>
<unique-id>0</unique-id>
<ejb>
<ejb-name>SecureEJB</ejb-name>
<jndi-name>ejb/secureEJB</jndi-name>
<gen-classes />
</ejb>
</enterprise-beans>
</sun-ejb-jar>META-INF/sun-ejb-jar.xml
The Web Client
For a little bit more detail explanation on the Web Application, see the previous post Securing Java EE 5 Web Applications
- The EJB Client Jar file: When you deploy the EJB application in Glassfish, it creates a corresponding EJB Client jar file for the EJB component, which can be used in the clients. The file will created in the following directory.
GLASSFISH_HOME\domains\DOMAIN_NAME/generated\xml/j2ee-modules/APPLICATION_NAME
- Selection page
<html>
<body>
<h1>Home Page</h1>
Anyone can view this page.
<form action="securityServlet"><select name="method">
<option value="create">create</option>
<option value="read">read</option>
<option value="update">update</option>
<option value="delete">delete</option>
</select> <input type="submit" name="submit" /></form>
</body>
</html>index.jsp - Servlet
package servlets;
import java.io.IOException;
import java.io.PrintWriter;
import javax.annotation.security.DeclareRoles;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import ejb.DABean;
@DeclareRoles("emp")
public class SecurityServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
@EJB(name = "timerBean", mappedName = "corbaname:iiop:localhost:3700#ejb/secureEJB")
private DABean daBean;
public SecurityServlet() {
super();
}
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
String method = request.getParameter("method");
try {
String result = "";
if (method.equals("create")) {
result = daBean.create();
}
if (method.equals("read")) {
result = daBean.read();
}
if (method.equals("update")) {
result = daBean.update();
}
if (method.equals("delete")) {
result = daBean.delete();
}
out.println(request.getUserPrincipal() + " is an Authorized User");
} catch (Exception e) {
e.printStackTrace();
out.println(request.getUserPrincipal() + " is not an Authorized to see this page.");
}
}
}SecurityServlet.java - Deployment descriptor
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>Java5Security</display-name>
<servlet>
<description></description>
<display-name>SecurityServlet</display-name>
<servlet-name>SecurityServlet</servlet-name>
<servlet-class>servlets.SecurityServlet</servlet-class>
<security-role-ref>
<role-name>emp</role-name>
<role-link>emp</role-link>
</security-role-ref>
</servlet>
<servlet-mapping>
<servlet-name>SecurityServlet</servlet-name>
<url-pattern>/securityServlet</url-pattern>
</servlet-mapping>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>file</realm-name>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/error.jsp</form-error-page>
</form-login-config>
</login-config>
<security-constraint>
<web-resource-collection>
<web-resource-name>Protected Area</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>PUT</http-method>
<http-method>DELETE</http-method>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>guest</role-name>
<role-name>emp</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Protected Area</web-resource-name>
<url-pattern>/secure/*</url-pattern>
<http-method>PUT</http-method>
<http-method>DELETE</http-method>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>emp</role-name>
</auth-constraint>
</security-constraint>
<!-- Security roles referenced by this web application -->
<security-role>
<role-name>guest</role-name>
</security-role>
<security-role>
<role-name>emp</role-name>
</security-role>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>web.xml - Glassfish Deployment descriptor
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 8.1 Servlet 2.4//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_2_4-1.dtd">
<sun-web-app>
<context-root>/Java5Security</context-root>
<security-role-mapping>
<role-name>guest</role-name>
<group-name>guest</group-name>
</security-role-mapping>
<security-role-mapping>
<role-name>emp</role-name>
<group-name>employee</group-name>
</security-role-mapping>
</sun-web-app>sun-web.xml
Tuesday, May 01, 2007
Java EE 5 on WebSphere
While the next version of WAS (v7.0) with Java EE 5, is yet to be released, you can now test some of the features such as EJB 3.0 with WebSphere software early programs. The new features are available as feature packs for the current WebSphere Application Server (v6.1).
Friday, April 13, 2007
Customize Acegi SecurityContext
This post describes how to modify the User details stored in the Acegi Security Context.
Acegi Security uses the SecurityContextHolder object to store details of the current security context of the application. The SecurityContext holds the details of the authenticated principal in an Authentication object. By default the SecurityContextHolder uses a ThreadLocal to store these details, so that they will be available all methods in the current thread of execution.In order to obtain the Principal, you would use the following line
Acegi Security uses the SecurityContextHolder object to store details of the current security context of the application. The SecurityContext holds the details of the authenticated principal in an Authentication object. By default the SecurityContextHolder uses a ThreadLocal to store these details, so that they will be available all methods in the current thread of execution.In order to obtain the Principal, you would use the following line
Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal();Usually, the principal is an object of the type UserDetails. The UserDetails object is sort of an adapter between the security database and Acegi SecurityContextHolder. Acegi uses a UserDetailsSevice to build the UserDetails object. In order to modify the data stored Security Context of Acegi, you either have to
- setContext() method of the SecurityContextHolder. The SecurityContext object can be set to hold an Authentication object. This will mean that you have to add some additional security code to your application code.
- Implement the UserDetailsService and UserDetails interfaces. This way you can keep security code seperated from the application code.
- Start with the implementing acegi security posts part 1 and part 2.
- Create the UserDetailsService:
package authentication;
import java.util.HashMap;
import java.util.Map;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.userdetails.UserDetails;
import org.acegisecurity.userdetails.UserDetailsService;
import org.acegisecurity.userdetails.UsernameNotFoundException;
import org.springframework.dao.DataAccessException;
public class MyUserDetailsService implements UserDetailsService {
private Map users = init();
private Map init() {
Map tUsers = new HashMap();
tUsers.put("scott", new User("scott", "tiger", "ROLE_USER"));
tUsers.put("harry", new User("harry", "potter", "ROLE_ADMIN"));
tUsers.put("frodo", new User("frodo", "baggins", "ROLE_USER"));
return tUsers;
}
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException, DataAccessException {
User user = (User) users.get(s);
GrantedAuthority authority = new MyGrantedAuthority(user.getRole());
UserDetails userDetails = new MyUserDetails(new GrantedAuthority[] { authority }, user.getUserId(), user.getPassword(), "Additional Data");
return userDetails;
}
}MyUserDetailsService.java
Notice that all the user data is defined in this class. The UserDetailsService has to return a UserDetails object using the User name. - Create the UserDetails class:
package authentication;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.userdetails.UserDetails;
public class MyUserDetails implements UserDetails {
private GrantedAuthority[] authorities = null;
private String password = null;
private String username = null;
private String additionalData = null;
public MyUserDetails(GrantedAuthority[] authorities, String password, String username, String additionalData) {
super();
this.authorities = authorities;
this.password = password;
this.username = username;
this.additionalData = additionalData;
}
public GrantedAuthority[] getAuthorities() {
return authorities;
}
public String getPassword() {
return password;
}
public String getUsername() {
return username;
}
public boolean isAccountNonExpired() {
return true;
}
public boolean isAccountNonLocked() {
return true;
}
public boolean isCredentialsNonExpired() {
return true;
}
public boolean isEnabled() {
return true;
}
}MyUserDetails.java - The User class:
package authentication;
public class User {
private String userId;
private String password;
private String role;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public User(String userId, String password, String role) {
super();
this.userId = userId;
this.password = password;
this.role = role;
}
}User.java - Modify the applicationContext.xml file: Modify the userDetailsService bean in the application context to as shown below
<bean id="userDetailsService" class="authentication.MyUserDetailsService">
</bean> - The GrantedAuthority class: The MyGrantedAuthority class is typically used to store application roles.
package authentication;
import org.acegisecurity.GrantedAuthority;
public class MyGrantedAuthority implements GrantedAuthority {
private String authority = null;
public MyGrantedAuthority(String authority) {
this.authority = authority;
}
public String getAuthority() {
return authority;
}
}MyGrantedAuthority.java
Tuesday, April 10, 2007
Native Queries with Hibernate Annotations
Hibernate EntityManager implements the programming interfaces and lifecycle rules as defined by the EJB3 persistence specification. Together with Hibernate Annotations, this wrapper implements a complete (and standalone) EJB3 persistence solution on top of the mature Hibernate core. In this post I will describe how map native queries (plain SQL) using Hibernate Annotations. Hibernate Annotations supports the use of Native queries through the @NamedNativeQuery and the @SqlResultSetMapping annotations.
- @NamedNativeQuery: Specifies a native SQL named query.
- @SqlResultSetMapping: Used to specify the mapping of the result of a native SQL query.
- The Hibernate Configuration File: Nothing new here. Except that there are no mappings defined. I used programmatic declaration of mapping for this example as shown in the following steps.
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="connection.url">jdbc:oracle:thin:@localhost:1521/orcl</property>
<property name="connection.username">scott</property>
<property name="connection.password">tiger</property>
<property name="dialect">org.hibernate.dialect.Oracle9Dialect</property>
<property name="hibernate.current_session_context_class">thread</property>
</session-factory>
</hibernate-configuration>hibernate.cfg.xml - The Entity class:
package data;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityResult;
import javax.persistence.FieldResult;
import javax.persistence.Id;
import javax.persistence.NamedNativeQuery;
import javax.persistence.SqlResultSetMapping;
@Entity
@SqlResultSetMapping(name = "implicit", entities = @EntityResult(entityClass = data.Employee.class))
@NamedNativeQuery(name = "implicitSample", query = "select e.empno empNumber, e.ename empName, e.job empJob, e.sal empSalary, salg.grade empGrade from emp e, salgrade salg where e.sal between salg.losal and salg.HISAL", resultSetMapping = "implicit")
//@SqlResultSetMapping(name = "explicit", entities = { @EntityResult(entityClass = data.Employee.class, fields = {
// @FieldResult(name = "empNumber", column = "empno"),
// @FieldResult(name = "empName", column = "ename"),
// @FieldResult(name = "empJob", column = "job"),
// @FieldResult(name = "empSalary", column = "sal"),
// @FieldResult(name = "empGrade", column = "grade") }) })
//@NamedNativeQuery(name = "implicitSample",
// query = "select e.empno empno, e.ename ename, e.job job, e.sal sal, salg.grade grade from emp e, salgrade salg where e.sal between salg.losal and salg.HISAL", resultSetMapping = "explicit")
public class Employee {
private String empNumber;
private String empName;
private String empJob;
private Double empSalary;
private int empGrade;
@Column
@Id
public int getEmpGrade() {
return empGrade;
}
public void setEmpGrade(int empGrade) {
this.empGrade = empGrade;
}
@Column
public String getEmpJob() {
return empJob;
}
public void setEmpJob(String empJob) {
this.empJob = empJob;
}
@Column
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
@Column
public String getEmpNumber() {
return empNumber;
}
public void setEmpNumber(String empNumber) {
this.empNumber = empNumber;
}
@Column
public Double getEmpSalary() {
return empSalary;
}
public void setEmpSalary(Double empSalary) {
this.empSalary = empSalary;
}
}Employee.java - The implitic mapping (the uncommented @NamedNativeQuery and @SqlResultSetMapping declarations are used for implicitly mapping the ResultSet to the entity class. Note that the SQL column names match the field names in the class. If the names do not match then you can set the name attribute of the @Column annotation to the column name in the query.
- The commented @NamedNativeQuery and the @SqlResultSetMapping declarations explicitly map the fields to the columns. This will come in handy when using joins and composite keys etc.
- Note the package definitions refer to javax.persistence and not the hibernate packages. If the packages are not declared properly, you will most likely end up with some exceptions like the following
org.hibernate.hql.ast.QuerySyntaxException: Employee is not mapped.
While there are other causes for this exception, the package declarations did cause a little trouble for me.
- The Client:
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import data.Employee;
public class Client {
public static void main(String[] args) {
Configuration config = new AnnotationConfiguration().addAnnotatedClass(Employee.class).configure();
SessionFactory sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.getCurrentSession();
List result = null;
try {
session.beginTransaction();
result = session.getNamedQuery("implicitSample").list();
System.out.println("Result size : " + result.size());
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(result.size());
}
}Client.java - Jar Files: The following jar files need to be included in the classpath
hibernate3.jar
All the Jar files will be available in the hibernate download. The hibernate-annotations.jar file is available in the hibernate annotations download.
commons-collections-2.1.1.jar
antlr-2.7.6.jar
commons-logging-1.0.4.jar
hibernate-annotations.jar
ejb3-persistence.jar
hibernate-commons-annotations.jar
dom4j-1.6.1.jar
ojdbc14.jar
jta.jar
log4j-1.2.11.jar
xerces-2.6.2.jar
xml-apis.jar
cglib-2.1.3.jar
asm.jar
Subscribe to:
Posts (Atom)
Popular Posts
-
This post will describe how to create and deploy a Java Web Application war to Heroku using Heroku CLI. You will need a basic understanding ...
-
In a previous post, I described how to use Quartz scheduler for scheduling . In this post, I describe the configuration changes required for...
-
The previous post described how to implement a JMS messaging client using Spring JMS . This post will describe how to implement the Message ...
-
JUnit 4 introduces a completely different API to the older versions. JUnit 4 uses Java 5 annotations to describe tests instead of using in...
-
Last week, I described how to implement JMS, using a stand-alone client and a Message Driven Bean . In this post and the next, I will descr...
-
In this post we will see how to do an offline install Jenkins and required plugins on a Red Hat Enterprise Linux Server release 7.3. This is...
-
New posts with iText 5.5.12 Following are two new posts for PDF Merge with iText 5.5.12 Merge PDF files using iText 5 Merge and Paginate PDF...
-
In the previous post, I described the use of Displaytag to implement paging in a simple JSP. In this example, I describe the use of Displayt...
-
Displaytag is an opensource tag library that can be used to display tables on JSPs. Apart from being able to display tables, the displaytag...
-
In the past, I had a few posts on how to implement pagination using displaytag( 1 , 2 ). That solution is feasible only with small result se...