Featured FREE Whitepapers

What's New Here?


Spring Custom Namespaces

Spring Custom Namespaces provides a good way to simplify the xml files used to describe the bean definitions of a Spring Application Context. It is a fairly old concept, first introduced with Spring 2.0, but deserves being reviewed once in a while. Consider a case of having to configure a part of the beans for a Spring MVC application without custom namespaces – this would typically look like this: <bean name="handlerAdapter" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="webBindingInitializer"> <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer"> <property name="conversionService" ref="conversionService"></property> <property name="validator"> <bean class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/> </property> </bean> </property> <property name="messageConverters"> <list> <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"></bean> <bean class="org.springframework.http.converter.StringHttpMessageConverter"></bean> <bean class="org.springframework.http.converter.ResourceHttpMessageConverter"></bean> <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"></bean> <bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"></bean> <bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"></bean> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean> </list> </property> </bean><bean name="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"> <property name="useSuffixPatternMatch" value="false"></property> </bean>Here it is configuring two beans – a handlerAdapter to handle the MVC controller flow and a handlerMapping to keep the mapping between request URI’s and the Controller methods to handle the requests. The same configuration becomes very concise with a custom namespace, “http://www.springframework.org/schema/mvc” typically given a namspace prefix of “mvc”: <mvc:annotation-driven conversion-service="conversionService"> </mvc:annotation-driven>This is in essence the advantage of using a Custom namespace – a very concise way to describe the Spring bean definitions So how does a custom namespace work: This section in the Spring Reference document describes it much better than I can – http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/extensible-xml.html#extensible-xml-schema . To summarize it, a custom namespace has 4 parts to it:the schema - which describes the structure of the custom namespace – the tag names, attributes, child tags etc. a NamespaceHandler – which creates the bean definition for the xml elements. However typically a better mechanism suggested by Spring document is to extend NameSpaceHandlerSupport and to register a series of BeanDefinitionParser(s) for the different xml elements supported by the Custom namespace(say annotation-driven, interceptors elements of mvc namespace). BeanDefinitionParser – create the bean definition for the specific element – here is where a line like <mvc:annotation-driven/> will be expanded to the broader bean definitions with actual bean class names. Registering the schema, NamespaceHandler – This is for Spring to find the schema for the custom namespaces and to find the NamespaceHandler that will handle the custom namespace. The registration of the schema is done by a file called META-INF/spring.schemas, this is neat way for Spring to find the schema in the classpath rather than downloading the schema over the web. The NamespaceHandler is further specified using a META-INF/spring.handlers file and contains the NamespaceHandler name that will handle the custom namespace, for eg. from the Spring documentation –http\://www.mycompany.com/schema/myns=org.springframework.samples.xml.MyNamespaceHandlerTying it together  This information of how the Custom namespace works internally can be put to good use to understand some of behavior of a few custom namepsace tags. Consider a tag to load up the properties file: <context:property-placeholder location="classpath*:META-INF/spring/database.properties"/>So to find how a property-placeholder element works internally, first find the spring.handlers file. Since property-placeholder is in the context namespace, the spring.handlers file will be present in the spring-context.jar file and the file indicates that the NamespaceHandler is org.springframework.context.config.ContextNamespaceHandler The ContextNameSpaceHandler registers a BeanDefinition parser called org.springframework.context.config.PropertyPlaceholderBeanDefinitionParser. This BeanDefinitionParser creates a bean definition with a class name of ” PropertyPlaceholderConfigurer” and so essentially we could have replaced: <context:property-placeholder location="classpath*:META-INF/spring/database.properties" local-override="true" properties-ref="localProperties"/>with but losing conciseness in the process – <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath*:META-INF/spring/database.properties"></property> <property name="localOverride" value="true"></property> <property name="properties"> <ref bean="localProperties"/> </property> </bean>This however provides a good way to understand some of the nuances in how Spring handles things underlying a custom namespace. Reference: Spring Custom Namespaces from our JCG partner Biju Kunjummen at the all and sundry blog....

Does Devops have a Culture Problem?

At the Devopsdays conference in Mountain View, Spike Morelli led an Open Space discussion on the importance of culture. He was concerned that when people think and talk about devops they think and talk too much about tools and practices, and not enough about culture and collaboration and communication, not enough about getting people to work closely together and caring about working closely together – and that this is getting worse as more vendors tie themselves to devops.At the Open Space we talked about the problem of defining culture and communicating it and other “soft and squishy” things. What was important and why. What got people excited about devops and how to communicate this and get it out to more people, and how to try to hold onto this in companies that aren’t agile and transparent. Culture isn’t something that you build by talking about itCulture is like quality. You don’t build culture, or quality, by talking about it. You build it by doing things, by acting, by making things happen and making things change, and reinforcing these actions patiently and continually over time.It’s important to talk – but to talk about the right things. To tell good stories, stories about people and organizations making things better and how they did it. What they did that worked, and what they did that didn’t work – how they failed, and what they learned by failing and how they got through it, so that others can learn from them. This transparency and honesty is one of the things that makes the devops community so compelling and so convincing – organizations that compete against each other for customers and talent and funding openly share their operational failures and lessons learned, as well as sharing some of the technology that they used to build their success. You need tools to make Devops workDevops needs good tools to succeed. So does anything that involves working with software. Take Agile development. Agile is about “people over process and tools”. You can’t get agile by putting in an Agile tool of some kind. Developers can, and often prefer to, use informal and low-tech methods, organize their work on a card wall for example. But I don’t know any successful agile development teams that don’t rely on a good continuous integration platform and automated testing tools at least. Without these tools, Agile development wouldn’t scale and Agile teams couldn’t deliver software successfully.The same is even more true for devops. Tools like Puppet and Chef and cfengine, and statsd and Graphite and the different log management toolsets are all a necessary part of devops. Without tools like these devops can’t work. Tools can’t make change, but people can’t change the way that they work without the right tools.  Devops doesn’t have a culture problem – not yetFrom what I can see, devops doesn’t have a culture problem – at least not yet. Everyone who has talked to me about devops (except for maybe a handful of vendors who are just looking for an angle), at this conference or at Velocity or at other conferences or meetups or in forums, all seem to share the same commitment to making operations better, and are all working earnestly and honestly with other people to make this happen.I hear people talking about deployment and configuration and monitoring and metrics and self-service APIs and about automated operations testing frameworks, and about creating catalogs of operations architecture patterns. About tools and practices. But everyone is doing this in a serious and open and transparent and collaborative way. They are living the culture.As Devops ideas catch on and eventually go mainstream – and I think it will happen – devops will change, just like Agile development has changed as it has gone mainstream. Agile in a big, bureaucratic enterprise with thousands of developers is heavier and more formal and not as much fun. But it is still agile. Developers are still able to deliver working software faster. They talk more with each other and with the customer to understand what they are working on and to solve problems and to find new ways to work better and faster. They focus more on getting things done, and less on paper pushing and process. This is a good thing.As bigger companies learn more about devops and adopt it and adapt, it will become something different. As devops is taken up in different industries outside of online web services, with different tolerances for risk different constraints, it will change. And as time goes on and the devops community gets bigger and the people who are involved change and more people find more ways to make more money from devops, devops will become more about training and certification and coaching and consulting and more about commercial tools or about making money from open source tools.Devops will change – not always for the better. That will suck. But at its core I think devops will still be about getting dev and ops together to solve operational problems, about getting feedback and responding to change, about making operations simpler and more transparent. And that’s going to be a good thing.Reference: Does Devops have a Culture Problem? from our JCG partner Jim Bird at the Building Real Software blog....

