Friday, November 30, 2012

Add Social Login to your site using Connect - simple Java based demo


Conducted researches prove that there is groving popularity in social login. It is very likely that user will leave your site, if they are forced to sing up through complex registration form. Users are looking for easier and faster ways to create web application's accounts, usually by reusing their existing profiles on popular services. Offering log in with Facebook, Google, Miicard, and other providers is a common feature for the most of modern web applications. It makes user's life much easier, but implementing such options may give quite a few developers a headache. Getting to know various authorization protocols (OAuth 1.0, OAuth 1.0a, OAuth 2.0, OpenID Connect, SAML, etc.), learning specific implementation's of these protocols, consuming various providers' APIs and continuously monitoring their changes are common tasks for websites that supports social login.

It would be much easier to have service that works with various authorization protocols, integrates with popular login providers, handles security issues and expose unified API that any web aplication can integrate with in no more that 10 minutes. This functionality is offered by Connect from Cloud Identity. Through integration with single Connect's API your site can accept user's with accounts on Facebook, Google, PayPal, Miicard, Yahoo, Windows Live, among the others. This tutorial will show how quickly add social login to your site.

We are going to build simple Java based application that requires user authentication. The application uses Connect service to enable authentication through social login. You can see demo here:


And the video:



Tuesday, December 6, 2011

The Business of Open Source

"I've experienced quite a bit about how open source works. It's been a wonderful learning experience for me and definitely turned me from someone who thought open source code and developers were somehow not as good as closed source equivalents into a person who knows that the opposite is most definitely the case!"(Mark Little, Red Hat, blog)

Indisputable fact of today's worlds is an existence of many IT companies that based their success on the Open Source. Talend, Alfresco, Cloudera, Mozilla and last but not least: Red Hat/JBoss (How JBoss did it!) are great examples of that.

Many more, Google, Facebook, Microsoft and Yahoo and many more, provides commercial services, and are not entirely based on open source projects, but helps their communities, seeing obviously support business model in there. Growing popularity of cloud computing has been giving birth of new open source cloud platforms, high performance distributed computing, decentralized and scalable databases. Many of these solutions does not have comparable closed ones and all of them in some way constitute of the revenue for the enterprises.

Even though, many businesses are constantly striving for using closed source software provided by "big vendor's", with very expensive and professional marketing machine. Good, that there is slow, but visible movement towards open products build within communities. Benefits of that movement are getting more and more visible, followed by many successful stories. That is caused by many advantages of the Open Source.:
  • No vendor lock-in
There is no need to depend on any software vendor. Open source projects are free, and publicly available for everyone without requirement to sign purchase agreement. Take it and use it is the only rule. That gives high flexibility for any organization. If product does not suit your requirements you can simply change it without breaking contract and loosing money.

In more advanced cases you may want to have professional support for the open source product from external company that knows well this particular solution. Most of the times you can choose from at least few companies. Sometimes vendors provide a commercial version of open source projects. Using them make sense if you need very stable product, 24h support, SLA or customized functionality. Even if it looks like traditional vendor lock-in it is common practice that you require from them continuous compatibility with open source version, e.g. every feature requested by you that is added to commercial version is contributed back to the community. Then, you can always resign from their services and choose open source stack.
  • Continuity
If you purchase closed product you take the risk that vendor will not bankrupt or shutdown project while you use it. You may easily end up with "black box" product, not developed anymore with potential bugs and security issues that you cannot fix. Replacing solution with competitive one is not usually easy way either even if both are standard compliant. With Open Source you never come across that. In the blackest scenario you have source that you can modify, add new features, fix bugs or train developers to expand it further. 
  • Companies competition
In most cases every mature open source products have several companies that provides professional services or commercial version of it. This provides to much healthier market than in single, monopoly vendor situation. Companies supporting clients has to compete with price, better adherence to the standards and services quality - often employees of these companies are commiters to open source projects and knows them very well.
  • Zero entry cost
It is always good practice to try out several solution, to choose most suitable one before deploying it within your organization. You can test several open source projects without any cost and choose one that best matches you requirements. 
  • Reduced overall costs
