Wednesday, 23 September 2015

Connecting to a remote instance of SQL Server (Developer Edition 2014)

It's been a while since my last post! Less posts means less problems, right?

Recently I had to connect to a remote instance of SQL Server Developer Edition 2014 and it was harder than expected <insert Microsoft whining here>. The solution is quite simple but until you know it, it can be quite evasive.

Lets get straight to the point.

How to make it work?

First configure your instance.

On your Sql Server Configuration Manager enable Shared Memory and TCP/IP protocols (Named Pipes shouldn't be needed though):

Right-click TCP/IP and click Properties and scroll to the bottom of the new window. You can set the desired port there. You can see that I used 51672 at the bottom under TCP Dynamic Ports:

After this, make sure the port is open on your the firewall (I opened both TCP and UDP):

Configure it as below:
(And do the same for UDP)

Now restart your instance service:

It looks like you should be able to connect remotely now, but sadly that may not be the case. If you still can't connect, open your command prompt (press Windows Key + R) and type cmd:

And then type in the command netsh Winsock reset:


And voilĂ , it's working!

Wednesday, 19 August 2015

Ugh... "A different object with the same identifier value was already associated with the session"

nested exception is org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session If you see the above message, you're probably calling saveOrUpdate() (or something similar) somewhere in your code.
The root of the problem is usually somewhere before whatever line (of your code) the stacktrace reports, so you'll have to find and fix it.

In this post I'll talk about a little bit how hibernate deals with objects, what can make this problem appear and how you can list what hibernate currently has in it's session.

The problem and how to spot it

Often the problem is solved with a merge(), but you should know why it solves the problem (so that you know what you are doing). I'll try to provide a good summary to help you understand what is going on, but do look at Working with Objects in Hibernate Docs for more in-depth knowledge.

So what is merge() and why is it "solving" the problem?

First of all, I'd like to say that if you didn't have a merge() in that area of your code, then you probably don't want to put one there. I say "probably" because you're likely seeing this issue now whereas before you didn't. You know your code and you should be the judge of what should and shouldn't be done. However, keep in mind that if you found a solution but you don't know the problem, then you won't be sure if you are solving it without causing side-effects. It's a bit like 42.

Like I said before, you're seeing this NonUniqueObjectException because you are probably trying to call saveOrUpdate() on a detached object while you have a version of it attached to the hibernate session. There are a number of ways this can happen:
  • Fetched an object, changed it, saved it, changed it again and saved it a second time. (When a hibernate session is closed, the objects are detached from it but they remain in the application's memory, meaning you can still change them).
  • Created a new object newX that is equal to one that exists in the database (oldX), fetch oldX, then save the newX.
Modifying the detached object then calling saveOrUpdate() will confuse hibernate as it was not keeping track of the changes. Instead of assuming you want the detached object and (possibly) saving bad data, hibernate throws NonUniqueObjectException and lets you fix the problem.

Check if you have any of the scenarios above (double fetching, double edit+save or something else which can create two versions of the same persistent object).

How does merge() work?

You can use it to attach an object to the current hibernate session without any consideration for what is already there. If you have two instances of Object A with the same identifier*, then (a copy of) the object that you pass in to merge() will be re-attached to the session, saved and returned back to you. The previous object in the session will be discarded.
* meaning they are "the same" as far your persistent layer (aka database) is concerned


Excuse my terrible drawing skills.

Above is a very rough picture of what happens when you call merge() when you have a version of Object A in the session (blue) and another version of the same object in memory (green). After calling merge, it will put a copy of the green Object A into the session and return it back to you (yellow).

In practical terms, this means that merge() will make sure the current state of the object that you passed into it will be persisted.

How is it different from saveOrUpdate()?

Before you say "So merge() is what I wanted to use all along!", you should understand what is the difference between these two. The hibernate documentation kindly provides this information (transcribed below):
saveOrUpdate() does the following:
  • if the object is already persistent in this session, do nothing
  • if another object associated with the session has the same identifier, throw an exception
  • if the object has no identifier property, save() it
  • if the object's identifier has the value assigned to a newly instantiated object, save() it
  • if the object is versioned by a or , and the version property value is the same value assigned to a newly instantiated object, save() it
  • otherwise update() the object

and merge() is very different:
  • if there is a persistent instance with the same identifier currently associated with the session, copy the state of the given object onto the persistent instance
  • if there is no persistent instance currently associated with the session, try to load it from the database, or create a new persistent instance
  • the persistent instance is returned
  • the given instance does not become associated with the session, it remains detached

How do I know if the object in the session is different?

Regardless of which scenario you're experiencing, you can compare what you have currently in the session and what you have in memory.
It's somewhat easy to list all the objects inside a hibernate session and the code snippet below can be helpful when you're debugging your application. static class HibernateSessionUtils { public static Map listAllObjects(Session session){ SessionImplementor sessionImplementor = (SessionImplementor) session; StatefulPersistenceContext context = (StatefulPersistenceContext) sessionImplementor.getPersistenceContext(); return context.getEntitiesByKey(); } } then just use it like so Map hibernateObjectsMap = HibernateSessionUtils.listAllObjects(session)
Hopefully by comparing the two objects (the one in the session and the one you have), you'll find out what the problem is.

How do I fix it?

Finally, the part that matters.
After knowing what you're experiencing, you should know how to avoid it (and if you can avoid it). So first you should try to prevent double-fetching or double-(edit+save)
If you cannot avoid the scenarios above, then it could be safe to use merge() or you may just want to evict() one of the objects.


Now that you know a little bit more about this subject and you still think merge() is the way to go, then go ahead and use it: Object attachedObject = session.merge(detachedObject);
Happy coding!

Wednesday, 12 August 2015

Unwrapping objects by an attribute in Groovy (also, flattening maps of maps)

Groovy truly is groovy, but sometimes you need to add in a little bit of sparkle to make it do what you want while not losing it's Groovy look.
It's easy to flatten a list of lists with Groovy: you just call flatten() on it: assert ["a", "b", ["ca", "cb", "cc"], ["da", ["dba", "dbb"], "dc"], "e"].flatten() == ["a", "b", "ca", "cb", "cc", "da", "dba", "dbb", "dc", "e"] Sometimes you might want to do something that is kind of what Groovy already offers you but it's not really quite there. Luckily Groovy offers you the ability to alter the behaviour of some methods, in this particular situation, you can pass a closure to flatten().
I wanted to flatten a list of objects by one of their attributes (while ignoring the parent object). Consider the example below where I want to unpack all boxes which contain boxes inside (i.e. child-boxes) in order to get a list of boxes that only have stuff inside (i.e. no child-boxes). def boxes = [ [ name: "Bigass Box of Boxes", childBoxes:[ [ name: "Box of Stuff", childBoxes:[] ], [ name: "Small Empty Box", childBoxes:[] ], [ name: "Medium Box of Boxes", childBoxes:[ [ name: "Box of books", childBoxes:[] ] ] ] ] ], [ name: "Another Empty Box", childBoxes:[] ] ] assert boxes.flatten({it.childBoxes.isEmpty() ? it : it.childBoxes}) == [[name:"Box of Stuff", childBoxes:[]], [name:"Small Empty Box", childBoxes:[]], [name:"Box of books", childBoxes:[]], [name:"Another Empty Box", childBoxes:[]]] This is particularly useful for unwrapping objects (e.g. unnesting nodes).

Monday, 10 August 2015

Adding a logout listener in Grails and spring-security-core

Recently I've had to log certain activities the users were performing in an application. One particular action was logging out.
I'm using spring-security-core plugin to handle authentication and security.
I have done this in the past so I thought I better document this in a way that I don't have to dig up my old code from the annals of... well ~\dev\archived.

Taking advantage of Listeners

I don't want this cluttering my application logic and since Grails is a spring application, I turned my attention to ApplicationListeners. You could argue that I could have made use of filters but if the logout handler already emits an event when a user is successfully logged out, why not use it?
So, lets start our (short) implementation of this. First you will have to tell spring-security to publish http session events so that you can catch them later. In order to do so, add the following line to your grails-app/conf/Config.groovy:
grails.plugin.springsecurity.useHttpSessionEventPublisher = true
Now you have to implement your listener: import org.springframework.context.ApplicationListener import org.springframework.security.core.session.SessionDestroyedEvent public class MyLogoutEventListener implements ApplicationListener<SessionDestroyedEvent> { @Override public void onApplicationEvent(SessionDestroyedEvent event){ /*Your code here*/ } } (If you're not sure where to put it, place it in your src/groovy/ directory)
And then you need to register this bean in grails-app/conf/spring/resources.groovy beans = { myLogoutEventListener(MyLogoutEventListener) } Note: Your MyLogoutEventListener will listen for any SessionDestroyedEvent which means that when someone logs in, the listener will trigger as the anonymous session has been destroyed, so remember to check if the session is anonymous.

Thursday, 6 August 2015

Tomcat session mix-up hell (aka, RTFM)

Weirdness!

Recently I encountered a very strange issue where I would be logged out of an application in one tab if I opened a different instance of the same application (running on a different port but on the same machine) on another tab.

For clarity, this was my environment:
  • localhost
    • http://localhost:7224 → Application A1 on Tomcat T1 running with Java J1
    • http://localhost:8080 → Application A2 on Tomcat T2 running with Java J2

And what happened was this:
  1. Open A1 in Tab1
  2. Open A2 in Tab2
  3. Go to Tab1 and login to A1
  4. Go to Tab2 and refresh
  5. Go to Tab1 and refresh
  6. I am logged out from Tab1

WHAT?! But... how?

I am running two different instances on two different Tomcat containers using two different Javas?! Is there a leak somewhere? Unless... the problem is with the client. No. It couldn't be... could it?
I tried on other devices, other OSs, and other browsers... same thing. Ok, this must be something the server is sending back.

How I cursed at my computer.

Overnight I kept thinking about this and I realised I had this problem in my previous company. It wasn't the same but it was slightly similar but I remembered it had something to do with cookies.
Cookies are domain-specific (I was using localhost for both), this means they wouldn't care about ports. This was a good clue

The next morning I checked my StackOverflow question and Emmanuel Rosa had the courtesy of reminding my that Grails (well, the container) uses cookies to store session IDs.

RIGHT!

With Chrome, if you open Developer Tools → Resources Tab → Cookies you should see this:


According to the Tomcat 8 documentation there's an attribute called sessionCookieName which could be used to solve this.

So, how to fix it?

To address this issue, you'd have to make both apps stop competing for the JSESSIONID name. For Tomcat 8, if you look in {tomcat}/conf/context.xml the <Context> node is probably empty. This makes the session cookie name default to SESSIONID. The solution is to explicitly set sessionCookieName. After you do that change you should see something like below: <?xml version='1.0' encoding='utf-8'?> <Context sessionCookieName="APPNAMESESSIONID8080"> <WatchedResource>WEB-INF/web.xml>/WatchedResource> <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource> </Context> And you'd make a similar change for the other application: <?xml version='1.0' encoding='utf-8'?> <Context sessionCookieName="APPNAMESESSIONID7224"> <WatchedResource>WEB-INF/web.xml>/WatchedResource> <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource> </Context> I used DASHBOARDSESSIONID<portname> (as you can see in the screenshot below)
If you have another look at your developer tools, you should see that the issue is now gone (you may see the left-over JSESSIONID but that is ok. Your application will ignore it).

Hello World

Heh, typical title I guess.

I'm writing this for future reference in case I re-encounter issues, I'll have a place where I'm documenting these things... also the internet is a good place to rant.

Hopefully this is as useful to me as it is to you.