Couchbase 101 : install, store and query data

Introduction In this post I just want to show how easily is to get started with Couchbase, and also explain how to “query” the data. The basic steps of this tutorial are:Install Couchbase Create Data Query DataI will try to post more articles, if I have time to show how to use Couchbase from your applications (starting with Java). Prerequisites :Could not be simpler : Couchbase 2.0 available here. (Currently in Developer Preview)Couchbase 101 : Insert and Query data Installation I am using Couchbase on Mac OS X, so let me describe the installation in this environment. If you are using other operating system just take a look to the Couchbase documentation. Couchbase installation is very (very!) fast:Download the Mac OS X Zip file. Double-click the downloaded Zip installation file to extract the contents. This will create a single file, the Couchbase.app application. Drag and Drop the Couchbase.app to your chosen installation folder, such as the system Applications folder.Start and Configure Couchbase Server   To start Couchbase Server, just double click on the Couchbase Server. Once the server is started, a new icon is added in the OS X Menu to indicate that the Server is up and running. You can now configure your Couchbase instance, for this you just need to access the Admin Console, available at the following location (change the IP address if needed) or simply by going in the Couchbase menu and click on Open Admin Console entry.Welcome Screen : Click Setup Set the disk and cluster configuration. On my instance I keep the default location for the on disk storage. Just configure the size of the memory usage for your instance, for example 800Mb. So far, we have a single instance, so no need to join a cluster. Choose to generate sample data. This will be interesting to learn more about data and views. Create the default bucket (use for testing only). A bucket is used by Couchbase to store data. It could be compared to a “database” in RDBMS world. Configure update notifications to be alerted when new version of Couchbase is released Configure the server with a final step with the administrator username and password When this is done you are automatically redirected to the Admin Console.This is it! You are ready to use your Couchbase server. Couchbase has many interesting features, especially around scalability and elasticity but for not in this article let’s focus on the basics :Insert some data and query themInsert Data Couchbase has many ways to manipulate data from you favorite programming language using the different client libraries : Java, Python, PHP, Ruby, .Net, C. For now let’s use the Admin Console to create and query data. Couchbase can store any type of data, but when you need to manipulate some data with a structure the best way is to use JSON Documents. So let’s use the console and create documents. To create new documents in your database, click on the “Data Buckets” tab. If you have installed the sample you see 2 buckets: default and gamesim-sample. Let’s create a new documents in the default bucket:Click on Documents button Click on Create Document Since each document must have an id for example 100. Couchbase save the document and add some metadata such as _rev, $flags, expiration Add new attributes to the document that describe an employee : Name, Departement and Salary, then save it. You just need to update the JSON object with values { “_id”: “100″, “name”: “Thomas”, “dept”: “Sales”, “salary”: 5000 }Repeat the operation with some other employees : 200,Jason,Technology,5500 300,Mayla,Technology,7000 400,Nisha,Marketing,9500 500,Randy,Technology,6000 501,Ritu,Accounting,5400 You have now a list of employees in your database. That was easy isn’t? Let’s now query them. Query Data Access document directly from its ID First of all you can quickly access a document using a simple HTTP request using its id. For example to access the Mayla with the id 300 just enter the following URL: this URL you have :8092 is the Couch API REST port used to access data (where 8091 is the port for the Admin console) default is the bucket in which the document is stored 300 is the id of the documentSearch your data with queries So we have seen how you can access one document. But what if my need is :“Give me all the employee of the Technology department”To achieve such query it is necessary to create views. The views are used by Couchbase server to index and search your data. A view is a Map function written in JavaScript, that will generate a key value list that is compliant with logic you put in the Map function. Note that this key,value is now indexed and sorted by key. This is important when you query your data. So let’s create a new view from the Admin Console:Click on the Views tab (be sure you are on the default bucket) Click on the “Create Development View” Enter the Document and View name:Document Name : _design/dev_dept View Name : deptCick Save Click on your View to edit itSince we need to provide the list of employees that are part of a the Technology department, we need to create a view that use the department as key, so the map function looks like : function (doc) { emit(doc.dept, null); }Save the view This function takes the document and create a list that contains the “dept” as key and null as value. The value itself is not that important in our case. A simple rule will be : do not put too much data in the value since at the end Couchbase server creates an index with this map. Will see that Couchbase allows developer to easily get the document information when accessing a view. Click on the “Show Results” button, the result will look like: {"total_rows":6,"rows":[ {"id":"501","key":"Accounting","value":null}, {"id":"400","key":"Marketing","value":null}, {"id":"100","key":"Sales","value":null}, {"id":"200","key":"Technology","value":null}, {"id":"300","key":"Technology","value":null}, {"id":"500","key":"Technology","value":null} ] }As we have seen in earlier it is possible to access the document using a single URL, it is the same for views. You can for example access the view we have just created using the following URL: it is possible to use query parameter to filter the results using the key parameter with the value entered using a JSON String :”Technology”The result of this query is now : {"total_rows":6,"rows":[ {"id":"200","key":"Technology","value":null}, {"id":"300","key":"Technology","value":null}, {"id":"500","key":"Technology","value":null} ] }You have many other parameters you can use when accessing a view to control the size, the time out, …. One of them is quite interesting is include_docs that ask Couchbase to include the full content of the document in the result. So if you call :”Technology”&include_docs=trueThe result is : {"total_rows":6,"rows":[ {"id":"200","key":"Technology","value":null,"doc": {"_id":"200","_rev":"1-1de6e6751608eada0000003200000000","$flags":0,"$expiration":0,"name":"Jason","dept":"Technology","salary":5500}}, {"id":"300","key":"Technology","value":null,"doc":{"_id":"300","_rev":"1-f3e44cee742bfae10000003200000000","$flags":0,"$expiration":0,"name":"Mayla","dept":"Technology","salary":7000}}, {"id":"500","key":"Technology","value":null,"doc": {"_id":"500","_rev":"1-05780359aac8f3790000003200000000","$flags":0,"$expiration":0,"name":"Randy","dept":"Technology","salary":6000}} ] }Let’s now create a little more complicated view to answer the following business requirement: “Give me all the employee with a salary between 5000 and 6000″ So now you know that you need to create a new view with the salary as key let’s with the following Map function: function (doc) { emit(doc.salary, null); }Couchbase is automatically sorting the key when creating/updating the index so, let’s use the startkey and endkey parameter when calling the view. So let’s call the view with from the following URL: result is : {"total_rows":6,"rows":[ {"id":"100","key":5000,"value":null,"doc":{"_id":"100","_rev":"1-0f33580d780014060000002e00000000","$flags":0,"$expiration":0,"name":"Thomas","dept":"Sales","salary":5000}}, {"id":"501","key":5400,"value":null,"doc":{"_id":"501","_rev":"1-b1fe5bc79637720e0000003100000000","$flags":0,"$expiration":0,"name":"Ritu","dept":"Accounting","salary":5400}}, {"id":"200","key":5500,"value":null,"doc":{"_id":"200","_rev":"1-1de6e6751608eada0000003200000000","$flags":0,"$expiration":0,"name":"Jason","dept":"Technology","salary":5500}}, {"id":"500","key":6000,"value":null,"doc":{"_id":"500","_rev":"1-05780359aac8f3790000003200000000","$flags":0,"$expiration":0,"name":"Randy","dept":"Technology","salary":6000}} ] }Conclusion In this short article you have learn how to:Install Couchbase Create data using the Admin Console Query data with viewsWhen I get more time I will write another article that do the same from Java, and other languages. Reference: Couchbase 101 : install, store and query data from our JCG partner Tugdual Grall at the Tug’s Blog blog....