From the business perspective what matters the most is TCO (Total Cost of Ownership) that determines direct and indirect costs of purchased software. There is plenty of arguments in Open Source favour:
    • Zero purchase fee. 
    • No license fees, e.g. for every product user (does not increase cost when you organization grows)
    • No organizational administrative costs to purchase software, updates etc.
    • Competition in the markets keeps lower support costs and quality services
    • Eliminated risk of closing project by the vendor or vendor bankruptcy
  • Security and quality
Open source projects code is publicly available and may be seen by anyone. This causes that many developers from all over the world, browse actual source code, find bugs or security breaches and contribute patches. All they have different background, specialties, education so they focus on different aspects of the product. That makes overall open source software very reliable, consisting best practices of software engineering. 
Open source software engineers produces much better code than in closed projects as code visible to their colleagues, random programmers or potential future employers. 
  • Engineers are happy
That is what marketing and business people does not usually understand. Most of the engineers love to work for companies that has interesting and creative projects and uses "cool" technologies. Job then allows them not only to pay bills but as well fulfill their ambition, get chance to exhibit themselves in absorbing tasks and have satisfaction from what they are building. I've talked with few developers that were ready to agree to the lover salary in favor of working on more interesting projects. 

Using and contributing to open source projects allows developers to interact with many different people from around the world, even if it is usually just through an email conversation. Developers may fix bugs add new features in whole community benefit. Their work is then visible for public and done in cooperation with other project members. Comparing to the internal team or particular customer. That makes them happy and encourages work. It's completely not different from other technologist professions. The best enjoyment for an architect is to see that bridge he designed helps thousands of people, every day to move side to side. 
  • Easier to add new features
Open Source gives you another benefit. Faster changes introduction comparing to the closed source software. It may take long time before your "big software vendor" gives you feature you requested. That depends how much money your organization pays for support and SLAs. Release proccess in community projects is much flexible and in the critical situations you can introduce change on your own.    
  • Benefit from each other
If software is build by the community, many people and companies contributes to that. Not every functionality that your organization wants to use has to be implemented by your software vendor. In open source very often you get it for free, just because somebody else within the project community had similar problem to you. On the other hand, code contributed by your organization may be used by others. It's a mutual benefit.
  • Have influence on a standard
Very often reference implementation of the standard specification is implemented as open source project. It allows all involved in the standard parties to work on the development to fulfill all theirs priorities. Even more often happens that implementation is done beforehand standardization. If your organization is one of its creators, you can influence the way that standard goes. 


This article is a mix of our thoughts and discussions over last ApacheCon NA 2011 in Vancouver, BC that SMART project was able to attend. Thanks very much for TAC team for the support.

Tuesday, September 20, 2011

Exceptions Handling in Spring

Java Servlet Specification comes up with basic exception and HTTP response code mapping. It allows to define customized, user friendly web pages in case of Java exception or HTTP server error response. User never sees exception stacktrace or ugly 404 Not Found server page. This can be simply achieved through configuring deployment description web.xml, e.g.: by adding following entries:
    
404
/error/notFound



403
/error/denied



java.lang.Throwable
/error/generic


This is very straightforward solution and can be add to any application very quickly. However there are at least two main drawbacks of such solutions:
  1. Error page customization: Error page cannot be customized (custom error message, displaying error id helpful for the support) depending on for example exception that has been thrown. Servlet container immediately redirects user to the error page.
  2. Invoking application logic: There is no way to perform any additional application logic before redirecting user to the error page like logging, etc.
Spring Framework provides solution that overcomes both these drawbacks. All magic is done by class implementing following interface:
org.springframework.web.servlet.HandlerExceptionResolver
There is attached below sample implementation of the Spring exception resolver (it extends AbstractHandlerExceptionResolver class which adds some additional functionality to the resolver e.g.: allows defining what exceptions this particular resolver should handle: error response statuses, java exceptions, etc; default is all)

package uk.ac.ncl.cs.smart.am2.web.exception;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;

import net.smartam.commons.util.http.UrlUtils;
import uk.ac.ncl.cs.smart.am2.core.exception.SharingSettingUnauthorizedAccess;

