Featured FREE Whitepapers

What's New Here?

java-logo

Serialization in java

Java provides mechanism called serialization to persists java objects in a form of ordered or sequence of bytes that includes the object’s data as well as information about the object’s type and the types of data stored in the object. So if we have serialize any object then it can be read and deserialize it using object’s type and other information so we can retrieve original object. Classes ObjectInputStream and ObjectOutputStream are high-level streams that contain the methods for serializing and deserializing an object. ObjectOutputStream has many method for serializing object but commonly used method is:     private void writeObject(ObjectOutputStream os) throws IOException {} Similarly ObjectInputStream has private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException {} Need of Serialization? Serialization is usually used When the need arises to send your data over network or stored in files. By data I mean objects and not text. Now the problem is your Network infrastructure and your Hard disk are hardware components that understand bits and bytes but not Java objects. Serialization is the translation of your Java object’s values/states to bytes to send it over network or save it.On other hand,Deserialization is conversion of byte code to corresponding java objects. Concept of serialVersionUID : SerialVersionUID is used to ensure that same object(That was used during Serialization) is loaded during Deserialization.serialVersionUID is used for version control of object.You can read more at serialVersionUID in java serialization For Serialization: Steps are :Lets take an example: Create Employee.java in src->org.arpit.javapostsforlearning: 1.Employee.java package org.arpit.javapostsforlearning; import java.io.Serializable; public class Employee implements Serializable{int employeeId; String employeeName; String department;public int getEmployeeId() { return employeeId; } public void setEmployeeId(int employeeId) { this.employeeId = employeeId; } public String getEmployeeName() { return employeeName; } public void setEmployeeName(String employeeName) { this.employeeName = employeeName; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; } } As you can see above,if you want to serialize any class then it must implement Serializable interface which is marker interface. Marker interface in Java is interfaces with no field or methods or in simple word empty interface in java is called marker interface. Create SerializeMain.java in src->org.arpit.javapostsforlearning 2.SerializeMain.java package org.arpit.javapostsforlearning; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class SerializeMain {/** * @author Arpit Mandliya */ public static void main(String[] args) {Employee emp = new Employee(); emp.setEmployeeId(101); emp.setEmployeeName('Arpit'); emp.setDepartment('CS'); try { FileOutputStream fileOut = new FileOutputStream('employee.ser'); ObjectOutputStream outStream = new ObjectOutputStream(fileOut); outStream.writeObject(emp); outStream.close(); fileOut.close(); }catch(IOException i) { i.printStackTrace(); } } } For Deserialization: Steps are:Create DeserializeMain.java in src->org.arpit.javapostsforlearning 3.DeserializeMain.java package org.arpit.javapostsforlearning; import java.io.IOException; import java.io.ObjectInputStream;public class DeserializeMain { /** * @author Arpit Mandliya */ public static void main(String[] args) {Employee emp = null; try { FileInputStream fileIn =new FileInputStream('employee.ser'); ObjectInputStream in = new ObjectInputStream(fileIn); emp = (Employee) in.readObject(); in.close(); fileIn.close(); }catch(IOException i) { i.printStackTrace(); return; }catch(ClassNotFoundException c) { System.out.println('Employee class not found'); c.printStackTrace(); return; } System.out.println('Deserialized Employee...'); System.out.println('Emp id: ' + emp.getEmployeeId()); System.out.println('Name: ' + emp.getEmployeeName()); System.out.println('Department: ' + emp.getDepartment()); } } 4.Run it: First run SerializeMain.java then DeserializeMain.java and you will get following output: Deserialized Employee... Emp id: 101 Name: Arpit Department: CS So we have serialize an employee object and then deserialized it.It seems very simple but it can be very complex when reference object,inheritance come into the picture.So we will see different cases one by one and how we can apply serialization in different scenarios. Case 1-What if an object has a reference to other objects We have seen very simple case of serialization,now what if it also a reference to other objects.How will it serialized then? will reference object will also get serialized?.Yes,You don’t have to explicitly serialize reference objects.When you serialize any object and if it contain any other object reference then Java serialization serialize that object’s entire object graph. For example:Lets say,Employee now has reference to address object and Address can have reference to some other object(e.g.Home) then when you serialize Employee object all other reference objects such as address and home will be automatically serialized. Lets create Address class and add object of Address as a reference to above employee class. Employee.java: package org.arpit.javapostsforlearning; import java.io.Serializable;public class Employee implements Serializable{int employeeId; String employeeName; String department; Address address;public int getEmployeeId() { return employeeId; } public void setEmployeeId(int employeeId) { this.employeeId = employeeId; } public String getEmployeeName() { return employeeName; } public void setEmployeeName(String employeeName) { this.employeeName = employeeName; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } } Create Address.java in org.arpit.javapostsforlearning: Address.java: package org.arpit.javapostsforlearning; public class Address {int homeNo; String street; String city; public Address(int homeNo, String street, String city) { super(); this.homeNo = homeNo; this.street = street; this.city = city; } public int getHomeNo() { return homeNo; } public void setHomeNo(int homeNo) { this.homeNo = homeNo; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } } Create SerializeDeserializeMain.java in org.arpit.javapostsforlearning: SerializeDeserializeMain.java: package org.arpit.javapostsforlearning; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream;public class SerializeDeserializeMain { /** * @author Arpit Mandliya */ public static void main(String[] args) {Employee emp = new Employee(); emp.setEmployeeId(101); emp.setEmployeeName('Arpit'); emp.setDepartment('CS'); Address address=new Address(88,'MG road','Pune'); emp.setAddress(address); //Serialize try { FileOutputStream fileOut = new FileOutputStream('employee.ser'); ObjectOutputStream outStream = new ObjectOutputStream(fileOut); outStream.writeObject(emp); outStream.close(); fileOut.close(); }catch(IOException i) { i.printStackTrace(); }//Deserialize emp = null; try { FileInputStream fileIn =new FileInputStream('employee.ser'); ObjectInputStream in = new ObjectInputStream(fileIn); emp = (Employee) in.readObject(); in.close(); fileIn.close(); }catch(IOException i) { i.printStackTrace(); return; }catch(ClassNotFoundException c) { System.out.println('Employee class not found'); c.printStackTrace(); return; } System.out.println('Deserialized Employee...'); System.out.println('Emp id: ' + emp.getEmployeeId()); System.out.println('Name: ' + emp.getEmployeeName()); System.out.println('Department: ' + emp.getDepartment()); address=emp.getAddress(); System.out.println('City :'+address.getCity()); } } Run it : When you run SerializeDeserializeMain.java.You will get following output: java.io.NotSerializableException: org.arpit.javapostsforlearning.Address at java.io.ObjectOutputStream.writeObject0(Unknown Source) at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source) at java.io.ObjectOutputStream.writeSerialData(Unknown Source) at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source) at java.io.ObjectOutputStream.writeObject0(Unknown Source) at java.io.ObjectOutputStream.writeObject(Unknown Source) We got exception what went wrong.I forgot to mention,Address class must also be serializable.So you have to make Address serializable by implement serialzable interface. Address.java: import java.io.Serializable;public class Address implements Serializable{int homeNo; String street; String city; public Address(int homeNo, String street, String city) { super(); this.homeNo = homeNo; this.street = street; this.city = city; } public int getHomeNo() { return homeNo; } public void setHomeNo(int homeNo) { this.homeNo = homeNo; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } } Run again: When you run again SerializeDeserializeMain.java.You will get following output: Deserialized Employee... Emp id: 101 Name: Arpit Department: CS City: Pune Case 2:What if you don’t have access to reference object’s source code(e.g you don’t have access to above Address class) If you don’t have access to address class then how will you implement serializable interface in Address class.Is there any alternative to that? yes there is,You can create another class which extends address and make it serialzable but It can fails in many cases:What if class is declared as final What if class have reference to other non serializable object.So then how will you serialize Employee object? so solution is you can make it transient.If you don’t want to serialize any field then make it transient. transient Address address So after making address transient in Employee class when you run program.You will get nullPointerException because during deserialization address reference will be null Case 3:What if you still want to save state of reference object(e.g above address object): If you make address transient then during deserialization it will return null.But what if you still want to have same state as when you have serialized address object.Java serialization provides a mechnism such that if you have private methods with particular signature then they will get called during serialization and deserialization so we will override writeObject and readObject method of employee class and they will be called during serialization and deserialization of Employee object. Employee.java: package org.arpit.javapostsforlearning; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable;public class Employee implements Serializable{int employeeId; String employeeName; String department; transient Address address;public int getEmployeeId() { return employeeId; } public void setEmployeeId(int employeeId) { this.employeeId = employeeId; } public String getEmployeeName() { return employeeName; } public void setEmployeeName(String employeeName) { this.employeeName = employeeName; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; }private void writeObject(ObjectOutputStream os) throws IOException, ClassNotFoundException { try { os.defaultWriteObject(); os.writeInt(address.getHomeNo()); os.writeObject(address.getStreet()); os.writeObject(address.getCity()); } catch (Exception e) { e.printStackTrace(); } }private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException { try { is.defaultReadObject(); int homeNo=is.readInt(); String street=(String) is.readObject(); String city=(String) is.readObject(); address=new Address(homeNo,street,city);} catch (Exception e) { e.printStackTrace(); } } } One thing should be kept in mind that ObjectInputStream should read data in same sequence in which we have written data to ObjectOutputStream. Create Address.java in org.arpit.javapostsforlearning: Address.java: package org.arpit.javapostsforlearning; import java.io.Serializable;public class Address {int homeNo; String street; String city;public Address(int homeNo, String street, String city) { super(); this.homeNo = homeNo; this.street = street; this.city = city; } public int getHomeNo() { return homeNo; } public void setHomeNo(int homeNo) { this.homeNo = homeNo; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } } Create SerializeDeserializeMain.java in org.arpit.javapostsforlearning: SerializeDeserializeMain.java: package org.arpit.javapostsforlearning; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream;public class SerializeDeserializeMain { /** * @author Arpit Mandliya */ public static void main(String[] args) {Employee emp = new Employee(); emp.setEmployeeId(101); emp.setEmployeeName('Arpit'); emp.setDepartment('CS'); Address address=new Address(88,'MG road','Pune'); emp.setAddress(address); //Serialize try { FileOutputStream fileOut = new FileOutputStream('employee.ser'); ObjectOutputStream outStream = new ObjectOutputStream(fileOut); outStream.writeObject(emp); outStream.close(); fileOut.close(); }catch(IOException i) { i.printStackTrace(); }//Deserialize emp = null; try { FileInputStream fileIn =new FileInputStream('employee.ser'); ObjectInputStream in = new ObjectInputStream(fileIn); emp = (Employee) in.readObject(); in.close(); fileIn.close(); }catch(IOException i) { i.printStackTrace(); return; }catch(ClassNotFoundException c) { System.out.println('Employee class not found'); c.printStackTrace(); return; } System.out.println('Deserialized Employee...'); System.out.println('Emp id: ' + emp.getEmployeeId()); System.out.println('Name: ' + emp.getEmployeeName()); System.out.println('Department: ' + emp.getDepartment()); address=emp.getAddress(); System.out.println('City :'+address.getCity()); } } Run it : When you run SerializeDeserializeMain.java.You will get following output: Deserialized Employee... Emp id: 101 Name: Arpit Department: CS City :Pune so now we got same state of address object as it was before serialization. Inheritance in Serialization: Now we will see how inheritance affects serialization.So there can be muliple cases whether super class is serializable or not.If not then how will you handle that and how it works.Lets see by example. We will create Person.java which will be superclass of Employee:Case 4: What if superclass is Serializable? If superclass is serialzable then all its subclasses are automatically serializable. Case 5:What if superclass is not Serializable? If super class is not serializable then we have to handle it quite differently.If superclass is not serializable then it must have no argument constructor.Person.java package org.arpit.javapostsforlearning; public class Person {String name='default'; String nationality;public Person() { System.out.println('Person:Constructor'); }public Person(String name, String nationality) { super(); this.name = name; this.nationality = nationality; }public String getName() { return name; }public void setName(String name) { this.name = name; }public String getNationality() { return nationality; }public void setNationality(String nationality) { this.nationality = nationality; }} Create Employee.java in org.arpit.javapostsforlearning: Employee.java: package org.arpit.javapostsforlearning; import java.io.Serializable;public class Employee extends Person implements Serializable{int employeeId; String department;public Employee(int employeeId,String name,String department,String nationality) { super(name,nationality); this.employeeId=employeeId; this.department=department; System.out.println('Employee:Constructor'); }public int getEmployeeId() { return employeeId; } public void setEmployeeId(int employeeId) { this.employeeId = employeeId; }public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; } } Create SerializeDeserializeMain.java in org.arpit.javapostsforlearning: SerializeDeserializeMain.java: package org.arpit.javapostsforlearning; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream;public class SerializeDeserializeMain {/** * @author Arpit Mandliya */ public static void main(String[] args) {//Serialize Employee emp = new Employee(101,'Arpit','CS','Indian'); System.out.println('Before serializing'); System.out.println('Emp id: ' + emp.getEmployeeId()); System.out.println('Name: ' + emp.getName()); System.out.println('Department: ' + emp.getDepartment()); System.out.println('Nationality: ' + emp.getNationality()); System.out.println('************'); System.out.println('Serializing'); try { FileOutputStream fileOut = new FileOutputStream('employee.ser'); ObjectOutputStream outStream = new ObjectOutputStream(fileOut); outStream.writeObject(emp); outStream.close(); fileOut.close(); }catch(IOException i) { i.printStackTrace(); }//Deserialize System.out.println('************'); System.out.println('Deserializing'); emp = null; try { FileInputStream fileIn =new FileInputStream('employee.ser'); ObjectInputStream in = new ObjectInputStream(fileIn); emp = (Employee) in.readObject(); in.close(); fileIn.close(); }catch(IOException i) { i.printStackTrace(); return; }catch(ClassNotFoundException c) { System.out.println('Employee class not found'); c.printStackTrace(); return; } System.out.println('After serializing'); System.out.println('Emp id: ' + emp.getEmployeeId()); System.out.println('Name: ' + emp.getName()); System.out.println('Department: ' + emp.getDepartment()); System.out.println('Nationality: ' + emp.getNationality()); } } Run it : When you run SerializeDeserializeMain.java.You will get following output:If superclass is not Serializable then all values of the instance variables inherited from super class will be initialized by calling constructor of Non-Serializable Super class during deserialization process. So here name is inherited from person so during deserialization,name is initialized to default. Case 6-What if superclass is Serializable but you don’t want subclass to be Serializable If you don’t want subclass to serializable then you need to implement writeObject() and readObject() method and need to throw NotSerializableException from this methods. Case 7-Can you Serialize static variables? No,you can’t.As you know static variable are at class level not at object level and you serialize a object so you can’t serialize static variables. Summary:Serialization is the translation of your Java object’s values/states to bytes to send it over network or save it.On other hand,Deserialization is conversion of byte code to corresponding java objects. Good thing about Serialization is entire process is JVM independent, meaning an object can be serialized on one platform and deserialized on an entirely different platform.\ If you want to serialize any class then it must implement Serializable interface which is marker interface. Marker interface in Java is interface with no field or methods or in simple word empty interface in java is called marker interface serialVersionUID is used to ensure that same object(That was used during Serialization) is loaded during Deserialization.serialVersionUID is used for version control of object. When you serialize any object and if it contain any other object reference then Java serialization serialize that object’s entire object graph. If you don’t want to serialize any field,then make it trasient. If superclass is Serializable then its subclasses are automatically Serializable. If superclass is not Serializable then all values of the instance variables inherited from super class will be initialized by calling constructor of Non-Serializable Super class during deserialization process. If you don’t want subclass to serializable then you need to implement writeObject() and readObject() method and need to throw NotSerializableException from this methods. You can’t serialize static variables.  Reference: Serialization in java from our JCG partner Arpit Mandliya at the Java frameworks and design patterns for beginners blog. ...
java-logo

The Big Java News Keeps Coming: Java SE 6 and OpenJDK

I recently posted Recent Java 8 News, summarizing some of the recent developments in Java 8. In less than a week since publishing that post, several more significant Java news stories have come out and I summarize some of these in this post. Common themes include different Java SE 6 implementations and OpenJDK. Java Security Issues Impact End-of-Life for Oracle Java SE 6 Implementation In February 2012, Oracle extended the end-of-life for its Java SE 6 implementation from July 2012 to November 2012. This was later changed to February 2013 as shown in the Java SE EOL Policy under the section ‘Java SE 6 End of Public Updates Notice':   ‘After February 2013, Oracle will no longer post updates of Java SE 6 to its public download sites.’ Plans were slightly changed, however, due to discovered security vulnerabilities that led to two more Critical Patch Updates (CPUs): Java SE 6 Update 41 and Java SE 6 Update 43. Note that the odd numbers in the releases (41 and 43) indicate CPUs rather than limited updates. Oracle encourage developers to move to Java 7 for future updates. RedHat to Lead OpenJDK 6 It was announced this week that RedHat will take over leadership of the OpenJDK 6 project. As stated in the Red Hat press release, this move ‘effectively [extends] support for [OpenJDK 6] and its users.’ This is especially significant, of course, given the imminent end-of-life of the Java SE 6 implementation provided by Oracle. Java on iOS I recently posted on the announcement of plans to put JavaFX on iOS and Android. Now, there’s talk via an OpenJDK JDK Enhancement Proposal (JEP #178 – ‘Statically-Linked JNI Libraries’) of ‘[enhancing] the JNI specification to support statically-linked native libraries.’ This becomes even more interesting than it may initially sound when one considers implications such as the potential for this to allow Java applications to be deployed to iOS. Complimentary (Free!) Admission to JAXConf US It was announced this week that JAXConf US 2013 is open without charge to attendees to attend two days of keynotes and conference sessions (Tutorials day is $299). The conference is being held in Santa Clara, California, in early June (June 4-5). Other Interesting and Recent Java-Related Posts Although not necessarily news, there are other recent Java posts of general interest. Java Version History outlines some of the features introduced with each major version of Java/JDK. Geert Bevin uses the post My three-year Java abstinence: there and back again to look at ‘three reasons why I came back to Java and the JVM': community, tools and technology, JVM (and Java). Another recent post that was surprisingly interesting is Edmund Kirwan‘s JUnit’s evolving structure that looks at how JUnit (in particular version 4.3) delved into a convoluted package structure that is difficult to visualize. That post references radial encapsulation as one way to avoid this.   Reference: The Big Java News Keeps Coming: Java SE 6 and OpenJDK from our JCG partner Dustin Marx at the Inspired by Actual Events blog. ...
spring-interview-questions-answers

DeferredResult – asynchronous processing in Spring MVC

DeferredResult is a container for possibly not-yet-finished computation that will be available in future. Spring MVC uses it to represent asynchronous computation and take advantage of Servlet 3.0 AsyncContext asynchronous request handling. Just to give a quick impression how it works:               @RequestMapping("/") @ResponseBody public DeferredResult<String> square() throws JMSException { final DeferredResult<String> deferredResult = new DeferredResult<>(); runInOtherThread(deferredResult); return deferredResult; } private void runInOtherThread(DeferredResult<String> deferredResult) { //seconds later in other thread... deferredResult.setResult("HTTP response is: 42"); } Normally once you leave controller handler method request processing is done. But not with DeferredResult. Spring MVC (using Servlet 3.0 capabilities) will hold on with the response, keeping idle HTTP connection. HTTP worker thread is no longer used, but HTTP connection is still open. Later some other thread will resolve DeferredResult by assigning some value to it. Spring MVC will immediately pick up this event and send response (“HTTP response is: 42″ in this example) to the browser, finishing request processing. You might see some conceptual similarity between Future<V> and DeferredResult – they both represent computation with result available some time in the future. You might wonder, why Spring MVC doesn’t allow us to simply return Future<V> but instead introduced new, proprietary abstraction? The reason is simply and once again shows Future<V> deficiencies. The whole point of asynchronous processing is avoid blocking threads. Standard java.util.concurrent.Future does not allow registering callbacks when computation is done – so you either need to devote one thread to block until future is done or use one thread to poll several futures periodically. However the latter option consumes more CPU and introduces latency. But superior ListenableFuture<V> from Guava seems like a good fit? True, but Spring doesn’t have a dependency on Guava, thankfully bridging these two APIs is pretty straightforward. But first have a look at previous part on implementing custom java.util.concurrent.Future<V>. Admittedly it wasn’t as simple as one might expect. Clean up, handling interruptions, locking and synchronization, maintaining state. A lot of boilerplate when everything we need is as simple as receiving a message and returning it from get(). Let us try to retrofit previous implementation of JmsReplyFuture to also implement more powerful ListenableFuture – so we can use it later in Spring MVC. ListenableFuture simply extends standard Future adding possibility to register callbacks (listeners). So an eager developer would simply sit down and add list of Runnable listeners to existing implementation: public class JmsReplyFuture<T extends Serializable> implements ListenableFuture<T>, MessageListener { private final List<Runnable> listeners = new ArrayList<Runnable>(); @Override public void addListener(Runnable listener, Executor executor) { listeners.add(listener); } //... But it’s greatly oversimplified. Of course we must iterate over all listeners when future is done or exception occurs. If the future is already resolved when we add a listener, we must call that listener immediately. Moreover we ignore executor – according to API each listener may use a different thread pool supplied to addListener() so we must store pairs: Runnable + Executor. Last but not least addListener() is not thread safe. Eager developer would fix all this in a matter of an hour or two. And spend two more hours to fix bugs introduced in the meantime. And few more hours weeks later when another “impossible” bug pops-up on production. I am not eager. As a matter of fact, I am too lazy to write even the simplest implementation above. But I am desperate enough to hit Ctrl + H (Subtypes view in IntelliJ IDEA) on ListenableFuture and scan through available skeletal implementations tree. AbstractFuture<V> – Bingo! public class JmsReplyListenableFuture<T extends Serializable> extends AbstractFuture<T> implements MessageListener { private final Connection connection; private final Session session; private final MessageConsumer replyConsumer; public JmsReplyListenableFuture(Connection connection, Session session, Queue replyQueue) throws JMSException { this.connection = connection; this.session = session; this.replyConsumer = session.createConsumer(replyQueue); this.replyConsumer.setMessageListener(this); } @Override public void onMessage(Message message) { try { final ObjectMessage objectMessage = (ObjectMessage) message; final Serializable object = objectMessage.getObject(); set((T) object); cleanUp(); } catch (Exception e) { setException(e); } } @Override protected void interruptTask() { cleanUp(); } private void cleanUp() { try { replyConsumer.close(); session.close(); connection.close(); } catch (Exception e) { Throwables.propagate(e); } } } That’s it, everything, compile and run. Almost 2x less code compared to initial implementation and we get much more powerful ListenableFuture. Most of the code is set up and clean up. AbstractFuture already implements addListener(), locking and state handling for us. All we have to do is call set() method when future is resolved (JMS reply arrives in our case). Moreover we finally support exceptions properly. Previously we simply ignored/rethrown them while now they are correctly wrapped and thrown from get() when accessed. Even if we weren’t interested in ListenableFuture capabilities, AbstractFuture still helps us a lot. And we get ListenableFuture for free. Good programmers love writing code. Better ones love deleting it. Less to maintain, less to test, less to break. I am sometimes amazed how helpful Guava can be. Last time I was working with iterator-heavy piece of code. Data was generated dynamically and iterators could easily produce millions of items so I had no choice. Limited iterator API together with quite complex business logic is a recipe for endless amount of plumbing code. And then I found Iterators utility class and it saved my life. I suggest you to open JavaDoc of Guava and go through all packages, class by class. You’ll thank me later. Once we have our custom ListenableFuture in place (obviously you can use any implementation) we can try integrating it with Spring MVC. Here is what we want to achieve:HTTP request comes in We send a request to JMS queue HTTP worker thread is no longer used, it can serve other requests JMS listener asynchronously waits for a reply in temporary queue Once the reply arrives we push it immediately as an HTTP response and the connection is done.First naive implementation using blocking Future: @Controller public class JmsController { private final ConnectionFactory connectionFactory; public JmsController(ConnectionFactory connectionFactory) { this.connectionFactory = connectionFactory; } @RequestMapping("/square/{value}") @ResponseBody public String square(@PathVariable double value) throws JMSException, ExecutionException, InterruptedException { final ListenableFuture<Double> responseFuture = request(value); return responseFuture.get().toString(); } //JMS API boilerplate private <T extends Serializable> ListenableFuture<T> request(Serializable request) throws JMSException { Connection connection = this.connectionFactory.createConnection(); connection.start(); final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); final Queue tempReplyQueue = session.createTemporaryQueue(); final ObjectMessage requestMsg = session.createObjectMessage(request); requestMsg.setJMSReplyTo(tempReplyQueue); sendRequest(session.createQueue("square"), session, requestMsg); return new JmsReplyListenableFuture<T>(connection, session, tempReplyQueue); } private void sendRequest(Queue queue, Session session, ObjectMessage requestMsg) throws JMSException { final MessageProducer producer = session.createProducer(queue); producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); producer.send(requestMsg); producer.close(); } } This implementation is not very fortunate. As a matter of fact we don’t need Future at all as we are barely blocking on get(), synchronously waiting for a response. Let’s try with DeferredResult: @RequestMapping("/square/{value}") @ResponseBody public DeferredResult<String> square(@PathVariable double value) throws JMSException { final DeferredResult<String> deferredResult = new DeferredResult<>(); final ListenableFuture<Double> responseFuture = request(value); Futures.addCallback(responseFuture, new FutureCallback<Double>() { @Override public void onSuccess(Double result) { deferredResult.setResult(result.toString()); } @Override public void onFailure(Throwable t) { deferredResult.setErrorResult(t); } }); return deferredResult; } Much more complex, but will also be much more scalable. This method takes almost no time to execute and HTTP worker thread is shortly after ready to handle another request. The biggest observation to make is that onSuccess() and onFailure() are executed by another thread, seconds or even minutes later. But HTTP worker thread pool is not exhausted and application remains responsive. This was a school book example, but can we do better? First attempt is to write generic adapter from ListenableFuture to DeferredResult. These two abstractions represent exactly the same thing, but with different API. It’s quite straightforward: public class ListenableFutureAdapter<T> extends DeferredResult<String> { public ListenableFutureAdapter(final ListenableFuture<T> target) { Futures.addCallback(target, new FutureCallback<T>() { @Override public void onSuccess(T result) { setResult(result.toString()); } @Override public void onFailure(Throwable t) { setErrorResult(t); } }); } } We simply extend DeferredResult and notify it using ListenableFuture callbacks. Usage is simple: @RequestMapping("/square/{value}") @ResponseBody public DeferredResult<String> square(@PathVariable double value) throws JMSException { final ListenableFuture<Double> responseFuture = request(value); return new ListenableFutureAdapter<>(responseFuture); } But we can do even better! If ListenableFuture and DeferredResult are so similar, why not simply return ListenableFuture from the controller handler method? @RequestMapping("/square/{value}") @ResponseBody public ListenableFuture<Double> square2(@PathVariable double value) throws JMSException { final ListenableFuture<Double> responseFuture = request(value); return responseFuture; } Well, it won’t work because Spring doesn’t understand ListenableFuture and will just blow up. Fortunately Spring MVC is very flexible and it allows us to easily register new so-called HandlerMethodReturnValueHandler. There are 12 such built-in handlers and every time we return some object from a controller, Spring MVC examines them in predefined order and chooses the first one that can handle given type. One such handler is DeferredResultHandler (name says it all) which we will use as a reference: public class ListenableFutureReturnValueHandler implements HandlerMethodReturnValueHandler { public boolean supportsReturnType(MethodParameter returnType) { Class<?> paramType = returnType.getParameterType(); return ListenableFuture.class.isAssignableFrom(paramType); } public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { if (returnValue == null) { mavContainer.setRequestHandled(true); return; } final DeferredResult<Object> deferredResult = new DeferredResult<>(); Futures.addCallback((ListenableFuture<?>) returnValue, new FutureCallback<Object>() { @Override public void onSuccess(Object result) { deferredResult.setResult(result.toString()); } @Override public void onFailure(Throwable t) { deferredResult.setErrorResult(t); } }); WebAsyncUtils.getAsyncManager(webRequest).startDeferredResultProcessing(deferredResult, mavContainer); } } Running out of karma, installing this handler is not as straightforward as I had hoped. Technically there is WebMvcConfigurerAdapter.addReturnValueHandlers() which we can easily override if using Java configuration for Spring MVC. But this method adds custom return value handler at the end of handlers chain and for reasons beyond the scope of this article we need to add it at the beginning (higher priority). Fortunately with a little bit of hacking we can achieve that as well: @Configuration @EnableWebMvc public class SpringConfig extends WebMvcConfigurerAdapter { @Resource private RequestMappingHandlerAdapter requestMappingHandlerAdapter; @PostConstruct public void init() { final List<HandlerMethodReturnValueHandler> originalHandlers = new ArrayList<>(requestMappingHandlerAdapter.getReturnValueHandlers().getHandlers()); originalHandlers.add(0, listenableFutureReturnValueHandler()); requestMappingHandlerAdapter.setReturnValueHandlers(originalHandlers); } @Bean public HandlerMethodReturnValueHandler listenableFutureReturnValueHandler() { return new ListenableFutureReturnValueHandler(); } } Summary In this article we familiarized ourselves with another incarnation of future/promise abstraction called DeferredResult. It is used to postpone handling of HTTP request until some asynchronous task finishes. Thus DeferredResult is great for web GUIs built on top of event-driven systems, message brokers, etc. It is not as powerful as raw Servlet 3.0 API though. For example we cannot stream multiple events as they arrive (e.g. new tweets) in long-running HTTP connection – Spring MVC is designed more toward request-response pattern. We also tweaked Spring MVC to allow returning ListenableFuture from Guava directly from controller method. It makes our code much cleaner and expressive.   Reference: DeferredResult – asynchronous processing in Spring MVC from our JCG partner Tomasz Nurkiewicz at the NoBlogDefFound blog. ...
akka-logo

Futures in Akka with Scala

Akka is actor based, event-driven framework for building highly concurrent, reliable applications. Shouldn’t come a surprise that concept of a future is ubiquitous in a system like that. You typically never block waiting for a response, instead you send a message and expect response to arrive some time in the future. Sounds like great fit for… futures. Moreover futures in Akka are special for two reasons: Scala syntax together with type inference greatly improve readability and monadic nature. To fully appreciate the latter advantage check out scala.Option Cheat Sheet if you haven’t yet grasped monads in practice in Scala. We will continue our web crawler example taking yet another approach, this time with Akka on top of Scala. First the basic syntax: val future = Future { Source.fromURL( new URL("http://www.example.com"), StandardCharsets.UTF_8.name() ).mkString That was quick! future is of scala.concurrent.Future[String] inferred type. Provided code block will be executed asynchronously later and future (of Future[String] type) represents a handle to the value of that block. By now you should be wondering, how do you configure threads running this task? Good question, this code won’t compile as it stands, it needs ExecutionContext to work on. ExecutionContext is just like ExecutorService but can be given implicitly. You have several choices: import ExecutionContext.Implicits.global //or implicit val ec = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(50)) //or (inside actor) import context.dispatcher //or (explicitly) val future = Future { //... } (ec) First approach uses built in execution context composed of as many threads as many CPU/cores you have. Use this context only for small applications as it doesn’t scale well and is quite inflexible. Second approach takes existing ExecutorService and wraps it. You have full control over the number of threads and their behaviour. Notice how implicit val is picked up automatically. If you are inside an actor you can reuse Akka dispatcher to run your task using the same thread pool as actors use. Finally you can of course pass ExecutionContext explicitly. In next examples I assume some implicit context is available. Having Future instance we would like to process the result. I am not even mentioning about blocking and waiting for them synchronously (but examine official documentation if you really need it). More in a spirit of ListenableFuture from Guava we will register some completion callbacks first: Future { Source.fromURL(new URL("http://www.example.com"), StandardCharsets.UTF_8.name()).mkString } onComplete { case Success(html) => logger.info("Result: " + html) case Failure(ex) => logger.error("Problem", ex) } This feels pretty much like ListenableFuture but with cleaner syntax. However there are even more powerful tools in our box. Remember, last time we had one synchronous method to parse downloaded HTML and a second, asynchronous method to compute relevance of the document (whatever that means): def downloadPage(url: URL) = Future { Source.fromURL(url, StandardCharsets.UTF_8.name()).mkString } def parse(html: String): Document = //... def calculateRelevance(doc: Document): Future[Double] = //... Of course we can register onComplete callback but futures in Akka/Scala are monads, thus we can process the data as a sequence of chained, strongly typed transformations (explicit types preserved for clarity): val htmlFuture: Future[String] = downloadPage(new URL("http://www.example.com")) val documentFuture: Future[Document] = htmlFuture map parse val relevanceFuture: Future[Double] = documentFuture flatMap calculateRelevance val bigRelevanceFuture: Future[Double] = relevanceFuture filter {_ > 0.5} bigRelevanceFuture foreach println I want to be clear here. Calling Future.map(someOperation) does not wait for that future to complete. It simply wraps it and runs someOperation the moment it completes, some time in the, ekhem, future. The same applies to Future.filter and Future.foreach. You might be surprised to see them in this context as we typically associate such operators with collections. But just as with Option[T], Future[T] is, greatly oversimplifying, a collection that may or may not contain exactly one element. With this comparison it should be obvious what the code above does. Future.filter invocation might not be clear but it basically specifies that we are not interested in the result of asynchronous operation that does not meet certain criteria. If the predicate yields false, foreach operation will never be executed. Of course you can take advantage of type inference and chaining to get more concise, but not necessarily easier to read code: downloadPage(new URL("http://www.example.com")). map(parse). flatMap(calculateRelevance). filter(_ > 0.5). foreach(println But the biggest win comes from for-comprehensions. You might not be aware of that, but because Future implements map, foreach, filter and such (simplifying), we can use it inside for comprehension (same applies to Option[T]). So yet another, arguably most readable approach would be: for { html <- downloadPage(new URL("http://www.example.com")) relevance <- calculateRelevance(parse(html)) if(relevance > 0.5) } println(relevance) println("Done") It feels very imperative and sequential but in fact each step of this for comprehension is executed asynchronously and there is no blocking here. "Done" message will be displayed immediately, long before the computed relevance. This construct brings best of both worlds – looks sequential but in fact runs in background. Moreover it hides the obscure difference between functions returning value vs. Future of value (map vs. flatMap). Say we run code above for a list of web sites which gives us List[Future[Double]] and now we want to find the biggest relevance in that set. By now you should refuse all solutions involving blocking. There are two clever ways to do this in Scala – either by turning a List[Future[Double]] to Future[List[Double]] or by folding over a list of futures. The first solutions is identical to Futures.allAsList in Guava: val futures: Seq[Future[Double]] = //... val future: Future[Seq[Double]] = Future sequence futures future.onSuccess{ case x => println(s"Max relevance: ${x.max}") } or even more concisely (remember that x is a Seq[Double] in both cases: Future.sequence(futures).map {x => println(s"Max relevance: ${x.max}") } Remember that there is no blocking here. Future[Seq[Double]] completes when last underlying Future[Double] reports completion. If you like foldLeft() just like I do (but not necessarily here) consider the following idiom: Future.fold(futures)(0.0) {_ max _} map {maxRel => println(s"Max relevance: $maxRel") } This ones iterates over futures one-by-one and invokes our supplied {_ max _} fold function whenever given future succeeds. Summary Futures in Scala and Akka are very powerful: they allow non-blocking, CPU-effective asynchronous programming but they feel like imperative, single-threaded programming. You can apply sequence of transformations on top of a single future or a collection of them just as if that future was already resolved. Code looks totally imperative where you wait for one stage, run some transformation and run second stage. But in reality everything is asynchronous and event driven. Due to monadic nature of Future[V] and concise syntax, futures in Scala are a wonderful tool without introducing too much ceremony.   Reference: Futures in Akka with Scala from our JCG partner Tomasz Nurkiewicz at the NoBlogDefFound blog. ...
spring-interview-questions-answers

Customize Spring Social Connect Framework For MongoDB

In my previous post, I talked about the first challenge I had was to change the data model and add the connection framework. Here I want to give more details about how I did it. Spring Social project already provides a jdbc based connection repository implementation to persist user connection data into a relational database. However, I’m using MongoDB, so I need to customize the code, and I found it is relatively easy to do it. The user connection data will be saved as the object of UserSocialConnection, it is a MongoDB document:         @SuppressWarnings('serial') @Document(collection = 'UserSocialConnection') public class UserSocialConnection extends BaseEntity { private String userId; private String providerId; private String providerUserId; private String displayName; private String profileUrl; private String imageUrl; private String accessToken; private String secret; private String refreshToken; private Long expireTime;//Getter/Setter omitted.public UserSocialConnection() { super(); }public UserSocialConnection(String userId, String providerId, String providerUserId, int rank, String displayName, String profileUrl, String imageUrl, String accessToken, String secret, String refreshToken, Long expireTime) { super(); this.userId = userId; this.providerId = providerId; this.providerUserId = providerUserId; this.displayName = displayName; this.profileUrl = profileUrl; this.imageUrl = imageUrl; this.accessToken = accessToken; this.secret = secret; this.refreshToken = refreshToken; this.expireTime = expireTime; } } BaseEntity just has ‘id’. With the help of the Spring Data project, I don’t need to write any code of CRUD operations for UserSocialConnection, just extend MongoRepository: public interface UserSocialConnectionRepository extends MongoRepository<UserSocialConnection, String>{ List<UserSocialConnection> findByUserId(String userId);List<UserSocialConnection> findByUserIdAndProviderId(String userId, String providerId);List<UserSocialConnection> findByProviderIdAndProviderUserId(String providerId, String providerUserId);UserSocialConnection findByUserIdAndProviderIdAndProviderUserId(String userId, String providerId, String providerUserId);List<UserSocialConnection> findByProviderIdAndProviderUserIdIn(String providerId, Collection<String> providerUserIds); } After we have our database UserSocialConnectionRepository, we will implement Spring Social required ConnectionRepository and UsersConnectionRepository. I just copied the code from JdbcConnectionRepository and JdbcUsersConnectionRepository, and created my own MongoConnectionRepository and MongoUsersConnectionRepository. public class MongoUsersConnectionRepository implements UsersConnectionRepository{private final UserSocialConnectionRepository userSocialConnectionRepository;private final SocialAuthenticationServiceLocator socialAuthenticationServiceLocator;private final TextEncryptor textEncryptor;private ConnectionSignUp connectionSignUp;public MongoUsersConnectionRepository(UserSocialConnectionRepository userSocialConnectionRepository, SocialAuthenticationServiceLocator socialAuthenticationServiceLocator, TextEncryptor textEncryptor){ this.userSocialConnectionRepository = userSocialConnectionRepository; this.socialAuthenticationServiceLocator = socialAuthenticationServiceLocator; this.textEncryptor = textEncryptor; }/** * The command to execute to create a new local user profile in the event no user id could be mapped to a connection. * Allows for implicitly creating a user profile from connection data during a provider sign-in attempt. * Defaults to null, indicating explicit sign-up will be required to complete the provider sign-in attempt. * @see #findUserIdsWithConnection(Connection) */ public void setConnectionSignUp(ConnectionSignUp connectionSignUp) { this.connectionSignUp = connectionSignUp; }public List<String> findUserIdsWithConnection(Connection<?> connection) { ConnectionKey key = connection.getKey(); List<UserSocialConnection> userSocialConnectionList = this.userSocialConnectionRepository.findByProviderIdAndProviderUserId(key.getProviderId(), key.getProviderUserId()); List<String> localUserIds = new ArrayList<String>(); for (UserSocialConnection userSocialConnection : userSocialConnectionList){ localUserIds.add(userSocialConnection.getUserId()); }if (localUserIds.size() == 0 && connectionSignUp != null) { String newUserId = connectionSignUp.execute(connection); if (newUserId != null) { createConnectionRepository(newUserId).addConnection(connection); return Arrays.asList(newUserId); } } return localUserIds; }public Set<String> findUserIdsConnectedTo(String providerId, Set<String> providerUserIds) { final Set<String> localUserIds = new HashSet<String>();List<UserSocialConnection> userSocialConnectionList = this.userSocialConnectionRepository.findByProviderIdAndProviderUserIdIn(providerId, providerUserIds); for (UserSocialConnection userSocialConnection : userSocialConnectionList){ localUserIds.add(userSocialConnection.getUserId()); } return localUserIds; }public ConnectionRepository createConnectionRepository(String userId) { if (userId == null) { throw new IllegalArgumentException('userId cannot be null'); } return new MongoConnectionRepository(userId, userSocialConnectionRepository, socialAuthenticationServiceLocator, textEncryptor); }} MongoUsersConnectionRepository is pretty much exactly like JdbcUsersConnectionRepository. But for MongoConnectionRepository, I needed to make some changes: public class MongoConnectionRepository implements ConnectionRepository {private final String userId;private final UserSocialConnectionRepository userSocialConnectionRepository;private final SocialAuthenticationServiceLocator socialAuthenticationServiceLocator;private final TextEncryptor textEncryptor;public MongoConnectionRepository(String userId, UserSocialConnectionRepository userSocialConnectionRepository, SocialAuthenticationServiceLocator socialAuthenticationServiceLocator, TextEncryptor textEncryptor) { this.userId = userId; this.userSocialConnectionRepository = userSocialConnectionRepository; this.socialAuthenticationServiceLocator = socialAuthenticationServiceLocator; this.textEncryptor = textEncryptor; }public MultiValueMap<String, Connection<?>> findAllConnections() { List<UserSocialConnection> userSocialConnectionList = this.userSocialConnectionRepository .findByUserId(userId);MultiValueMap<String, Connection<?>> connections = new LinkedMultiValueMap<String, Connection<?>>(); Set<String> registeredProviderIds = socialAuthenticationServiceLocator.registeredProviderIds(); for (String registeredProviderId : registeredProviderIds) { connections.put(registeredProviderId, Collections.<Connection<?>> emptyList()); } for (UserSocialConnection userSocialConnection : userSocialConnectionList) { String providerId = userSocialConnection.getProviderId(); if (connections.get(providerId).size() == 0) { connections.put(providerId, new LinkedList<Connection<?>>()); } connections.add(providerId, buildConnection(userSocialConnection)); } return connections; }public List<Connection<?>> findConnections(String providerId) { List<Connection<?>> resultList = new LinkedList<Connection<?>>(); List<UserSocialConnection> userSocialConnectionList = this.userSocialConnectionRepository .findByUserIdAndProviderId(userId, providerId); for (UserSocialConnection userSocialConnection : userSocialConnectionList) { resultList.add(buildConnection(userSocialConnection)); } return resultList; }@SuppressWarnings('unchecked') public <A> List<Connection<A>> findConnections(Class<A> apiType) { List<?> connections = findConnections(getProviderId(apiType)); return (List<Connection<A>>) connections; }public MultiValueMap<String, Connection<?>> findConnectionsToUsers(MultiValueMap<String, String> providerUsers) { if (providerUsers == null || providerUsers.isEmpty()) { throw new IllegalArgumentException('Unable to execute find: no providerUsers provided'); }MultiValueMap<String, Connection<?>> connectionsForUsers = new LinkedMultiValueMap<String, Connection<?>>();for (Iterator<Entry<String, List<String>>> it = providerUsers.entrySet().iterator(); it.hasNext();) { Entry<String, List<String>> entry = it.next(); String providerId = entry.getKey(); List<String> providerUserIds = entry.getValue(); List<UserSocialConnection> userSocialConnections = this.userSocialConnectionRepository.findByProviderIdAndProviderUserIdIn(providerId, providerUserIds); List<Connection<?>> connections = new ArrayList<Connection<?>>(providerUserIds.size()); for (int i = 0; i < providerUserIds.size(); i++) { connections.add(null); } connectionsForUsers.put(providerId, connections);for (UserSocialConnection userSocialConnection : userSocialConnections) { String providerUserId = userSocialConnection.getProviderUserId(); int connectionIndex = providerUserIds.indexOf(providerUserId); connections.set(connectionIndex, buildConnection(userSocialConnection)); }} return connectionsForUsers; }public Connection<?> getConnection(ConnectionKey connectionKey) { UserSocialConnection userSocialConnection = this.userSocialConnectionRepository .findByUserIdAndProviderIdAndProviderUserId(userId, connectionKey.getProviderId(), connectionKey.getProviderUserId()); if (userSocialConnection != null) { return buildConnection(userSocialConnection); } throw new NoSuchConnectionException(connectionKey); }@SuppressWarnings('unchecked') public <A> Connection<A> getConnection(Class<A> apiType, String providerUserId) { String providerId = getProviderId(apiType); return (Connection<A>) getConnection(new ConnectionKey(providerId, providerUserId)); }@SuppressWarnings('unchecked') public <A> Connection<A> getPrimaryConnection(Class<A> apiType) { String providerId = getProviderId(apiType); Connection<A> connection = (Connection<A>) findPrimaryConnection(providerId); if (connection == null) { throw new NotConnectedException(providerId); } return connection; }@SuppressWarnings('unchecked') public <A> Connection<A> findPrimaryConnection(Class<A> apiType) { String providerId = getProviderId(apiType); return (Connection<A>) findPrimaryConnection(providerId); }public void addConnection(Connection<?> connection) { //check cardinality SocialAuthenticationService<?> socialAuthenticationService = this.socialAuthenticationServiceLocator.getAuthenticationService(connection.getKey().getProviderId()); if (socialAuthenticationService.getConnectionCardinality() == ConnectionCardinality.ONE_TO_ONE || socialAuthenticationService.getConnectionCardinality() == ConnectionCardinality.ONE_TO_MANY){ List<UserSocialConnection> storedConnections = this.userSocialConnectionRepository.findByProviderIdAndProviderUserId( connection.getKey().getProviderId(), connection.getKey().getProviderUserId()); if (storedConnections.size() > 0){ //not allow one providerId connect to multiple userId throw new DuplicateConnectionException(connection.getKey()); } }UserSocialConnection userSocialConnection = this.userSocialConnectionRepository .findByUserIdAndProviderIdAndProviderUserId(userId, connection.getKey().getProviderId(), connection.getKey().getProviderUserId()); if (userSocialConnection == null) { ConnectionData data = connection.createData(); userSocialConnection = new UserSocialConnection(userId, data.getProviderId(), data.getProviderUserId(), 0, data.getDisplayName(), data.getProfileUrl(), data.getImageUrl(), encrypt(data.getAccessToken()), encrypt(data.getSecret()), encrypt(data.getRefreshToken()), data.getExpireTime()); this.userSocialConnectionRepository.save(userSocialConnection); } else { throw new DuplicateConnectionException(connection.getKey()); } }public void updateConnection(Connection<?> connection) { ConnectionData data = connection.createData(); UserSocialConnection userSocialConnection = this.userSocialConnectionRepository .findByUserIdAndProviderIdAndProviderUserId(userId, connection.getKey().getProviderId(), connection .getKey().getProviderUserId()); if (userSocialConnection != null) { userSocialConnection.setDisplayName(data.getDisplayName()); userSocialConnection.setProfileUrl(data.getProfileUrl()); userSocialConnection.setImageUrl(data.getImageUrl()); userSocialConnection.setAccessToken(encrypt(data.getAccessToken())); userSocialConnection.setSecret(encrypt(data.getSecret())); userSocialConnection.setRefreshToken(encrypt(data.getRefreshToken())); userSocialConnection.setExpireTime(data.getExpireTime()); this.userSocialConnectionRepository.save(userSocialConnection); } }public void removeConnections(String providerId) { List<UserSocialConnection> userSocialConnectionList = this.userSocialConnectionRepository .findByUserIdAndProviderId(userId, providerId); for (UserSocialConnection userSocialConnection : userSocialConnectionList) { this.userSocialConnectionRepository.delete(userSocialConnection); } }public void removeConnection(ConnectionKey connectionKey) { UserSocialConnection userSocialConnection = this.userSocialConnectionRepository .findByUserIdAndProviderIdAndProviderUserId(userId, connectionKey.getProviderId(), connectionKey.getProviderUserId()); this.userSocialConnectionRepository.delete(userSocialConnection); }// internal helpersprivate Connection<?> buildConnection(UserSocialConnection userSocialConnection) { ConnectionData connectionData = new ConnectionData(userSocialConnection.getProviderId(), userSocialConnection.getProviderUserId(), userSocialConnection.getDisplayName(), userSocialConnection.getProfileUrl(), userSocialConnection.getImageUrl(), decrypt(userSocialConnection.getAccessToken()), decrypt(userSocialConnection.getSecret()), decrypt(userSocialConnection.getRefreshToken()), userSocialConnection.getExpireTime()); ConnectionFactory<?> connectionFactory = this.socialAuthenticationServiceLocator.getConnectionFactory(connectionData .getProviderId()); return connectionFactory.createConnection(connectionData); }private Connection<?> findPrimaryConnection(String providerId) { List<UserSocialConnection> userSocialConnectionList = this.userSocialConnectionRepository .findByUserIdAndProviderId(userId, providerId);return buildConnection(userSocialConnectionList.get(0)); }private <A> String getProviderId(Class<A> apiType) { return socialAuthenticationServiceLocator.getConnectionFactory(apiType).getProviderId(); }private String encrypt(String text) { return text != null ? textEncryptor.encrypt(text) : text; }private String decrypt(String encryptedText) { return encryptedText != null ? textEncryptor.decrypt(encryptedText) : encryptedText; }} First, I replaced JdbcTemplate with UserSocialConnectionRepository to retrieve UserSocialConnection objects from the database. Then replaced ConnectionFactoryLocator with SocialAuthenticationServiceLocator from spring-social-security module. A big change is in the addConnection method (highlighted above), where it checks connection cardinality first. If connectionCardinality of socialAuthenticationService is ONE_TO_ONE (which means one userId with one and only one pair of providerId/providerUserId), or ONE_TO_MANY (which means one userId can connect to one or many providerId/providerUserId, but one pair of providerId/providerUserId can only connect to one userId). After all those customizations, the final step is to glue them together in spring config: @Configuration public class SocialAndSecurityConfig { @Inject private Environment environment;@Inject AccountService accountService;@Inject private AuthenticationManager authenticationManager;@Inject private UserSocialConnectionRepository userSocialConnectionRepository;@Bean public SocialAuthenticationServiceLocator socialAuthenticationServiceLocator() { SocialAuthenticationServiceRegistry registry = new SocialAuthenticationServiceRegistry();//add google OAuth2ConnectionFactory<Google> googleConnectionFactory = new GoogleConnectionFactory(environment.getProperty('google.clientId'), environment.getProperty('google.clientSecret')); OAuth2AuthenticationService<Google> googleAuthenticationService = new OAuth2AuthenticationService<Google>(googleConnectionFactory); googleAuthenticationService.setScope('https://www.googleapis.com/auth/userinfo.profile'); registry.addAuthenticationService(googleAuthenticationService);//add twitter OAuth1ConnectionFactory<Twitter> twitterConnectionFactory = new TwitterConnectionFactory(environment.getProperty('twitter.consumerKey'), environment.getProperty('twitter.consumerSecret')); OAuth1AuthenticationService<Twitter> twitterAuthenticationService = new OAuth1AuthenticationService<Twitter>(twitterConnectionFactory); registry.addAuthenticationService(twitterAuthenticationService);//add facebook OAuth2ConnectionFactory<Facebook> facebookConnectionFactory = new FacebookConnectionFactory(environment.getProperty('facebook.clientId'), environment.getProperty('facebook.clientSecret')); OAuth2AuthenticationService<Facebook> facebookAuthenticationService = new OAuth2AuthenticationService<Facebook>(facebookConnectionFactory); facebookAuthenticationService.setScope(''); registry.addAuthenticationService(facebookAuthenticationService);return registry; }/** * Singleton data access object providing access to connections across all users. */ @Bean public UsersConnectionRepository usersConnectionRepository() { MongoUsersConnectionRepository repository = new MongoUsersConnectionRepository(userSocialConnectionRepository, socialAuthenticationServiceLocator(), Encryptors.noOpText()); repository.setConnectionSignUp(autoConnectionSignUp()); return repository; }/** * Request-scoped data access object providing access to the current user's connections. */ @Bean @Scope(value = 'request', proxyMode = ScopedProxyMode.INTERFACES) public ConnectionRepository connectionRepository() { UserAccount user = AccountUtils.getLoginUserAccount(); return usersConnectionRepository().createConnectionRepository(user.getUsername()); }/** * A proxy to a request-scoped object representing the current user's primary Google account. * * @throws NotConnectedException * if the user is not connected to Google. */ @Bean @Scope(value = 'request', proxyMode = ScopedProxyMode.INTERFACES) public Google google() { Connection<Google> google = connectionRepository().findPrimaryConnection(Google.class); return google != null ? google.getApi() : new GoogleTemplate(); }@Bean @Scope(value='request', proxyMode=ScopedProxyMode.INTERFACES) public Facebook facebook() { Connection<Facebook> facebook = connectionRepository().findPrimaryConnection(Facebook.class); return facebook != null ? facebook.getApi() : new FacebookTemplate(); }@Bean @Scope(value='request', proxyMode=ScopedProxyMode.INTERFACES) public Twitter twitter() { Connection<Twitter> twitter = connectionRepository().findPrimaryConnection(Twitter.class); return twitter != null ? twitter.getApi() : new TwitterTemplate(); }@Bean public ConnectionSignUp autoConnectionSignUp() { return new AutoConnectionSignUp(accountService); }@Bean public SocialAuthenticationFilter socialAuthenticationFilter() { SocialAuthenticationFilter filter = new SocialAuthenticationFilter(authenticationManager, accountService, usersConnectionRepository(), socialAuthenticationServiceLocator()); filter.setFilterProcessesUrl('/signin'); filter.setSignupUrl(null); filter.setConnectionAddedRedirectUrl('/myAccount'); filter.setPostLoginUrl('/myAccount'); return filter; }@Bean public SocialAuthenticationProvider socialAuthenticationProvider(){ return new SocialAuthenticationProvider(usersConnectionRepository(), accountService); }@Bean public LoginUrlAuthenticationEntryPoint socialAuthenticationEntryPoint(){ return new LoginUrlAuthenticationEntryPoint('/signin'); }} accountService is my own user account service to provide account related functions, and it implements SocialUserDetailsService, UserDetailsService, UserIdExtractor. There are still many areas to improve, such as refactoring MongoConnectionRepository and MongoUsersConnectionRepository to have an abstract social connection repository implementation using Spring Data Repository interface. And I found someone already has raised an issue for that: Leverage Spring Data for UsersConnectionRepository.   Reference: Customize Spring Social Connect Framework For MongoDB from our JCG partner Yuan Ji at the Jiwhiz blog. ...
software-development-2-logo

Enterprisey Developers, Acronyms, and Discrimination

Over the past few years my clientele shifted from a mix of mostly mid-market companies and a few startups to almost entirely startups, and that shift has resulted in a wider palette of languages requested by clients. Where my business was about 95% Java for the first 10+ years of my career, today it is closer to 25%. As I’ve written before, my business veered naturally from a pure Java focus when a considerable amount of the Java talent I have represented in years past started to migrate and show interest in diverse languages and ecosystems. Unlike the boom periods for startups in the past, it appears that today’s startup is much less likely to choose Java as the primary development platform. Many developers who did Java work for startups in the mid 2000?s sought higher ground in the late part of   the decade when small shops took a hit, and found themselves working for large companies and more corporate environments. Flash forward to the past few years and the resurgence of startups. Many of those engineers who took shelter in the larger firms are now interested in establishing themselves once again as a major contributor on a small team in a startup, and when I have represented some of these highly qualified developers to startups now, I’ve been met with the feedback ‘The candidate’s résumé appears too enterprisey‘. As an aside, I don’t get that response nearly as often for Java engineers that stayed with small companies. The enterprisey label, in my experience, seems to be used in two situations that can often (but not always) go hand-in-hand. First, enterprisey is often used to describe candidates that come from large development shops regardless of the languages used (although Java and .Net platforms are the norm), where the bias is that the development culture and the broader company culture make that candidate less likely to succeed in the startup. This is the result of preconceptions surrounding development methodology, possible unnecessary complexity in applications, a slower release schedule, or the impression that developers in these larger environments are sheltered from tasks related to data, devops, sysadmin, and QA that are frequently handled by developers at startups. The label may be applied liberally to virtually any candidate coming from a company larger than the hiring firm. The second common enterprisey tag is used on any developer using Java or .Net regardless of the employer size, due to the predominant viewpoint that other language communities have developed regarding Java/.Net being wrought with and plagued by dozens of frameworks and bloated stacks. As someone who sees thousands of résumés a year, it is clear that résumés of Java and .Net developers are often significantly longer than those of developers in other languages, but there could be several factors at play there beyond just the number of potential bloat items (insert Java = verbose joke here). At a distance, the résumés of Java developers can resemble an eye chart, with acronyms outnumbering actual words. One hiring manager of a Scala shop provided this gem: “The laundry list of legacy enterprise technologies (JMS, JMX, etc.) doesn’t do anything for me.” The word ‘legacy’ seems particularly cruel there. Sadly, many of those making hiring decisions in these startups are quick to dismiss a highly-skilled talent simply because of their experience working for a larger company or their primary language being in the Java or .Net worlds. Whereas an interest in, say, functional languages is now often used by startups as an indicator of ability, the prolonged use of Java or .Net at a large firm can be a detriment when applying for work in any other language or polyglot environments. So how can engineers labeled ‘enterprisey’ escape that bias and be accepted by smaller shops with different languages? Résumé and bio de-enterprisification That’s not a word (yet), but the concept would be to go back and make sure your résumé/bio/LinkedIn profile/etc. doesn’t read like a corporate Buzzword Bingo card. Eliminate or modify anything that may appear steeped in bureaucratic process and procedure, and be wary of any items that can be perceived as indicative of a glacial development pace. References to project length and time between releases should typically be avoided. Emphasize new development over maintenance tasks, and accomplishments over process. Listing too many tools, frameworks, and specifications will often work against you and may be considered an indicator of your dependence upon them. Shortening the résumé is almost always the way to go here, and three + page résumés generally smell of enterpriseyness. Develop other language credibility Any code that you can point to that does not run the risk of being labeled enterprisey is better than nothing. As stated before, some startups perceive functional programming interest as a marker for ability, so even an implementation of a typical interview exercise in a functional language (or one different from your primary) has value. Provide links to this code on your résumé and reference any personal projects that are applicable. Stop calling yourself ‘LANGUAGE Developer’ I do it too (all the time), but you should not. Use whatever you feel is appropriate – Software Engineer, Programmer, Developer, Geek – but stop inserting a language when describing yourself on paper or verbally. And perhaps more importantly, stop thinking of yourself as a LANGUAGE Developer. Sometimes you may need to dumb it down so the clueless recruiter will find you, but try to minimize those instances the best you can (and do you really want that recruiter to find you anyway?). Express your outside interests Just because you get paid by some insurance company to write Java/.Net apps all day doesn’t mean that is who you are. If you are exploring other languages through books, conferences, and self-study, make that known in whatever way may be discovered during your job search (résumé, blog, social media, etc.). Hobbies like robotics, Raspberry Pi, and Arduino are probably unrelated to your job but not necessarily unrelated to your career. Any technical interests beyond the primary function of your job demonstrate at least some level of versatility and the ability to adapt outside of your enterprisey 9 to 5.   Reference: Enterprisey Developers, Acronyms, and Discrimination from our JCG partner Dave Fecak at the Job Tips For Geeks blog. ...
software-development-2-logo

A case for putting off documentation until the end

I have a bad habit of putting off documenting my code as long as possible; it’s often my last task before I submit a pull request. And every time I’m slogging through hundreds or thousands of lines of code writing documentation, I think ‘Next time, I’m going to do this as I go along.’ And the next time I write a new feature, I’ll probably leave the documentation until the end again. As bad as this is, though, I’ve realized there are a few advantages to waiting until your code is finished before writing the documentation:      Minimize wasted effort: In an ideal world, your API and requirements wouldn’t change after you’ve started coding. But how often does that happen? If you need to change your code and you’ve already documented it, now you have to waste time updating your documentation. Forced self-review: Have you ever written a section of code, then looked at it later and realized you could have done it better? While going back through your code to document it, you are forced to reevaluate everything you’ve done; the extra time between coding and documenting can sometimes give you the perspective you need to refactor it. Catch dead code: Nothing makes me want to delete unnecessary code more than having to document it. Before I document a method, I’ll probably check to make sure it’s actually still being used. Consistency: I find I used more consistent terminology in my documentation when I’m doing it all at once. I get in a zone, find a language I think works, and stick with it the whole way through.Of course, there are some reasons nobody actually encourages this behavior:It’s awful: If you don’t enjoy documentation (and I definitely do not), it is really painful to write it all at once. Writing the documentation every time you write a method is annoying; writing documentation for dozens of methods is brutal. Faded memory: By the time you finally write the documentation, you may have forgotten what the code does or why you made certain decisions. On the flip side, this is a good indication that you should refactor your code anyway. Eh, forget it: When faced with this monumental task, it will be very tempting to just skip the documentation, or put it on your TODO list for later. Sometimes you may be able to get away with this, but you really never should.So I guess I’m not exactly recommending that you wait until the last minute to write your documentation. I’m just saying that there are some upsides to it. Or maybe I’m really just trying to justify my own behavior…   Reference: A case for putting off documentation until the end from our JCG partner Jerry Orr at the Jerry on Java blog. ...
software-development-2-logo

Peer reviews for security are a waste of time?

At this year’s RSA conference, one of the panel’s questioned whether software security is a waste of time. A panellist, John Viega, said a few things that I agreed with, and a lot that I didn’t. Especially that “peer reviews for security are a waste of time.” This statement is wrong on every level. Everyone should know by now that code reviews find real bugs – even informal, lightweight code reviews. “Reviews catch more than half of a product’s defects regardless of the domain, level of maturity of the organization, or lifecycle phase during which they were applied”. What We Have Learned About Fighting DefectsSoftware security vulnerabilities are like other software bugs – you find them through testing or through reviews. If peer code reviews are a good way to find bugs, why would they be a waste of time for finding security bugs? There are only a few developers anywhere who write security plumbing: authentication and session management, access control, password management, crypto and secrets handling. Or other kinds of plumbing like the data access layer and data encoding and validators that also have security consequences. All of this is the kind of kind of stuff that should be handled in frameworks anyway – if you’re writing this kind of code, you better have a good reason for doing it and you better know what you are doing. It’s obviously tricky and high-risk high-wire work, so unless you’re a team of one, your code and decisions need to be carefully reviewed by somebody else who is at least as smart as you are. If you don’t have anyone on the team who can review your work, then what the hell are you doing trying to write it in the first place? Everybody else has to be responsible for writing good, defensive application code. Their responsibilities are:Make sure their code works – that the logic is correct Use the framework properly Check input data and return values Handle errors and exceptions correctly Use safe routines/APIs/libraries Be careful with threading and locking and synchronizationA good developer can review this code for security and privacy requirements: making sure that you are masking or encrypting or – even better – not storing PII and secrets, auditing, properly following access control rules. And they can review the logic and workflow, look for race conditions, check data validation, make sure that error handling and exception handling is done right and that you are using frameworks and libraries carefully. This is what code reviews are for. To look for and find coding problems. If you find these problems – and code reviews are one of the most effective ways of doing this – your code will be safer and more secure. So I don’t get it. Why are peer reviews for security a waste of time?   Reference: Peer reviews for security are a waste of time? from our JCG partner Jim Bird at the Building Real Software blog. ...
mongodb-logo

MongoDB: Add A Counter With Spring Data

In my blog app, you can view any user’s profile, for example, my profile page will be http://www.jiwhiz.com/profile/user1, and ‘user1′ is my user Id in the system. In MongoDB, every document object will have a unique identifier, and often we store it as String, so I have a BaseEntity class for that:               @Document @SuppressWarnings('serial') public abstract class BaseEntity implements Serializable { @Id private String id; … } But the system generated id usually is very long, and I want to generate my own userId in my UserAccount class: @Document(collection = 'UserAccount') public class UserAccount extends BaseEntity implements SocialUserDetails { @Indexed private String userId;private UserRoleType[] roles;private String email;private String displayName;private String imageUrl;private String webSite; ... } The generated userId is very simple, just ‘user’ with a sequence number, for example, I’m the first user, so my userId is ‘User1′, and the next signed up user will be ‘User2′, etc. I want a sequence number generator from MongoDB to give me unique sequence numbers. The operations are to return current sequence number and also increase the sequence number in the database. In MongoDB, command findAndModify automatically modifies and returns a single document. So we can use this command to query the sequence number and increase it by $inc function. First we create a Counter class to store sequence numbers for different purposes, like userId: @SuppressWarnings('serial') @Document(collection = 'Counter') public class Counter extends BaseEntity{private String name;private long sequence;... } Since we will use counter in a special way, there is no need to have a repository. I just create a CounterService with the method to return the next user id: public interface CounterService { long getNextUserIdSequence(); } The implementation will use findAndModify to get next sequence: public class CounterServiceImpl implements CounterService { public static final String USER_ID_SEQUENCE_NAME = 'user_id';private final MongoTemplate mongoTemplate;@Inject public CounterServiceImpl(MongoTemplate mongoTemplate){ this.mongoTemplate = mongoTemplate; }@Override public long getNextUserIdSequence() { return increaseCounter(USER_ID_SEQUENCE_NAME); }private long increaseCounter(String counterName){ Query query = new Query(Criteria.where('name').is(counterName)); Update update = new Update().inc('sequence', 1); Counter counter = mongoTemplate.findAndModify(query, update, Counter.class); // return old Counter object return counter.getSequence(); } } Using this approach, you can add as many sequence as you want, just create a name for it. For example, you can record visits to your web site, so add a method like logVisit(), which calls the private method increaseCounter() with a name like ‘visit_num’. In this example, we don’t use Spring Data Repository for Counter document, but instead use MongoTemplate directly. From my MongoConfig class, which extends AbstractMongoConfiguration, which exposes MongoTemplate bean, we can easily inject MongoTemplate into other config bean, like CounterService: @Configuration class MainAppConfig { ... @Bean public CounterService counterService(MongoTemplate mongoTemplate) { return new CounterServiceImpl(mongoTemplate); } ... } Before you start running your app in any environment, you have to set up a Counter document first. Just type the following script in MongoDB shell: db.Counter.insert({ 'name' : 'user_id', sequence : 1}) OK, those are the steps to prepare a user id sequence generator. But how can we use it when we want to add a new user to our system? It becomes very easy now. We will have an AccountService, which has createUserAccount method, to create a new UserAccount when the user sign in for the first time. public interface AccountService extends SocialUserDetailsService, UserDetailsService, UserIdExtractor { UserAccount findByUserId(String userId);List<UserAccount> getAllUsers();List<UserSocialConnection> getConnectionsByUserId(String userId);UserAccount createUserAccount(ConnectionData data); } In our implementation class AccountServiceImpl, we can use CounterService, see highlighted code below: public class AccountServiceImpl implements AccountService { private final UserAccountRepository accountRepository; private final UserSocialConnectionRepository userSocialConnectionRepository; private final CounterService counterService;@Inject public AccountServiceImpl(UserAccountRepository accountRepository, UserSocialConnectionRepository userSocialConnectionRepository, CounterService counterService) { this.accountRepository = accountRepository; this.userSocialConnectionRepository = userSocialConnectionRepository; this.counterService = counterService; }@Override public UserAccount findByUserId(String userId) { return accountRepository.findByUserId(userId); }@Override public List<UserAccount> getAllUsers() { return accountRepository.findAll(); }@Override public List<UserSocialConnection> getConnectionsByUserId(String userId){ return this.userSocialConnectionRepository.findByUserId(userId); }@Override public UserAccount createUserAccount(ConnectionData data) { UserAccount account = new UserAccount(); account.setUserId('user' + this.counterService.getNextUserIdSequence()); account.setDisplayName(data.getDisplayName()); account.setImageUrl(data.getImageUrl()); account.setRoles(new UserRoleType[] { UserRoleType.ROLE_USER }); this.accountRepository.save(account); return account; }@Override public SocialUserDetails loadUserByUserId(String userId) throws UsernameNotFoundException, DataAccessException { UserAccount account = findByUserId(userId); if (account == null) { throw new UsernameNotFoundException('Cannot find user by userId ' + userId); } return account; }@Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { return loadUserByUserId(username); }@Override public String extractUserId(Authentication authentication) { if (authentication instanceof SocialAuthenticationToken) { SocialAuthenticationToken token = (SocialAuthenticationToken) authentication; if (token.getPrincipal() instanceof SocialUserDetails) { return ((SocialUserDetails) token.getPrincipal()).getUserId(); } } return null; }} The Java config code to glue them together for AccountService: @Configuration class MainAppConfig { ... @Bean public AccountService accountService(MongoTemplate mongoTemplate, UserAccountRepository accountRepository, UserSocialConnectionRepository userSocialConnectionRepository) { AccountServiceImpl service = new AccountServiceImpl(accountRepository, userSocialConnectionRepository, counterService(mongoTemplate)); return service; } ... } When do we call AccountService.createUserAccount()? At the time when a first time user tries to sign in, and the system cannot find an existing UserAccount, so the ConnectionSignUp bean plugged into MongoUsersConnectionRepository will be called. (See my previous post for other spring social connection related code.) So ConnectionSignUp will pass ConnectionData to AccountService.createUserAccount(): public class AutoConnectionSignUp implements ConnectionSignUp{ private final AccountService accountService;@Inject public AutoConnectionSignUp(AccountService accountService){ this.accountService = accountService; }public String execute(Connection<?> connection) { ConnectionData data = connection.createData();UserAccount account = this.accountService.createUserAccount(data);return account.getUserId(); } } My experience with Spring Data MongoDB is very positive. It is very powerful in providing basic CRUD functions as well as abundant query functions, and you don’t need to write any implementation code. If you have to use a special command of MongoDB, MongoTemplate is flexible enough to meet your requirements.   Reference: MongoDB: Add A CounterWithSpring Data from our JCG partner Yuan Ji at the Jiwhiz blog. ...
spring-interview-questions-answers

Add RememberMe Authentication With Spring Security

I mentioned in my post Add Social Login to Jiwhiz Blog that the RememberMe function was not working with Spring Social Security. Well, it is because the application is not authenticating the user by username and password now, and is totally depending on social websites (like Google, Facebook and Twitter) to do the job. The default Spring Security configuration cannot handle this situation. Spring Security might be the most complicated software among all Spring Portfolio projects. There are about 10 filters needing to be set up correctly to get a very simple Web application to work with security. To simplify application development, Spring Security provides namespace configuration since version 2.0 to automatically set up all the necessary components together, so developers don’t need to figure out the details. It works very well for most of the Web applications, unless your application is different from a traditional one. After I changed my website login process from username password authentication to Spring Social Security without a password, the old configuration for remember-me didn’t work anymore. The Spring Security Reference document has very few explanations about Remember-Me Authentication, so I bought the book Spring Security 3.1 written by Rob Winch, the project lead of Spring Security. The book has an entire chapter talking about Remember-Me Services, and it helped me a lot to understand how remember-me works in Spring Security. After reading the book, I feel it is much easier to read the Spring Security source code, and reading the source code is always enjoyable. Since I’m not storing passwords for users’ accounts, the default TokenBasedRememberMeServices cannot work with my application, and I don’t want to create my own RememberMeServices – too much work. Fortunately, there is another Persistent Token Approach, that is to store tokens into the database and compare tokens inside cookies. All I need is to customize PersistentTokenBasedRememberMeServices in my application with PersistentTokenRepository to store the tokens. Spring Security provides a JDBC implementation of PersistentTokenRepository, and I found it is trivial to write my own implementation for MongoDB after reading the source code. The first step is to store data of PersistentRememberMeToken to MongoDB. I need to add a domain entity class for it: @Document(collection = 'RememberMeToken') public class RememberMeToken extends BaseEntity{private String username;@Indexed private String series;private String tokenValue;private Date date;... // getter/setter omittedpublic RememberMeToken(){}public RememberMeToken(PersistentRememberMeToken token){ this.series = token.getSeries(); this.username = token.getUsername(); this.tokenValue = token.getTokenValue(); this.date = token.getDate(); }} Next, use Spring Data to add a repository for the entity: public interface RememberMeTokenRepository extends MongoRepository<RememberMeToken, String>{ RememberMeToken findBySeries(String series); List<RememberMeToken> findByUsername(String username); } Then the only relatively heavy coding is to implement PersistentTokenRepository for MongoDB: public class MongoPersistentTokenRepositoryImpl implements PersistentTokenRepository {private final RememberMeTokenRepository rememberMeTokenRepository;public MongoPersistentTokenRepositoryImpl(RememberMeTokenRepository rememberMeTokenRepository){ this.rememberMeTokenRepository = rememberMeTokenRepository; }@Override public void createNewToken(PersistentRememberMeToken token) { RememberMeToken newToken = new RememberMeToken(token); this.rememberMeTokenRepository.save(newToken); }@Override public void updateToken(String series, String tokenValue, Date lastUsed) { RememberMeToken token = this.rememberMeTokenRepository.findBySeries(series); if (token != null){ token.setTokenValue(tokenValue); token.setDate(lastUsed); this.rememberMeTokenRepository.save(token); }}@Override public PersistentRememberMeToken getTokenForSeries(String seriesId) { RememberMeToken token = this.rememberMeTokenRepository.findBySeries(seriesId); return new PersistentRememberMeToken(token.getUsername(), token.getSeries(), token.getTokenValue(), token.getDate()); }@Override public void removeUserTokens(String username) { List<RememberMeToken> tokens = this.rememberMeTokenRepository.findByUsername(username); this.rememberMeTokenRepository.delete(tokens); } } The rest of the work is all configuration. I need to wire them together in Java config class: @Configuration public class SocialAndSecurityConfig { @Inject private Environment environment;@Inject private AccountService accountService;@Inject private AuthenticationManager authenticationManager;@Inject private RememberMeTokenRepository rememberMeTokenRepository;...@Bean public RememberMeServices rememberMeServices(){ PersistentTokenBasedRememberMeServices rememberMeServices = new PersistentTokenBasedRememberMeServices( environment.getProperty('application.key'), accountService, persistentTokenRepository()); rememberMeServices.setAlwaysRemember(true); return rememberMeServices; }@Bean public RememberMeAuthenticationProvider rememberMeAuthenticationProvider(){ RememberMeAuthenticationProvider rememberMeAuthenticationProvider = new RememberMeAuthenticationProvider(environment.getProperty('application.key')); return rememberMeAuthenticationProvider; }@Bean public PersistentTokenRepository persistentTokenRepository() { return new MongoPersistentTokenRepositoryImpl(rememberMeTokenRepository); } } The last step is to add the remember-me service to security xml config file, which is the last piece of xml config and we cannot eliminate it now. (Update: a new project Spring Security Java Config will replace xml configuration with Java config in Spring Security.) <?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/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd'><http use-expressions='true' entry-point-ref='socialAuthenticationEntryPoint'> <custom-filter position='PRE_AUTH_FILTER' ref='socialAuthenticationFilter' /> <logout logout-url='/signout' delete-cookies='JSESSIONID' /> <remember-me services-ref='rememberMeServices' /> <!-- Configure these elements to secure URIs in your application --> <intercept-url pattern='http://a3ab771892fd198a96736e50.javacodegeeks.netdna-cdn.com/favicon.ico' access='permitAll' /> <intercept-url pattern='/robots.txt' access='permitAll' /> <intercept-url pattern='/resources/**' access='permitAll' /> <intercept-url pattern='/signin' access='permitAll' requires-channel='#{environment['application.secureChannel']}' /> <intercept-url pattern='/signin/*' access='permitAll' requires-channel='#{environment['application.secureChannel']}' /> <intercept-url pattern='/presentation/**' access='hasRole('ROLE_USER')' requires-channel='#{environment['application.secureChannel']}' /> <intercept-url pattern='/myAccount/**' access='hasRole('ROLE_USER')' requires-channel='#{environment['application.secureChannel']}' /> <intercept-url pattern='/myPost/**' access='hasRole('ROLE_AUTHOR')' requires-channel='#{environment['application.secureChannel']}' /> <intercept-url pattern='/admin/**' access='hasRole('ROLE_ADMIN')' requires-channel='#{environment['application.secureChannel']}' /> <intercept-url pattern='/**' access='permitAll' /></http><authentication-manager alias='authenticationManager'> <authentication-provider ref='socialAuthenticationProvider' /> <authentication-provider ref='rememberMeAuthenticationProvider' /> </authentication-manager></beans:beans> That’s all for adding Remember-Me Authentication to my blog application. Now you can login through Google/Facebook/Twitter to my website, and the website will consistently remember you for the next two weeks.   Reference: Add RememberMe Authentication With Spring Security from our JCG partner Yuan Ji at the Jiwhiz blog. ...
Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
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.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close