Spring Security Part 1 – Simple Login application with database

What is Spring Security? Spring security is a framework that provides security solution, handling authentication and authorization at both the web request level and the method level. Spring security handle security in two ways. One is secure web request and other one is restrict access at the URL level. Spring security uses servlet filters. In this post I’m going to create a simple web application that handle the login authentication and authorization. Download project : http://www.mediafire.com/?bb9x88uxvkb0uuv or http://dl.dropbox.com/u/7215751/JavaCodeGeeks/SpringSecurityTutorialPart1/spring-security-login-example.rar Before create the project need to execute some queries to mysql to create a new database , tables and add some sample data. create-table.sql CREATE DATABASE IF NOT EXISTS `spring-test`; -- create user CREATE USER 'user'@'localhost' IDENTIFIED BY 'test'; GRANT ALL ON spring-test.* TO 'user'@'localhost'; USE `spring-test`; CREATE TABLE USER_DETAILS ( USERNAME VARCHAR(10) NOT NULL, PASSWORD VARCHAR(32) NOT NULL, PRIMARY KEY (USERNAME) ); CREATE TABLE USER_AUTH ( USERNAME VARCHAR(10) NOT NULL, AUTHORITY VARCHAR(10) NOT NULL, FOREIGN KEY (USERNAME) REFERENCES USER_DETAILS(USERNAME) ); test-data.sql insert into USER_DETAILS values ('user','123'); insert into USER_DETAILS values ('admin','admin'); insert into USER_AUTH values ('user', 'ROLE_USER'); insert into USER_AUTH values ('admin', 'ROLE_ADMIN'); After that I create a web project using maven and add below dependencies to pom.xml <properties> <spring.version>3.0.5.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>1.0.0.GA</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <!-- Spring Security --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-taglibs</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-acl</artifactId> <version>${spring.version}</version> </dependency> <!-- jstl --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!-- MySQL database driver --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.9</version> </dependency> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1</version> </dependency> </dependencies> After that change the web.xml like this <!DOCTYPE web-app PUBLIC '-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN' 'http://java.sun.com/dtd/web-app_2_3.dtd' > <web-app> <display-name>spring-security-login</display-name> <servlet> <servlet-name>login</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>login</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/login-servlet.xml, /WEB-INF/login-security.xml, /WEB-INF/login-service.xml </param-value> </context-param> <!-- Spring Security --> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list> </web-app> Now I need to create login-servlet.xml, login-security.xml and login-service.xml spring configuration files. In this example we are using c3p0 connection pool with Mysql database. Here is the login-servlet.xml file <?xml version='1.0' encoding='UTF-8'?> <beans xmlns='http://www.springframework.org/schema/beans' xmlns:context='http://www.springframework.org/schema/context' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsd'><context:component-scan base-package='rd.controller'/> <bean id='internalResourceResolver' class='org.springframework.web.servlet.view.InternalResourceViewResolver'> <property name='prefix' value='/WEB-INF/views/'/> <property name='suffix' value='.jsp'/> </bean> <bean class='org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping'></bean> <bean class='org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter'/> <bean id='placeholderConfig' class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer'> <property name='locations'> <list> <value>classpath:login.properties</value> </list> </property> </bean> </beans> Here is the login-security.xml <?xml version='1.0' encoding='UTF-8'?> <beans:beans xmlns='http://www.springframework.org/schema/security' xmlns:beans='http://www.springframework.org/schema/beans' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/securityhttp://www.springframework.org/schema/security/spring-security-3.0.xsd'><beans:import resource='login-service.xml'/> <http> <intercept-url pattern='/home*' access='ROLE_USER,ROLE_ADMIN' /> <intercept-url pattern='/admin*' access='ROLE_ADMIN' /> <form-login login-page='/login.jsp' default-target-url='/home' authentication-failure-url='/login.jsp?error=true'/> <logout logout-success-url='/login.jsp' /> <anonymous username='guest' granted-authority='ROLE_GUEST'/> <remember-me/> </http> <authentication-manager> <authentication-provider> <!--<user-service>--> <!--<user name='admin' password='secret' authorities='ROLE_ADMIN,ROLE_USER' />--> <!--<user name='user1' password='1111' authorities='ROLE_USER' />--> <!--</user-service>--> <jdbc-user-service data-source-ref='dataSource' users-by-username-query='select username,password, 'true' as enabled from USER_DETAILS where username=?' authorities-by-username-query='select USER_DETAILS.username , USER_AUTH.AUTHORITY as authorities from USER_DETAILS,USER_AUTH where USER_DETAILS.username = ? AND USER_DETAILS.username=USER_AUTH.USERNAME '/> </authentication-provider> </authentication-manager> </beans:beans> Here is the login-service.xml <beans xmlns='http://www.springframework.org/schema/beans' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd'><bean id='dataSource' class='com.mchange.v2.c3p0.ComboPooledDataSource'> <!--Driver name to connect to the database--> <property name='driverClass'> <value>${login.jdbc.driver}</value> </property> <!--DB URL--> <property name='jdbcUrl'> <value>${login.url}</value> </property> <!--DB User used to connect to the schema--> <property name='user'> <value>${login.username}</value> </property> <!--Password required to access for the above user--> <property name='password'> <value>${login.password}</value> </property> <!-- configuration pool via c3p0--> <property name='acquireIncrement'> <value>${login.c3p0.acquireIncrement}</value> </property> <property name='idleConnectionTestPeriod'> <value>${login.c3p0.idleConnectionTestPeriod}</value> <!-- seconds --> </property> <property name='maxPoolSize'> <value>${login.c3p0.maxPoolSize}</value> </property> <property name='maxStatements'> <value>${login.c3p0.maxStatements}</value> </property> <property name='minPoolSize'> <value>${login.c3p0.minPoolSize}</value> </property> <property name='initialPoolSize'> <value>${login.c3p0.initialPoolSize}</value> </property> <property name='maxIdleTime'> <value>${login.c3p0.maxIdleTime}</value> </property> <property name='acquireRetryAttempts'> <value>${login.c3p0.acquireRetryAttempts}</value> </property> <property name='acquireRetryDelay'> <value>${login.c3p0.acquireRetryDelay}</value> </property> <property name='breakAfterAcquireFailure'> <value>${login.c3p0.breakAfterAcquireFailure}</value> </property> </bean> </beans> The login.jsp page looks like this. (Need to place is under webapp directory. But not in under WEB_INF directory) <%@ taglib prefix='c' uri='http://java.sun.com/jsp/jstl/core' %> <html> <head> <title>Login</title> </head> <body> <c:if test='${not empty param.error}'> <font color='red'> Login error. <br /> Reason : ${sessionScope['SPRING_SECURITY_LAST_EXCEPTION'].message} </font> </c:if> <form method='POST' action='<c:url value='/j_spring_security_check' />'> <table> <tr> <td align='right'>Username</td> <td><input type='text' name='j_username' /></td> </tr> <tr> <td align='right'>Password</td> <td><input type='password' name='j_password' /></td> </tr> <tr> <td colspan='2' align='right'> <input type='submit' value='Login' /> </td> </tr> </table> </form> </body> </html> home.jsp page <%@ taglib prefix='c' uri='http://java.sun.com/jsp/jstl/core' %> <%@ taglib prefix='sec' uri='http://www.springframework.org/security/tags' %> <html> <head> <title>Home</title> </head> <body> <a href=<c:url value='/j_spring_security_logout'/>>Logout</a><br/> <sec:authorize ifAnyGranted='ROLE_ADMIN'> <h1>Only admin can see this</h1><br/> <a href='admin'> Admin Home </a> </sec:authorize> <h1>Welcome</h1> </body> </html> admin-home.jsp page <%@ taglib prefix='c' uri='http://java.sun.com/jsp/jstl/core' %> <%@ page contentType='text/html;charset=UTF-8' language='java' %> <html> <head> <title>Admin</title> </head> <body> <a href=<c:url value='/j_spring_security_logout'/>>Logout</a><br/> <h1>Only Admin allowed here</h1> </body> </html> After that you need to write two controller to retrieve home page and admin-home page. Here is the HomeController.java package rd.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class HomeController { @RequestMapping(value = '/home' , method = RequestMethod.GET) public String setUp(Model model){ return 'home'; } } Here is the AdminController.java package rd.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class AdminController { @RequestMapping(value = '/admin' , method = RequestMethod.GET) public String setUp(Model model){ return 'admin-home'; } } That’s it. Run mvn clean install command to create war file. Copy the war file under tomcat/webapps directory and access the web app in your favorite browser. url : localhost:<port>/spring-login/login.jsp Test case 1 : Try to log with user as username 123 as password. You will get users home page. Test case 2 : Try to log with admin as username admin as password. You will get users home page with visible admin page link. In spring security part 2 I will modify this project and add remember me feature and md5 password encryption feature. In near future Ill try to post some interesting article about spring security with CAS integration and LDAP integration. Stay tuned :) Reference: Spring Security Part 1 – Simple Login application with database from our JCG partner Rajith Delantha at the Looping around with Rajith… blog....