/**
* @author Lukasz Moren
*/
@Component
public class CustomExceptionResolver extends AbstractHandlerExceptionResolver {

private static Logger logger = LoggerFactory.getLogger(CustomExceptionResolver.class);

@Override
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) {

// log exception
logger.error("Error:", ex);

if (ex instanceof SharingSettingUnauthorizedAccess) {

//this is special type of exception, do not show error but redirect to other page
final ModelAndView view = new ModelAndView("unauthorized_switch_users");
final String redirectTo = UrlUtils.buildFullRequestUrl(request);
view.addObject("redirect_to", redirectTo);
return view;

} else {

//show error page with short explanation
final ModelAndView error = new ModelAndView("error");
error.addObject("error_msg", ex.getMessage());
return error;
}
}
}
This implementation does three main things:
  1. Logs an error
  2. For exception type SharingSettingUnauthorizedAccess it redirects user to some authorization page
  3. By default it adds error message to be displayed and redirects to the error page

Wednesday, September 14, 2011

Hibernate Many To Many mapping with additional column in the join table

In this post I would like to show how to create Hibernate many to many mapping (using annotations) with join table containing additional column, next to two foreign keys. Let's consider two entities: Student and Course. Student can have multiple Courses and Course can have multiple Students. First, basic and typical many to many Hibernate mapping:
package uk.co.cloudidentity.manymany.simple;

import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

/**
* @author Lukasz Moren
*/
@Table
@Entity
public class Course implements Serializable {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;

@Column(name = "course_name")
private String courseName;

@ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
@JoinTable(
name = "student_courses",
joinColumns = @JoinColumn(name = "course_id"),
inverseJoinColumns = @JoinColumn(name = "student_id"),
uniqueConstraints = {@UniqueConstraint(columnNames = {"student_id", "course_id"})})
private List students;

public Course() {
}

public Course(String courseName) {
this.courseName = courseName;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getCourseName() {
return courseName;
}

public void setCourseName(String courseName) {
this.courseName = courseName;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}

Course course = (Course)o;

if (courseName != null ? !courseName.equals(course.courseName) : course.courseName != null) {
return false;
}
if (id != null ? !id.equals(course.id) : course.id != null) {
return false;
}

return true;
}

@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (courseName != null ? courseName.hashCode() : 0);
return result;
}
}
package uk.co.cloudidentity.manymany.simple;

import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

/**
* @author Lukasz Moren
*/

@Entity
@Table
public class Student {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "first_name")
private String firstName;

@Column(name = "last_name")
private String lastName;

@ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
@JoinTable(
name = "student_courses",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id"),
uniqueConstraints = {@UniqueConstraint(columnNames = {"student_id", "course_id"})})
private List courses;

public Student() {
}

public Student(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public List getCourses() {
return courses;
}

public void setCourses(List courses) {
this.courses = courses;
}

public void addCourse(Course course) {
if (courses == null) {
courses = new ArrayList();
}

courses.add(course);
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}

Student student = (Student)o;

if (firstName != null ? !firstName.equals(student.firstName) : student.firstName != null) {
return false;
}
if (id != null ? !id.equals(student.id) : student.id != null) {
return false;
}
if (lastName != null ? !lastName.equals(student.lastName) : student.lastName != null) {
return false;
}

return true;
}

@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (firstName != null ? firstName.hashCode() : 0);
result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
return result;
}
}
@JoinTable annotation creates new table: student_courses that associates Students and Courses. We don't need to create new mapping class in Java, table will be created automatically by Hibernate. The problem with this solution is that we cannot add new column to student_courses table. What if we would like to add sign_up_date column. To solve that we have to create use different mapping technique that requires creating student_courses mapping class. Full list of required mappings below:
package uk.co.cloudidentity.manymany.pk;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

/**
* @author Lukasz Moren
*/
@Table
@Entity
public class CoursePK implements Serializable {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name = "ID")
private Long id;

@Column(name = "course_name")
private String courseName;

public CoursePK() {
}

public CoursePK(String courseName) {
this.courseName = courseName;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getCourseName() {
return courseName;
}

public void setCourseName(String courseName) {
this.courseName = courseName;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}

CoursePK course = (CoursePK)o;

if (courseName != null ? !courseName.equals(course.courseName) : course.courseName != null) {
return false;
}
if (id != null ? !id.equals(course.id) : course.id != null) {
return false;
}

return true;
}

@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (courseName != null ? courseName.hashCode() : 0);
return result;
}
}
package uk.co.cloudidentity.manymany.pk;

import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

/**
* @author Lukasz Moren
*/

@Entity
@Table
public class StudentPK {

@Id
@Column(name = "ID")
@GeneratedValue(strategy= GenerationType.IDENTITY)
private Long id;

@Column(name = "first_name")
private String firstName;

@Column(name = "last_name")
private String lastName;

@OneToMany(cascade = CascadeType.ALL, mappedBy = "student", fetch = FetchType.LAZY)
private List courses;

public StudentPK() {
}

public StudentPK(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public List getCourses() {
return courses;
}

public void setCourses(List courses) {
this.courses = courses;
}

public void addCourse(CoursePK coursePK) {
if (courses == null) {
courses = new ArrayList();
}

StudentCourse studentCourse = new StudentCourse(this, coursePK);
courses.add(studentCourse);
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}

StudentPK student = (StudentPK)o;

if (firstName != null ? !firstName.equals(student.firstName) : student.firstName != null) {
return false;
}
if (id != null ? !id.equals(student.id) : student.id != null) {
return false;
}
if (lastName != null ? !lastName.equals(student.lastName) : student.lastName != null) {
return false;
}

return true;
}

@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (firstName != null ? firstName.hashCode() : 0);
result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
return result;
}
}
Student an Course mapping classes are very similar to our first example.
package uk.co.cloudidentity.manymany.pk;

import java.io.Serializable;
import javax.persistence.Embeddable;

/**
* @author Lukasz Moren
*/
@Embeddable
public class StudentCoursePK implements Serializable {

private Long courseId;
private Long studentId;

public StudentCoursePK(Long courseId, Long studentId) {
this.courseId = courseId;
this.studentId = studentId;
}

public StudentCoursePK() {
}

public Long getCourseId() {
return courseId;
}

public void setCourseId(Long courseId) {
this.courseId = courseId;
}

public Long getStudentId() {
return studentId;
}

public void setStudentId(Long studentId) {
this.studentId = studentId;
}
}
Above class maps student_course table primary key, that contains two columns: courseId and studentId. Class is marked with @Embeddable what means it can be used in other mapping classes as a primary key.
package uk.co.cloudidentity.manymany.pk;

import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MapsId;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

/**
* @author Lukasz Moren
*/
@Table
@Entity
public class StudentCourse implements Serializable {

@EmbeddedId
private StudentCoursePK userHostPK = new StudentCoursePK();

@MapsId("studentId")
@JoinColumn(name = "STUDENT_ID", referencedColumnName = "ID")
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private StudentPK student;

@MapsId("courseId")
@JoinColumn(name = "COURSE_ID", referencedColumnName = "ID")
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private CoursePK course;

@Column
@Temporal(TemporalType.TIMESTAMP)
private Date signUpDate;

public StudentCourse() {
}

public StudentCourse(StudentPK student, CoursePK course) {
this.student = student;
this.course = course;
}

public StudentCoursePK getUserHostPK() {
return userHostPK;
}

public void setUserHostPK(StudentCoursePK userHostPK) {
this.userHostPK = userHostPK;
}

public StudentPK getStudent() {
return student;
}

public void setStudent(StudentPK student) {
this.student = student;
}

public CoursePK getCourse() {
return course;
}

public void setCourse(CoursePK course) {
this.course = course;
}
}
Finally we have mapping class for student_course table. Apart from embedded primary key it contains fields of StudentPK and CoursePK types. Moreover we have custom signUpDate column defined.

Friday, October 1, 2010

leeloo 0.1 released - OAuth 2.0 draft 10 java implementation