Logback: Application errors notification

Some months ago when I was doing big application refactoring I found really annoying pieces of log4j based code used for logging repeated hundreds of times:                   if (LOG.isDebugEnabled()) { LOG.debug("Logging some stuff = " + stuff); }I wanted to get rid of isXXXEnabled an thats how I found Logback and SLF4J.   Logback and SLF4J Logback in conjunction with SLF4J provides great API and fast and powerful implementation of logging framework. Reasons why to switch to Logback from log4j are not topic of this post and they are already described in details on logback website. Just in short notice what do you get with Logback and SL4FJ:simple and fast way to skip isXXXEnabled with: LOG.debug("Logging some stuff = {}", stuff);automatic reloading of configuration files powerful logging filters loading properties file into configuration xml conditional configurationThanks to SLF4J migration tool migration from log4j api to SLF4J is super fast. I’ve decided to switch all projects to Logback and after several months I have to say that I am really satisfied with that decision. In order to use Logback in your project add following dependencies: <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.6.4</version> </dependency><dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.0.1</version> </dependency><dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.6.4</version> </dependency>Setting up error notifications with Logback In application with proper logging every entry logged with level ERROR should be considered as a problem that should be fixed. Most common way of logging errors is of course logging exceptions with stacktraces to logfile but if you have plenty of applications on several hosts checking for errors can be time consuming. Smarter way is to log them into database – that can be achieved with DBAppender. I found the most helpful to send all exceptions on my email to be able to fix them immediately. In order to setup Logback to send mails with exceptions we need to add Java Mail dependency: <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4</version> </dependency>And define configuration for SMTPAppender in logback.xml: <?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- some application specific configuration here --><appender name="sheriff" class="ch.qos.logback.classic.net.SMTPAppender"> <smtpHost>localhost</SMTPHost> <from>sheriff@mycompany.com</From> <to>john@mycompany.com</To> <subject>Something went wrong</Subject> <layout class="ch.qos.logback.classic.html.HTMLLayout"/><filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>ERROR</level> </filter> </appender><root level="ERROR"> <appender-ref ref="sheriff" /> </root> </configuration>Thanks to ThresholdFilter with level set to ERROR we are sure that even if root level will be changed – only error mails will be sent. Now you should get emails that look similar to:Skipping error notifications in dev environment Probably you will not need to receive those mails coming from development environment and thanks to conditionals in logback configuration you can easily skip them. In order to use conditionals you need to add dependency to Janino: <dependency> <groupId>janino</groupId> <artifactId>janino</artifactId> <version>2.5.10</version> </dependency>Next thing is to know whats your environment. In Logback configuration you can access system properties, logback properties or special variables like HOSTNAME and CONTEXT_NAME and them to determine your environment. In my application I use Spring profiles for that so my ROOT logger configuration is: <root level="ERROR"> <if condition='"${spring.profiles.active}" == "production"'> <appender-ref ref="sheriff" /> </if> </root>Few words for log4j users If you decide to stick to log4j you can use it’s SMTPAppender. Log4j can be used together with SLF4J thanks to log4j-over-slf4j library.   Conclusion Sending mails with Logback is not the only way to notify about errors. Its possible to use Jabber appender or even write appender that would send errors through SMS gateway. Its up to you. What solutions for error notifications do you use in your projects? Reference: Application errors notification with Logback from our JCG partner Maciej Walkowiak at the Software Development Journey blog....

Tomcat Context JUnit @Rule