leeloo is the Java implementation of the OAuth 2.0 protocol (currently draft 10 of the specification).

It allows you to easily build OAuth clients, authorization servers and resource servers.
Check it out:  http://leeloo.smartam.net
and begin using it with quick start: http://bitbucket.org/smartproject/oauth-2.0/wiki/Client

Main leeloo features:

  • Covers OAuth 2.0 specification draft 10
  • Both for OAuth clients and AS/RS
  • Lightweight and non intrusive
  • Simple and extensible API
  • Under heavy development
  • High unit tests coverage
Your feedback and contribution is essential for us. You can submit bugs, ideas and feature requests at: http://bitbucket.org/smartproject/oauth-2.0/issues

We plan to actively develop this library with regular releases and implementing new features upcoming with new versions of OAuth 2.0 specification. Our goal is to build extension packages that will allow to quick integrate leeloo with popular Java frameworks.

Keep updated!

Monday, September 20, 2010

Hibernate's Open Session in View in Spring MVC

Problem: org.hibernate.LazyInitializationException on web application view rendering. 

Recipe:
LazyInitializationException is one of the most common Hibernate exception's that appears during web development.
It appears when hibernate tries to access persistent object without assocciated hibernate session.

For example assume Spring MVC controller:

@RequestMapping(value = "/users/{id}")
    public ModelAndView getUserInfo(@PathElement("id") String id, Model model) {
       
        //get user from database
        User user = userService.findUser(id);
   
        model.addAttribute("user", user);
        return new ModelAndView("userInfoView");
    }
}
and hibernate persistent class:
package uk.lmoren.blog.demo;

import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

/**
 * @author Lukasz Moren
 */

@Entity
@Table
public class User implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column
    private Long id;

    @Column
    private String name;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "user", fetch = FetchType.LAZY)
    private List albums;
   
    // access method ommited
    // ... ...   

}

Spring controller intercept request that matches pattern: /users/{user}, fetch user object with given id from database, add it to the application model and redirect to view named: userUnfoView. The View retrieves an information from model and display it to the user.

Example .jsp (using JSTL tags) page doing that:
Username:${user.name}

User albums:

    Album name: ${album.name}



When server try to read list of albums through ${user.albums} will cause org.hibernate.LazyInitializationException. The problem is that there is no associated hibernate session with thread fetching abums from database. It is great explained in post: http://community.jboss.org/docs/DOC-13954

Simply solution for that is just start new hibernate session and database transaction with every HTTP request and commit it just before sending response. It assures that view is fully rendered before closing session and there is no open database connection left.

Spring comes up with implementation of that either through:
org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor
or
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
Both behave similarly, difference is explained here: opensessioninviewinterceptor-vs-opensessioninviewfilter/.



To configure OpenSessionInViewFilter filter add to web.xml filter configuration and url mapping:
    
        hibernateSessionInViewFilter
        org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
   


    
        hibernateSessionInViewFilter
        /a/*
    


Similarly with OpenSessionInViewInterceptor , add this to Spring's applicationContext.xml configuration file:













Now you can forget about LazyInitializationException. Hope it helps.

Tuesday, July 27, 2010

OAuth 1.0a client and server examples

During my GSoC development I managed to build sample OAuth 1.0a client and server implementations.
I know that OAuth 1.0 is not the newest specification, and would be cool to create demos that show 2.0 spec in action. Hovewer, even OAuth 1.0a is more complicated than 2.0 aims to be, it is mature specification, do its work well and it's already implemented by number of big providers.

You can try OAuth client at: http://oauthclient.appspot.com/
and server at: http://cxfoauthserver.appspot.com/.

Client is just usual OAuth consumer that accesses protected resources from Resource Server. You can easily test your OAuth provider implementation with it or see how OAuth flow works by connecting to existing providers like Google, Yahoo, Twitter,.

Server on the other hand is a OAuth provider that bases on Apache CXF framework, and its OAuth module I'm working on. As I mentioned in my previous post, my Google Summer of Code project aims on making simple framework that helps developers to secure their JAX-RS services with OAuth.

Work is still in progress so I appreciate any comments on that.