A first draft of a JUnit @Rule that create the test context. This can be used with the Spring context rule for this post to create a complete Spring context for integration tests. import org.apache.commons.dbcp.BasicDataSource; import org.apache.log4j.Logger; import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.*; import java.lang.reflect.Method; import java.sql.Driver; import java.sql.DriverManager; /** * Creates an context for tests using an Apache Tomcat server.xml. * * https://blogs.oracle.com/randystuph/entry/injecting_jndi_datasources_for_junit * * @author alex.collins */ public class TomcatContextRule implements TestRule { public static final Logger LOGGER = Logger.getLogger(CatalinaContextRule.class); /** * Creates all the sub-contexts for a name. */ public static void createSubContexts(Context ctx, String name) { String subContext = ''; for (String x : name.substring(0, name.lastIndexOf('/')).split('/')) { subContext += x; try { ctx.createSubcontext(subContext); } catch (NamingException e) { // nop } subContext += '/'; } } private final File serverXml; public TomcatContextRule(File serverXml, Object target) { if (serverXml == null || !serverXml.isFile()) {throw new IllegalArgumentException();} if (target == null) {throw new IllegalArgumentException();} this.serverXml = serverXml; } public Statement apply(final Statement statement, Description description) { return new Statement() { @Override public void evaluate() throws Throwable { createInitialContext(); try { statement.evaluate(); } finally { destroyInitialContext(); } } }; } private void createInitialContext() throws Exception { LOGGER.info('creating context'); System.setProperty(Context.INITIAL_CONTEXT_FACTORY, org.apache.naming.java.javaURLContextFactory.class.getName()); System.setProperty(Context.URL_PKG_PREFIXES, 'org.apache.naming'); final InitialContext ic = new InitialContext(); createSubContexts(ic, 'java:/comp/env'); final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); final DocumentBuilder builder = factory.newDocumentBuilder(); final Document document = builder.parse(serverXml); // create Environment { final NodeList envs = document.getElementsByTagName('Environment'); for (int i = 0; i < envs.getLength(); i++) { final Element env = (Element)envs.item(i); // must be Element final String name = 'java:comp/env/' + env.getAttribute('name'); final Object instance = Class.forName(env.getAttribute('type')).getConstructor(String.class) .newInstance(env.getAttribute('value')); LOGGER.info('binding ' + name + ' <' + instance + '>'); createSubContexts(ic, name); ic.bind(name, instance); } } // Resource { final NodeList resources = document.getElementsByTagName('Resource'); for (int i = 0; i < resources.getLength(); i++) { final Element resource = (Element)resources.item(i); // must be Element final String name = 'java:comp/env/' + resource.getAttribute('name'); final Class<?> type = Class.forName(resource.getAttribute('type')); final Object instance; if (type.equals(DataSource.class)) { { @SuppressWarnings('unchecked') // this mus be driver? final Class<? extends Driver> driverClass = (Class<? extends Driver>) Class.forName(resource.getAttribute('driverClassName')); DriverManager.registerDriver(driverClass.newInstance()); } final BasicDataSource dataSource = new BasicDataSource(); // find all the bean attributes and set them use some reflection for (Method method : dataSource.getClass().getMethods()) { if (!method.getName().matches('^set.*')) {continue;} final String x = method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4); if (!resource.hasAttribute(x)) {continue;} Class<?> y = method.getParameterTypes()[0]; // might be primitive if (y.isPrimitive()) { if (y.getName().equals('boolean')) y = Boolean.class; if (y.getName().equals('byte')) y = Byte.class; if (y.getName().equals('char')) y = Character.class; if (y.getName().equals('double')) y = Double.class; if (y.getName().equals('float')) y = Float.class; if (y.getName().equals('int')) y = Integer.class; if (y.getName().equals('long')) y = Long.class; if (y.getName().equals('short')) y = Short.class; if (y.getName().equals('void')) y = Void.class; } method.invoke(dataSource, y.getConstructor(String.class).newInstance(resource.getAttribute(x))); } instance = dataSource; } else { // not supported, yet... throw new AssertionError('type ' + type + ' not supported'); } LOGGER.info('binding ' + name + ' <' + instance + '>'); createSubContexts(ic, name); ic.bind(name, instance); } } } private void destroyInitialContext() { System.clearProperty(Context.INITIAL_CONTEXT_FACTORY); System.clearProperty(Context.URL_PKG_PREFIXES); LOGGER.info('context destroyed'); } } For example: @Rule public TestRule rules = RuleChain.outerRule(new CatalinaContextRule(new File(getClass().getResource('/server.xml').getFile()), this)) .around(new ContextRule(new String[] {'/applicationContext.xml'}, this)); This code is on Github. Reference: Tomcat Context JUnit @Rule from our JCG partner Alex Collins at the Alex Collins ‘s blog blog....

Implementing SAML to XACML

Before Implementing SAMLThis is how a XACML request will looks like when it is arriving at PDP(Policy Decision Point) to be evaluated. <Request xmlns='urn:oasis:names:tc:xacml:2.0:context:schema:os'> <Subject> <Attribute AttributeId='urn:oasis:names:tc:xacml:1.0:subject:subject-id' DataType='http://www.w3.org/2001/XMLSchema#string'> <AttributeValue>admin</AttributeValue> </Attribute> </Subject> <Resource> <Attribute AttributeId='urn:oasis:names:tc:xacml:1.0:resource:resource-id' DataType='http://www.w3.org/2001/XMLSchema#string'> <AttributeValue>http://localhost:8280/services/echo/echoString</AttributeValue> </Attribute> </Resource> <Action> <Attribute AttributeId='urn:oasis:names:tc:xacml:1.0:action:action-id' DataType='http://www.w3.org/2001/XMLSchema#string'><AttributeValue>read</AttributeValue> </Attribute> </Action> <Environment/> </Request> Basically it states who is(Subject) wanting to access which resource and what action it wants to perform on the resource. PDP trusts that request made is not altered while being sent and received, evaluates the request against existing enabled policies and reply with the decision which will be as follows. <Response> <Result ResourceId='http://localhost:8280/services/echo/echoString'> <Decision>Permit</Decision> <Status> <StatusCode Value='urn:oasis:names:tc:xacml:1.0:status:ok'/> </Status> </Result> </Response> Again there is no guarantee for the party who is using this response that this decision is not altered since sent from PDP until been received. In order achieve the security of XACML requests and responses in server to server communication SAML profile for XACML is defined by OASIS.This take the system security to a higher level by allowing the usage of fine-grained authorization provided by XACML, to be signed.After Implementing SAMLFollowing is how the previous XACML request looks like after wrapped into a XACMLAuthzDecisionQueryType, which is generated using OpenSAML 2.0.0 library which is supporting SAML profile of XACML as declared in 2004 . The diagram shows the basic structure of a XACMLAuthzDecisionQueryType.Following is a sample XACMLAuthzDecisionQuery. <xacml-samlp:XACMLAuthzDecisionQueryType InputContextOnly='true' IssueInstant='2011-10-31T06:44:57.766Z' ReturnContext='false' Version='2.0' xmlns:xacml-samlp='urn:oasis:names:tc:xacml:2.0:profile:saml2.0:v2:schema:protocol'> <saml:Issuer SPProvidedID='SPPProvierId' xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion'> https://identity.carbon.wso2.org</saml:Issuer> <ds:Signature xmlns:ds='http://www.w3.org/2000/09/xmldsig#'> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm='http://www.w3.org/2001/10/xml-exc-c14n#'/> <ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/> <ds:Reference URI=''> <ds:Transforms> <ds:Transform Algorithm='http://www.w3.org/2000/09/xmldsig#enveloped-signature'/> <ds:Transform Algorithm='http://www.w3.org/2001/10/xml-exc-c14n#'> <ec:InclusiveNamespaces PrefixList='ds saml xacml-context xacml-samlp' xmlns:ec='http://www.w3.org/2001/10/xml-exc-c14n#'/> </ds:Transform> </ds:Transforms> <ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/> <ds:DigestValue>7T1ScatC2Xg7pSpjB2X9HB3EH8M=</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue>XQBUVH3j16HVm3aTFSFh5EYFyiYjn0IU4PJfXelzK6BfXp GGTBGouVJEe2Kk26sa3Yj0nEgh51pKsNWxk8xQFWdXg6/UlMkq+CaKrYj7laYlM9yGuIlEBT6t yzjIQBa8wskHeITL6tHE+G0aMa5YnTqtb+9IaJKGPIrl/K5Zn2A=</ds:SignatureValue> <ds:KeyInfo> <ds:X509Data> <ds:X509Certificate>MIICNTCCAZ6gAwIBAgIES343gjANBgkqhkiG9w0BA QUFADBVMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZ pZXcxDTALBgNVBAoMBFdTTzIxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xMDAyMTkwNzAyM jZaFw0zNTAyMTMwNzAyMjZaMFUxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1U EBwwNTW91bnRhaW4gVmlldzENMAsGA1UECgwEV1NPMjESMBAGA1UEAwwJbG9jYWxob3N0M IGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCUp/oV1vWc8/TkQSiAvTousMzOM4asB2i ltr2QKozni5aVFu818MpOLZIr8LMnTzWllJvvaA5RAAdpbECb+48FjbBe0hseUdN5Hpwvn H/DW8ZccGvk53I6Orq7hLCv1ZHtuOCokghz/ATrhyPq+QktMfXnRS4HrKGJTzxaCcU7OQI DAQABoxIwEDAOBgNVHQ8BAf8EBAMCBPAwDQYJKoZIhvcNAQEFBQADgYEAW5wPR7cr1LAdq +IrR44iQlRG5ITCZXY9hI0PygLP2rHANh+PYfTmxbuOnykNGyhM6FjFLbW2uZHQTY1jMrP prjOrmyK5sjJRO4d1DeGHT/YnIjs9JogRKv4XHECwLtIVdAbIdWHEtVZJyMSktcyysFcvu hPQK8Qc/E/Wq8uHSCo=</ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </ds:Signature> <xacml-context:Request xmlns:xacml-context='urn:oasis:names:tc:xacml:2.0:context:schema:os'><xacml-context:Subject SubjectCategory='urn:oasis:names:tc:xacml:1.0:subject-category:access-subject' xmlns:xacml-context='urn:oasis:names:tc:xacml:2.0:context:schema:os'><xacml-context:Attribute AttributeId='urn:oasis:names:tc:xacml:1.0:subject:subject-id' DataType='http://www.w3.org/2001/XMLSchema#string'><xacml-context:AttributeValue>admin</xacml-context:AttributeValue></xacml-context:Attribute></xacml-context:Subject><xacml-context:Resource xmlns:xacml-context='urn:oasis:names:tc:xacml:2.0:context:schema:os'><xacml-context:Attribute AttributeId='urn:oasis:names:tc:xacml:1.0:resource:resource-id' DataType='http://www.w3.org/2001/XMLSchema#string'><xacml-context:AttributeValue>http://localhost:8280/services/echo/echoString</xacml-context:AttributeValue></xacml-context:Attribute></xacml-context:Resource><xacml-context:Action xmlns:xacml-context='urn:oasis:names:tc:xacml:2.0:context:schema:os'><xacml-context:Attribute AttributeId='urn:oasis:names:tc:xacml:1.0:action:action-id' DataType='http://www.w3.org/2001/XMLSchema#string'><xacml-context:AttributeValue>read</xacml-context:AttributeValue></xacml-context:Attribute></xacml-context:Action><xacml-context:Environment xmlns:xacml-context='urn:oasis:names:tc:xacml:2.0:context:schema:os'/> </xacml-context:Request> </xacml-samlp:XACMLAuthzDecisionQueryType> As you can see it carries lot of information related to the content of the request like who issued it , when, signature with the X509Certificate and the XACML request. Data integrity can be preserved in this way. After executing the request and gaining the response from PDP, it is also sent secured with a signature. The diagram shows the structure of a basic SAML Response.Following is a sample SAML response that carries XACML response. <samlp:Response IssueInstant='2011-10-31T06:49:51.013Z' Version='2.0' xmlns:samlp='urn:oasis:names:tc:SAML:2.0:protocol'> <saml:Issuer SPProvidedID='SPPProvierId' xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion'>https://identity.carbon.wso2.org</saml:Issuer><ds:Signature xmlns:ds='http://www.w3.org/2000/09/xmldsig#'> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm='http://www.w3.org/2001/10/xml-exc-c14n#'/> <ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/> <ds:Reference URI=''> <ds:Transforms> <ds:Transform Algorithm='http://www.w3.org/2000/09/xmldsig#enveloped-signature'/> <ds:Transform Algorithm='http://www.w3.org/2001/10/xml-exc-c14n#'> <ec:InclusiveNamespaces PrefixList='ds saml samlp xacml-context xacml-saml' xmlns:ec='http://www.w3.org/2001/10/xml-exc-c14n#'/> </ds:Transform> </ds:Transforms> <ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/> <ds:DigestValue>uct4nBcdqAV4FIO50WMmFjSy9sE=</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue>dLaXFl6+HHqtaQoE8l22bCCM8byxblyBOYUTdUdG/LeYIR+ NUTn6nTRe9MJqWqrXT4qLtQ2Jvb3Cjrw66YZTdVrBXNjD1t6oWAg3YFXtZcO4s1+z5y4BeN6Mq spLLKIUnovCADNbHvhhVDwtMkCOcUs0x35R0zENiU1PYVMLQMM=</ds:SignatureValue> <ds:KeyInfo> <ds:X509Data> <ds:X509Certificate> MIICNTCCAZ6gAwIBAgIES343gjANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJVUzELMAkGA1 UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxDTALBgNVBAoMBFdTTzIxEjAQBgNVBAMM CWxvY2FsaG9zdDAeFw0xMDAyMTkwNzAyMjZaFw0zNTAyMTMwNzAyMjZaMFUxCzAJBgNVBAYTAl VTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzENMAsGA1UECgwEV1NPMjES MBAGA1UEAwwJbG9jYWxob3N0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCUp/oV1vWc8/ TkQSiAvTousMzOM4asB2iltr2QKozni5aVFu818MpOLZIr8LMnTzWllJvvaA5RAAdpbECb+48F jbBe0hseUdN5HpwvnH/DW8ZccGvk53I6Orq7hLCv1ZHtuOCokghz/ATrhyPq+QktMfXnRS4HrK GJTzxaCcU7OQIDAQABoxIwEDAOBgNVHQ8BAf8EBAMCBPAwDQYJKoZIhvcNAQEFBQADgYEAW5wP R7cr1LAdq+IrR44iQlRG5ITCZXY9hI0PygLP2rHANh+PYfTmxbuOnykNGyhM6FjFLbW2uZHQTY 1jMrPprjOrmyK5sjJRO4d1DeGHT/YnIjs9JogRKv4XHECwLtIVdAbIdWHEtVZJyMSktcyysFcv uhPQK8Qc/E/Wq8uHSCo= </ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </ds:Signature> <saml:Assertion IssueInstant='2011-10-31T06:49:51.008Z' Version='2.0' xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion'> <saml:Issuer SPProvidedID='SPPProvierId'>https://identity.carbon.wso2.org</saml:Issuer> <saml:Statement xmlns:xacml-saml='urn:oasis:names:tc:xacml:2.0:profile:saml2.0:v2:schema:assertion' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:type='xacml-saml:XACMLAuthzDecisionStatementType'> <xacml-context:Response xmlns:xacml-context='urn:oasis:names:tc:xacml:2.0:context:schema:os'> <xacml-context:Result ResourceId='http://localhost:8280/services/echo/echoString' xmlns:xacml-context='urn:oasis:names:tc:xacml:2.0:context:schema:os'> <xacml-context:Decision>Permit</xacml-context:Decision> <xacml-context:Status><xacml-context:StatusCode Value='urn:oasis:names:tc:xacml:1.0:status:ok'/> </xacml-context:Status> </xacml-context:Result> </xacml-context:Response> </saml:Statement> </saml:Assertion> </samlp:Response> The XACML response is wrapped into a SAML statement which is included in a SAML assertion that is again wrapped by a SAML response.I have only signed the response according to the context and included only one assertion. We can separately sign both the assertion and response according to the spec and include more assertions in one response. Also it is possible to send the relevant XACML request inside the response and lot more options are there according to the spec. With OpenSAML we can get most of them into action. Reference: Implementing SAML to XACML from our JCG partner Pushpalanka at the Pushpalanka’s Blog blog....

REST + Spring Security session problem

REST, sessions .. wait. There are no sessions in REST application, right? Well, thats true. If we can avoid sessions we should do that. REST is stateless. The main concern about statelessness is authentication. In usual web applications we were used to store user data in session after authentication. How to solve that if we don’t want to use sessions? We should authenticate every request. Thanks to that we can scale our application, add new nodes, remove nodes without care about session replication and also about consumed Java heap memory. Recently I’ve been working on high load REST application. Actually we didn’t expect to have high traffic there but surprisingly we had much much higher that we have been prepared for (it’s so called “happy problem”). Application is based on Spring Framework and its secured with Spring Security deployed on Apache Tomcat 7. All resources are totally stateless – HttpSession is not touched by any piece of my code. Unfortunately used Java heap space was increasing all the time until: java.lang.OutOfMemoryError: Java heap space was thrown. In order to analyze Java heap dump and runtime usage of heap I used VisualVM.Heap dump analysis shown that big part of memory was used by ConcurrentHashMaps used by Tomcat to store sessions. Those sessions object were almost empty but there were so many of them that they consumed ~50% of reserved Java heap space.Add parameter to Tomcat startup script: -XX:+HeapDumpOnOutOfMemoryError to get Java heap dump on java.lang.OutOfMemoryError: Java heap space First thing that I’ve done was to limit session timeout from default 30 minutes to 1 minute (lowest possible option) in web.xml: <?xml version='1.0' encoding='UTF-8'?> <web-app xmlns='http://java.sun.com/xml/ns/javaee' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_3_0.xsd'version='3.0'> <!-- ... --><session-config> <session-timeout>1</session-timeout> </session-config> </web-app> That solved the problem – heap was cleaned by GC with better results and OutOfMemoryError was not thrown anymore. But more important thing is where those sessions were coming from? The answer is: Spring Security. By default Spring Security creates sessions if required – which means that if user has authenticated successfully then session is created. In my case it meaan – always. In order to prevent Spring Security from creating sessions create-session='never' needs to be added to http: <http create-session='never'> <!-- ... --> </http> You might think – empty session objects should not be a problem. I can tell you that for application handling few hundreds of requests per second it does a real change. Especially when its not running in the cloud or has few GB or RAM memory dedicated for Java heap. That’s how Java heap usage look like after those modifications:Reference: Solving REST + Spring Security session problem from our JCG partner Maciej Walkowiak at the Software Development Journey blog....

How to analyze Thread Dump – Thread Stack Trace

This article is part 5 of our Thread Dump analysis series. So far you have learned the basic principles of Threads and their interactions with your Java EE container & JVM. You have also learned different Thread Dump formats for HotSpot and IBM Java VM’s. It is now time for you to deep dive into the analysis process. In order for you to quickly identify a problem pattern from a Thread Dump, you first need to understand how to read a Thread Stack Trace and how to get the “story” right. This means that if I ask you to tell me what the Thread #38 is doing; you should be able to precisely answer; including if Thread Stack Trace is showing a healthy (normal) vs. hang condition. Java Stack Trace revisited Most of you are familiar with Java stack traces. This is typical data that we find from server and application log files when a Java Exception is thrown. In this context, a Java stack trace is giving us the code execution path of the Thread that triggered the Java Exception such as a java.lang.NoClassDefFoundError, java.lang.NullPpointerException etc. Such code execution path allows us to see the different layers of code that ultimately lead to the Java Exception. Java stack traces must always be read from bottom-up:The line at the bottom will expose the originator of the request such as a Java / Java EE container Thread.  The first line at the top of the stack trace will show you the Java class where that last Exception got triggered.Let’s go through this process via a simple example. We created a sample Java program simply executing some Class methods calls and throwing an Exception. The program output generated is as per below: JavaStrackTraceSimulator Author: Pierre-Hugues Charbonneauhttp://javaeesupportpatterns.blogspot.comException in thread "main" java.lang.IllegalArgumentException: at org.ph.javaee.training.td.Class2.call(Class2.java:12) at org.ph.javaee.training.td.Class1.call(Class1.java:14) at org.ph.javaee.training.td.JavaSTSimulator.main(JavaSTSimulator.java:20)Java program JavaSTSimulator is invoked (via the “main” Thread)  The simulator then invokes method call() from Class1 Class1 method call() then invokes Class2 method call() Class2 method call() throws a Java Exception: java.lang.IllegalArgumentException  The Java Exception is then displayed in the log / standard outputAs you can see, the code execution path that lead to this Exception is always displayed from bottom-up. The above analysis process should be well known for any Java programmer. What you will see next is that the Thread Dump Thread stack trace analysis process is very similar to above Java stack trace analysis. Thread Dump: Thread Stack Trace analysis Thread Dump generated from the JVM provides you with a code level execution snapshot of all the “created” Threads of the entire JVM process. Created Threads does not mean that all these Threads are actually doing something. In a typical Thread Dump snapshot generated from a Java EE container JVM: Some Threads could be performing raw computing tasks such as XML parsing, IO / disk access etc.  Some Threads could be waiting for some blocking IO calls such as a remote Web Service call, a DB / JDBC query etc.   Some Threads could be involved in garbage collection at that time e.g. GC Threads  Some Threads will be waiting for some work to do (Threads not doing any work typically go in wait() state)  Some Threads could be waiting for some other Threads work to complete e.g. Threads waiting to acquire a monitor lock (synchronized block{}) on some objectsI will get back to the above with more diagrams in my next article but for now let’s focus on the stack trace analysis process. Your next task is to be able to read a Thread stack trace and understand what it is doing, on the best of your knowledge. A Thread stack trace provides you with a snapshot of its current execution. The first line typically includes native information of the Thread such as its name, state, address etc. The current execution stack trace has to be read from bottom-up. Please follow the analysis process below. The more experience you get with Thread Dump analysis, the faster you will able to read and identify very quickly the work performed by each Thread:Start to read the Thread stack trace from the bottom  First, identify the originator (Java EE container Thread, custom Thread ,GC Thread, JVM internal Thread, standalone Java program “main” Thread etc.)  The next step is to identify the type of request the Thread is executing (WebApp, Web Service, JMS, Remote EJB (RMI), internal Java EE container etc.)  The next step is to identify form the execution stack trace your application module(s) involved e.g. the actual core work the Thread is trying to perform. The complexity of analysis will depend of the layers of abstraction of your middleware environment and application  The next step is to look at the last ~10-20 lines prior to the first line. Identify the protocol or work the Thread is involved with e.g. HTTP call, Socket communication, JDBC or raw computing tasks such as disk access, class loading etc.  The next step is to look at the first line. The first line usually tells a LOT on the Thread state since it is the current piece of code executed at the time you took the snapshot  The combination of the last 2 steps is what will give you the core of information to conclude of what work and / or hanging condition the Thread is involved withNow find below a visual breakdown of the above steps using a real example of a Thread Dump Thread stack trace captured from a JBoss 5 production environment. In this example, many Threads were showing a similar problem pattern of excessive IO when creating new instances of JAX-WS Service instances.As you can see, the last 10 lines along with the first line will tell us what hanging or slow condition the Thread is involved with, if any. The lines from the bottom will give us detail of the originator and type of request. I hope this article has helped you understand the importance of proper Thread stack trace analysis. I will get back with much more Thread stack trace examples when we cover the most common Thread Dump problem patterns in future articles. The next article will now teach you how to breakdown the Thread Dump threads in logical silos and come up with a potential list of root cause “suspects”. Reference: How to analyze Thread Dump – Part 5: Thread Stack Trace from our JCG partner Pierre-Hugues Charbonneau at the Java EE Support Patterns & Java Tutorial blog....

Mobicents Diameter has a new home.. powered by git!

Due to the increasingly number and complexity of sub-projects, Mobicents has been splitting it’s projects under independent project homes. We are now at a transition stage, where each project lead will migrate his project at the appropriate time. For Diameter, after our major release (1.4.0.FINAL), it seemed the best time to do this migration. The new home of the Mobicents Diameter project is located at http://code.google.com/p/jdiameter/. Feel free to visit us! With this change, we have also taken the chance to move to a “better” and more powerful version control system, so we have changed from SVN to Git. We hope this will ease the contributions, which have been happening more often, thanks to out thriving community! Despite being a allegedly better VCS, Git also has it’s own shortcomings, such as not being able to checkout a single folder. The lack of this feature has impacted our structure, since it makes it impossible to independently release sub-components in the same Git repository. While digging for a solution, I’ve came across the “sparse checkout” feature. While this may work for checking out only some folder(s), it is not supported by maven release plugin, thus not fixing the main problem. Another possible (and probably more correct) solution would be to use the “sub-repository” approach, where we’d split the components into different sub-repositories. We actually did this on a first phase, but after realizing the big changes it would imply and being aware that google code messes with the automatic revision links ( http://code.google.com/p/support/issues/detail?id=3245) we have decided to revert back to the single repository approach and abdicate from the release independency for each component. We have barely used it, anyway. The only exception is for the Jopr RHQ Plugin, so it got it’s own sub-repository. As a reference for someone going through the same process of moving from a [googlecode] SVN repository to a [googlecode] git repository, I’ll leave a summary of the commands used for the move (please keep in mind that I’m totally new to git, so these may not be the optimal way, feel free to comment): 0. (optional) Since SVN only lists the username and git uses the email as well, the migration will cause weird authors such as “brainslog <brainslog@bf0df8d0-2c1f-0410-b170-bd30377b63dc>” it may be good to sanitize the authors. For that I’ve used the following script in the SVN repository: svn log -q | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > authors.txtAnd then I’ve fixed the outcome in authors.txt to the correct: username = Full Name . 1. Clone the new (and probably empty) repository git clone https://@code.google.com/p/jdiameter/ git-jdiameter2. Clone from SVN (with authors fixed) to the cloned git repository, with full history, tags and branches git svn clone -A authors.txt -Ttrunk/servers/diameter -ttags/servers/diameter -bbranches/servers/diameter https://mobicents.googlecode.com/svn git-jdiameterWhere -A points to the authors file, -T to the trunk of the SVN repository, -t to the tags and -b to the branches. Use only what you need, I didn’t needed the branches part as we don’t have any. 3. Enter the local git repository cd git-jdiameter4. Push! git push --all5. Create the git tags from SVN tags (I know this can be automatized but I needed to make some customizations to existing tags, as not all were correct) git tag "1.0.0.BETA1" "refs/remotes/tags/jdiameter-1.0.0.BETA1" ...git tag "1.0.0.FINAL" "refs/remotes/tags/1.0.0.FINAL"6. Push.. again! git push --tagsThese are the 7 magical steps! In case that you don’t care about history, simply do a svn export --force http://mobicents.googlecode.com/svn/trunk/servers/diameter/ git-jdiameterand push it, nothing else. Also, as mentioned, I did not had branches but I suppose they’d make it in the #4 push. Mobicents Diameter users working with trunk master, must now switch to this new repository as the SVN will not be updated anymore! Do a ” git clone https://code.google.com/p/jdiameter/” and hack away! Reference: Mobicents Diameter has a new home.. powered by git! from our JCG partner Alexandre Mendonca at the Alexandre Mendonca blog blog....
Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

20,709 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books