Same session for different calls? (Causing problem with Hibernate Filters)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

Same session for different calls? (Causing problem with Hibernate Filters)

Felipe Cypriano
Hello,

This is the first time I'm using Hibernate Filters and I'm using the withSession method from the domain classes to get the underlaying session to enable the filters, like this:

DomainClass.withSession { session ->
    if (someBussinessCondition) {
        session.enableFilter("myFilter")
    }
    // do the query
}

If I first call the method that executes the above code with someBussinessCondition = true the filter get enabled, that's ok. But after this call if I do another one with someBussinessCondition = false, the code that enables the filter isn't executed but the result is filtered. Seems like the session is shared between the calls.

It should be a new session for each call, shouldn't?

Regards,
---
Felipe Cypriano
Reply | Threaded
Open this post in threaded view
|

Re: Same session for different calls? (Causing problem with Hibernate Filters)

corey_s
On Thursday 04 June 2009 13:37:40 Felipe Cypriano wrote:

> Hello,
>
> This is the first time I'm using Hibernate Filters and I'm using the
> withSession method from the domain classes to get the underlaying session
> to enable the filters, like this:
>
> DomainClass.withSession { session ->
>     if (someBussinessCondition) {
>         session.enableFilter("myFilter")
>     }
>     // do the query
> }
>
> If I first call the method that executes the above code with
> someBussinessCondition = true the filter get enabled, that's ok. But after
> this call if I do another one with someBussinessCondition = false, the code
> that enables the filter isn't executed but the result is filtered. Seems
> like the session is shared between the calls.
>

Yeah, one session is shared for the entire thread - when you use
withSession(), it's just supplying the thread's session; not creating a
new one.

> It should be a new session for each call, shouldn't?
>

I'd also be interested in knowing how to initiatiate a new session within the
same thread.





---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: Same session for different calls? (Causing problem with Hibernate Filters)

burtbeckwith
In reply to this post by Felipe Cypriano
The OpenSessionInView interceptor opens a Hibernate session at the start of each request and closes it after the request is finished. withSession() looks up the thread-local session and uses it, so you'll get the same session for each withSession() call.


Burt


On Thursday 04 June 2009 4:37:40 pm Felipe Cypriano wrote:
> Hello,
>
> This is the first time I'm using Hibernate Filters and I'm using the
> withSession method from the domain classes to get the underlaying session to
> enable the filters, like this:
>
> DomainClass.withSession { session ->
> if (someBussinessCondition) {
> session.enableFilter("myFilter")
> }
> // do the query
> }
>
> If I first call the method that executes the above code with
> someBussinessCondition = true the filter get enabled, that's ok. But after
> this call if I do another one with someBussinessCondition = false, the code
> that enables the filter isn't executed but the result is filtered. Seems
> like the session is shared between the calls.
>
> It should be a new session for each call, shouldn't?
>
> Regards,
> ---
> Felipe Cypriano
>



signature.asc (204 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Same session for different calls? (Causing problem with Hibernate Filters)

Felipe Cypriano
In reply to this post by corey_s
That's why it's happening with the integration tests, they're all executed in the same thread. Use withSession could be a problem when the app is running and processing http requests?

Also, how could I guarantee (create) a new session for each call?

---
Felipe Cypriano


On Thu, Jun 4, 2009 at 5:42 PM, Corey <[hidden email]> wrote:
On Thursday 04 June 2009 13:37:40 Felipe Cypriano wrote:
> Hello,
>
> This is the first time I'm using Hibernate Filters and I'm using the
> withSession method from the domain classes to get the underlaying session
> to enable the filters, like this:
>
> DomainClass.withSession { session ->
>     if (someBussinessCondition) {
>         session.enableFilter("myFilter")
>     }
>     // do the query
> }
>
> If I first call the method that executes the above code with
> someBussinessCondition = true the filter get enabled, that's ok. But after
> this call if I do another one with someBussinessCondition = false, the code
> that enables the filter isn't executed but the result is filtered. Seems
> like the session is shared between the calls.
>

Yeah, one session is shared for the entire thread - when you use
withSession(), it's just supplying the thread's session; not creating a
new one.

> It should be a new session for each call, shouldn't?
>

I'd also be interested in knowing how to initiatiate a new session within the
same thread.





---------------------------------------------------------------------
To unsubscribe from this list, please visit:

   http://xircles.codehaus.org/manage_email



Reply | Threaded
Open this post in threaded view
|

Re: Same session for different calls? (Causing problem with Hibernate Filters)

burtbeckwith
In reply to this post by corey_s
You should be able to get a new session using the session factory, e.g


def sessionFactory // dependency-injection
...
def newSession = sessionFactory.openSession()


I haven't tried this but from looking at the code it should bypass the thread-local session and create a new one with a new connection. Easy enough to test though:


DomainClass.withSession { session ->
println "new Session: $newSession, old Session: $session, same: ${session.is(newSession)}"
}


Burt


On Thursday 04 June 2009 4:42:48 pm Corey wrote:
> On Thursday 04 June 2009 13:37:40 Felipe Cypriano wrote:
> > Hello,
> >
> > This is the first time I'm using Hibernate Filters and I'm using the
> > withSession method from the domain classes to get the underlaying session
> > to enable the filters, like this:
> >
> > DomainClass.withSession { session ->
> > if (someBussinessCondition) {
> > session.enableFilter("myFilter")
> > }
> > // do the query
> > }
> >
> > If I first call the method that executes the above code with
> > someBussinessCondition = true the filter get enabled, that's ok. But after
> > this call if I do another one with someBussinessCondition = false, the code
> > that enables the filter isn't executed but the result is filtered. Seems
> > like the session is shared between the calls.
> >
>
> Yeah, one session is shared for the entire thread - when you use
> withSession(), it's just supplying the thread's session; not creating a
> new one.
>
> > It should be a new session for each call, shouldn't?
> >
>
> I'd also be interested in knowing how to initiatiate a new session within the
> same thread.



signature.asc (204 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Same session for different calls? (Causing problem with Hibernate Filters)

Felipe Cypriano
Hi Burt,

The tip with sessionFactory doesn't work, at least with integration tests, I'm getting "Cannot invoke method openSession() on null object".

And seems like doing this isn't a good a way to solve the problem, since I'm implementing things that are specific for integration tests and aren't need in production, is there a better solution to solve the problem with integration tests or this is the best one?

Regards,
---
Felipe Cypriano


On Thu, Jun 4, 2009 at 5:49 PM, Burt Beckwith <[hidden email]> wrote:
You should be able to get a new session using the session factory, e.g


def sessionFactory // dependency-injection
...
def newSession = sessionFactory.openSession()


I haven't tried this but from looking at the code it should bypass the thread-local session and create a new one with a new connection. Easy enough to test though:


DomainClass.withSession { session ->
println "new Session: $newSession, old Session: $session, same: ${session.is(newSession)}"
}


Burt


On Thursday 04 June 2009 4:42:48 pm Corey wrote:
> On Thursday 04 June 2009 13:37:40 Felipe Cypriano wrote:
> > Hello,
> >
> > This is the first time I'm using Hibernate Filters and I'm using the
> > withSession method from the domain classes to get the underlaying session
> > to enable the filters, like this:
> >
> > DomainClass.withSession { session ->
> > if (someBussinessCondition) {
> > session.enableFilter("myFilter")
> > }
> > // do the query
> > }
> >
> > If I first call the method that executes the above code with
> > someBussinessCondition = true the filter get enabled, that's ok. But after
> > this call if I do another one with someBussinessCondition = false, the code
> > that enables the filter isn't executed but the result is filtered. Seems
> > like the session is shared between the calls.
> >
>
> Yeah, one session is shared for the entire thread - when you use
> withSession(), it's just supplying the thread's session; not creating a
> new one.
>
> > It should be a new session for each call, shouldn't?
> >
>
> I'd also be interested in knowing how to initiatiate a new session within the
> same thread.



Reply | Threaded
Open this post in threaded view
|

Re: Same session for different calls? (Causing problem with Hibernate Filters)

burtbeckwith
Are you using dependency injection, or declaring sessionFactory in the test method? It needs to be class-scope to be injected. This test passes:

   class FooTests extends GroovyTestCase {

      def sessionFactory

      void testSomething() {
         println "sessionFactory: $sessionFactory"
         assertNotNull sessionFactory
 
         Foo.withSession { session ->
            def newSession = sessionFactory.openSession()
            println "new Session: $newSession, old Session: $session, same: ${session.is(newSession)}"
            assertNotSame session, newSession
         }
      }
   }

But the integration test environment isn't that similar to the runtime environment. There's no OSIV interceptor, each test method is run in a transaction that's rolled back during tearDown() (unless the whole test class defines "boolean transactional = false" which can break other tests if not used correctly), etc.

If you want something that's close to runtime behavior you should look at functional testing.

Burt

On Thursday 04 June 2009 4:57:46 pm Felipe Cypriano wrote:

> Hi Burt,
>
> The tip with sessionFactory doesn't work, at least with integration tests,
> I'm getting "Cannot invoke method openSession() on null object".
>
> And seems like doing this isn't a good a way to solve the problem, since I'm
> implementing things that are specific for integration tests and aren't need
> in production, is there a better solution to solve the problem with
> integration tests or this is the best one?
>
> Regards,
> ---
> Felipe Cypriano
>
>
> On Thu, Jun 4, 2009 at 5:49 PM, Burt Beckwith <[hidden email]> wrote:
>
> > You should be able to get a new session using the session factory, e.g
> >
> >
> > def sessionFactory // dependency-injection
> > ...
> > def newSession = sessionFactory.openSession()
> >
> >
> > I haven't tried this but from looking at the code it should bypass the
> > thread-local session and create a new one with a new connection. Easy enough
> > to test though:
> >
> >
> > DomainClass.withSession { session ->
> > println "new Session: $newSession, old Session: $session, same: ${
> > session.is(newSession)}"
> > }
> >
> >
> > Burt
> >
> >
> > On Thursday 04 June 2009 4:42:48 pm Corey wrote:
> > > On Thursday 04 June 2009 13:37:40 Felipe Cypriano wrote:
> > > > Hello,
> > > >
> > > > This is the first time I'm using Hibernate Filters and I'm using the
> > > > withSession method from the domain classes to get the underlaying
> > session
> > > > to enable the filters, like this:
> > > >
> > > > DomainClass.withSession { session ->
> > > > if (someBussinessCondition) {
> > > > session.enableFilter("myFilter")
> > > > }
> > > > // do the query
> > > > }
> > > >
> > > > If I first call the method that executes the above code with
> > > > someBussinessCondition = true the filter get enabled, that's ok. But
> > after
> > > > this call if I do another one with someBussinessCondition = false, the
> > code
> > > > that enables the filter isn't executed but the result is filtered.
> > Seems
> > > > like the session is shared between the calls.
> > > >
> > >
> > > Yeah, one session is shared for the entire thread - when you use
> > > withSession(), it's just supplying the thread's session; not creating a
> > > new one.
> > >
> > > > It should be a new session for each call, shouldn't?
> > > >
> > >
> > > I'd also be interested in knowing how to initiatiate a new session within
> > the
> > > same thread.
> >
> >
> >
>

signature.asc (204 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Same session for different calls? (Causing problem with Hibernate Filters)

corey_s
In reply to this post by burtbeckwith
On Thursday 04 June 2009 13:49:17 Burt Beckwith wrote:
> You should be able to get a new session using the session factory, e.g
>
>    def sessionFactory // dependency-injection
>    ...
>    def newSession = sessionFactory.openSession()
>
> I haven't tried this but from looking at the code it should bypass the
> thread-local session and create a new one with a new connection.
>

Apologies if this is a stupid question, but once you have reference to a
new session, how do you go about operating within it? Such as performing
a query, or calling a domain instance's save()/update()/delete(), etc...


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: Same session for different calls? (Causing problem with Hibernate Filters)

burtbeckwith
You'd use it like in a non-Grails app, i.e.

   def allThings = session.createQuery('from Thing').list()

Another option is to use Spring's HibernateTemplate with alwaysUseNewSession = true, e.g.

   def template = new HibernateTemplate(sessionFactory)
   template.alwaysUseNewSession = true
   def allThings = template.find('from Thing')

GORM uses HibernateTemplate under the hood btw.

Burt

On Thursday 04 June 2009 6:00:21 pm Corey wrote:

> On Thursday 04 June 2009 13:49:17 Burt Beckwith wrote:
> > You should be able to get a new session using the session factory, e.g
> >
> >    def sessionFactory // dependency-injection
> >    ...
> >    def newSession = sessionFactory.openSession()
> >
> > I haven't tried this but from looking at the code it should bypass the
> > thread-local session and create a new one with a new connection.
> >
>
> Apologies if this is a stupid question, but once you have reference to a
> new session, how do you go about operating within it? Such as performing
> a query, or calling a domain instance's save()/update()/delete(), etc...


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: Same session for different calls? (Causing problem with Hibernate Filters)

corey_s
On Thursday 04 June 2009 15:54:35 Burt Beckwith wrote:

> You'd use it like in a non-Grails app, i.e.
>
>    def allThings = session.createQuery('from Thing').list()
>
> Another option is to use Spring's HibernateTemplate with
> alwaysUseNewSession = true, e.g.
>
>    def template = new HibernateTemplate(sessionFactory)
>    template.alwaysUseNewSession = true
>    def allThings = template.find('from Thing')
>

Excellent, thanks!


> GORM uses HibernateTemplate under the hood btw.
>

Good to know.


Cheers



---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: Same session for different calls? (Causing problem with Hibernate Filters)

Felipe Cypriano
In reply to this post by burtbeckwith
I'm declaring it in the class scope, just like you show. I'll explain more about what I'm trying to do and what I'm trying to test.

I've an interface that defines some methods about to get the stock of a product, for example:

public interface IStockService {
    public Set<Stock> findAllStock(Produto produto);
    public Set<Stock> findAllStockAvailable(Produto produto);
}

The first method returns all records, and the second method should return only the items which has more than zero in it's quantity property. Both methods uses the same query but the second enables the availability filter, so to obey the interface no matters who  nor what environment is calling the methods should be behave as the interface dictates, right?

This is a implementation's code:
public class StockService implements IStockService {
    // def sessionFactory // here is what I put the sessionFactory to test

    public Set<Stock> findAllStock(Produto produto) {
        loadStock(produto, false)
    }

    public Set<Stock> findAllStockAvailable(Produto produto) {
        loadStock(produto, true)
    }

    private Set<Stock> loadStock(Produto produto, boolean quantityMoreThanZero) {
        Set<Stock> resultado = new HashSet<Stock>()
        if (produto) {
            Estoque.withSession { session ->
                // ... some other filter that are always activated, at least to this method not all services ...
                if (quantityMoreThanZero) {
                    session.enableFilter("quantityMoreThanZero")
                }

                List<Estoque> list = Estoque.findAllByProduto(produto)
                if (list?.size() > 0) {
                    resultado.addAll(list)
                }
            }
        }
        return resultado
    }

}

The problem is when I call the findAllStockAvailable before calling the findAllStock, the result of the second call is also filtered and it shouldn't be, do you agree?

Now the integration test:
public class StockServiceTests extends GroovyTestCase {
    private IStockService stockService

    protected void setUp() {
        super.setUp()
        stockService = new StockService()
    }

    void testFindAllStockAvailable() {
        def resultados = stockService.findAllStockAvailable(produtoVariasCores)
        assertEquals("Filtered result should return 2", 2, resultados.size())
    }

    void testFindAllStock() {
        def resultados = stockService.findAllStock(produtoVariasCores)
        assertEquals("Should be 3, because it's not filtered'", 3, resultados.size())
    }

   // There's more tests that uses both methods
}

Do you think I'm using integration tests in a wrong way? Am I supposing anything that isn't correctly?


Regards,
---
Felipe Cypriano

P.S. I've translated some names in the code, but don't botter if I miss anyone and the code wouldn't work because of wrong names.

On Thu, Jun 4, 2009 at 6:30 PM, Burt Beckwith <[hidden email]> wrote:
Are you using dependency injection, or declaring sessionFactory in the test method? It needs to be class-scope to be injected. This test passes:

  class FooTests extends GroovyTestCase {

     def sessionFactory

     void testSomething() {
        println "sessionFactory: $sessionFactory"
        assertNotNull sessionFactory

        Foo.withSession { session ->
           def newSession = sessionFactory.openSession()
           println "new Session: $newSession, old Session: $session, same: ${session.is(newSession)}"
           assertNotSame session, newSession
        }
     }
  }

But the integration test environment isn't that similar to the runtime environment. There's no OSIV interceptor, each test method is run in a transaction that's rolled back during tearDown() (unless the whole test class defines "boolean transactional = false" which can break other tests if not used correctly), etc.

If you want something that's close to runtime behavior you should look at functional testing.

Burt

On Thursday 04 June 2009 4:57:46 pm Felipe Cypriano wrote:
> Hi Burt,
>
> The tip with sessionFactory doesn't work, at least with integration tests,
> I'm getting "Cannot invoke method openSession() on null object".
>
> And seems like doing this isn't a good a way to solve the problem, since I'm
> implementing things that are specific for integration tests and aren't need
> in production, is there a better solution to solve the problem with
> integration tests or this is the best one?
>
> Regards,
> ---
> Felipe Cypriano
>
>
> On Thu, Jun 4, 2009 at 5:49 PM, Burt Beckwith <[hidden email]> wrote:
>
> > You should be able to get a new session using the session factory, e.g
> >
> >
> > def sessionFactory // dependency-injection
> > ...
> > def newSession = sessionFactory.openSession()
> >
> >
> > I haven't tried this but from looking at the code it should bypass the
> > thread-local session and create a new one with a new connection. Easy enough
> > to test though:
> >
> >
> > DomainClass.withSession { session ->
> > println "new Session: $newSession, old Session: $session, same: ${
> > session.is(newSession)}"
> > }
> >
> >
> > Burt
> >
> >
> > On Thursday 04 June 2009 4:42:48 pm Corey wrote:
> > > On Thursday 04 June 2009 13:37:40 Felipe Cypriano wrote:
> > > > Hello,
> > > >
> > > > This is the first time I'm using Hibernate Filters and I'm using the
> > > > withSession method from the domain classes to get the underlaying
> > session
> > > > to enable the filters, like this:
> > > >
> > > > DomainClass.withSession { session ->
> > > > if (someBussinessCondition) {
> > > > session.enableFilter("myFilter")
> > > > }
> > > > // do the query
> > > > }
> > > >
> > > > If I first call the method that executes the above code with
> > > > someBussinessCondition = true the filter get enabled, that's ok. But
> > after
> > > > this call if I do another one with someBussinessCondition = false, the
> > code
> > > > that enables the filter isn't executed but the result is filtered.
> > Seems
> > > > like the session is shared between the calls.
> > > >
> > >
> > > Yeah, one session is shared for the entire thread - when you use
> > > withSession(), it's just supplying the thread's session; not creating a
> > > new one.
> > >
> > > > It should be a new session for each call, shouldn't?
> > > >
> > >
> > > I'd also be interested in knowing how to initiatiate a new session within
> > the
> > > same thread.
> >
> >
> >
>

Reply | Threaded
Open this post in threaded view
|

Re: Same session for different calls? (Causing problem with Hibernate Filters)

Felipe Cypriano
It would be possible to implement a interceptor that is loaded only in test environment to correct this problem?

Regards,
---
Felipe Cypriano


On Fri, Jun 5, 2009 at 8:59 AM, Felipe Cypriano <[hidden email]> wrote:
I'm declaring it in the class scope, just like you show. I'll explain more about what I'm trying to do and what I'm trying to test.

I've an interface that defines some methods about to get the stock of a product, for example:

public interface IStockService {
    public Set<Stock> findAllStock(Produto produto);
    public Set<Stock> findAllStockAvailable(Produto produto);
}

The first method returns all records, and the second method should return only the items which has more than zero in it's quantity property. Both methods uses the same query but the second enables the availability filter, so to obey the interface no matters who  nor what environment is calling the methods should be behave as the interface dictates, right?

This is a implementation's code:
public class StockService implements IStockService {
    // def sessionFactory // here is what I put the sessionFactory to test

    public Set<Stock> findAllStock(Produto produto) {
        loadStock(produto, false)
    }

    public Set<Stock> findAllStockAvailable(Produto produto) {
        loadStock(produto, true)
    }

    private Set<Stock> loadStock(Produto produto, boolean quantityMoreThanZero) {
        Set<Stock> resultado = new HashSet<Stock>()
        if (produto) {
            Estoque.withSession { session ->
                // ... some other filter that are always activated, at least to this method not all services ...
                if (quantityMoreThanZero) {
                    session.enableFilter("quantityMoreThanZero")
                }

                List<Estoque> list = Estoque.findAllByProduto(produto)
                if (list?.size() > 0) {
                    resultado.addAll(list)
                }
            }
        }
        return resultado
    }

}

The problem is when I call the findAllStockAvailable before calling the findAllStock, the result of the second call is also filtered and it shouldn't be, do you agree?

Now the integration test:
public class StockServiceTests extends GroovyTestCase {
    private IStockService stockService

    protected void setUp() {
        super.setUp()
        stockService = new StockService()
    }

    void testFindAllStockAvailable() {
        def resultados = stockService.findAllStockAvailable(produtoVariasCores)
        assertEquals("Filtered result should return 2", 2, resultados.size())
    }

    void testFindAllStock() {
        def resultados = stockService.findAllStock(produtoVariasCores)
        assertEquals("Should be 3, because it's not filtered'", 3, resultados.size())
    }

   // There's more tests that uses both methods
}

Do you think I'm using integration tests in a wrong way? Am I supposing anything that isn't correctly?


Regards,
---
Felipe Cypriano

P.S. I've translated some names in the code, but don't botter if I miss anyone and the code wouldn't work because of wrong names.


On Thu, Jun 4, 2009 at 6:30 PM, Burt Beckwith <[hidden email]> wrote:
Are you using dependency injection, or declaring sessionFactory in the test method? It needs to be class-scope to be injected. This test passes:

  class FooTests extends GroovyTestCase {

     def sessionFactory

     void testSomething() {
        println "sessionFactory: $sessionFactory"
        assertNotNull sessionFactory

        Foo.withSession { session ->
           def newSession = sessionFactory.openSession()
           println "new Session: $newSession, old Session: $session, same: ${session.is(newSession)}"
           assertNotSame session, newSession
        }
     }
  }

But the integration test environment isn't that similar to the runtime environment. There's no OSIV interceptor, each test method is run in a transaction that's rolled back during tearDown() (unless the whole test class defines "boolean transactional = false" which can break other tests if not used correctly), etc.

If you want something that's close to runtime behavior you should look at functional testing.

Burt

On Thursday 04 June 2009 4:57:46 pm Felipe Cypriano wrote:
> Hi Burt,
>
> The tip with sessionFactory doesn't work, at least with integration tests,
> I'm getting "Cannot invoke method openSession() on null object".
>
> And seems like doing this isn't a good a way to solve the problem, since I'm
> implementing things that are specific for integration tests and aren't need
> in production, is there a better solution to solve the problem with
> integration tests or this is the best one?
>
> Regards,
> ---
> Felipe Cypriano
>
>
> On Thu, Jun 4, 2009 at 5:49 PM, Burt Beckwith <[hidden email]> wrote:
>
> > You should be able to get a new session using the session factory, e.g
> >
> >
> > def sessionFactory // dependency-injection
> > ...
> > def newSession = sessionFactory.openSession()
> >
> >
> > I haven't tried this but from looking at the code it should bypass the
> > thread-local session and create a new one with a new connection. Easy enough
> > to test though:
> >
> >
> > DomainClass.withSession { session ->
> > println "new Session: $newSession, old Session: $session, same: ${
> > session.is(newSession)}"
> > }
> >
> >
> > Burt
> >
> >
> > On Thursday 04 June 2009 4:42:48 pm Corey wrote:
> > > On Thursday 04 June 2009 13:37:40 Felipe Cypriano wrote:
> > > > Hello,
> > > >
> > > > This is the first time I'm using Hibernate Filters and I'm using the
> > > > withSession method from the domain classes to get the underlaying
> > session
> > > > to enable the filters, like this:
> > > >
> > > > DomainClass.withSession { session ->
> > > > if (someBussinessCondition) {
> > > > session.enableFilter("myFilter")
> > > > }
> > > > // do the query
> > > > }
> > > >
> > > > If I first call the method that executes the above code with
> > > > someBussinessCondition = true the filter get enabled, that's ok. But
> > after
> > > > this call if I do another one with someBussinessCondition = false, the
> > code
> > > > that enables the filter isn't executed but the result is filtered.
> > Seems
> > > > like the session is shared between the calls.
> > > >
> > >
> > > Yeah, one session is shared for the entire thread - when you use
> > > withSession(), it's just supplying the thread's session; not creating a
> > > new one.
> > >
> > > > It should be a new session for each call, shouldn't?
> > > >
> > >
> > > I'd also be interested in knowing how to initiatiate a new session within
> > the
> > > same thread.
> >
> >
> >
>


Reply | Threaded
Open this post in threaded view
|

Re: Same session for different calls? (Causing problem with Hibernate Filters)

burtbeckwith
Shouldn't you disable the filter?

   if (quantityMoreThanZero) {
      session.enableFilter("quantityMoreThanZero")
   }
   else {
      session.disableFilter("quantityMoreThanZero")
   }

This should have no effect if it's not enabled, and will fix the issue where you enable it and then make the call a second time in the same session after enabling it.

Burt

On Friday 05 June 2009 1:07:37 pm Felipe Cypriano wrote:

> It would be possible to implement a interceptor that is loaded only in test
> environment to correct this problem?
>
> Regards,
> ---
> Felipe Cypriano
>
>
> On Fri, Jun 5, 2009 at 8:59 AM, Felipe Cypriano <[hidden email]>wrote:
>
> > I'm declaring it in the class scope, just like you show. I'll explain more
> > about what I'm trying to do and what I'm trying to test.
> >
> > I've an interface that defines some methods about to get the stock of a
> > product, for example:
> >
> > public interface IStockService {
> >     public Set<Stock> findAllStock(Produto produto);
> >     public Set<Stock> findAllStockAvailable(Produto produto);
> > }
> >
> > The first method returns all records, and the second method should return
> > only the items which has more than zero in it's quantity property. Both
> > methods uses the same query but the second enables the availability filter,
> > so to obey the interface no matters who  nor what environment is calling the
> > methods should be behave as the interface dictates, right?
> >
> > This is a implementation's code:
> > public class StockService implements IStockService {
> >     // def sessionFactory // here is what I put the sessionFactory to test
> >
> >     public Set<Stock> findAllStock(Produto produto) {
> >         loadStock(produto, false)
> >     }
> >
> >     public Set<Stock> findAllStockAvailable(Produto produto) {
> >         loadStock(produto, true)
> >     }
> >
> >     private Set<Stock> loadStock(Produto produto, boolean
> > quantityMoreThanZero) {
> >         Set<Stock> resultado = new HashSet<Stock>()
> >         if (produto) {
> >             Estoque.withSession { session ->
> >                 // ... some other filter that are always activated, at
> > least to this method not all services ...
> >                 if (quantityMoreThanZero) {
> >                     session.enableFilter("quantityMoreThanZero")
> >                 }
> >
> >                 List<Estoque> list = Estoque.findAllByProduto(produto)
> >                 if (list?.size() > 0) {
> >                     resultado.addAll(list)
> >                 }
> >             }
> >         }
> >         return resultado
> >     }
> >
> > }
> >
> > The problem is when I call the findAllStockAvailable before calling the
> > findAllStock, the result of the second call is also filtered and it
> > shouldn't be, do you agree?
> >
> > Now the integration test:
> > public class StockServiceTests extends GroovyTestCase {
> >     private IStockService stockService
> >
> >     protected void setUp() {
> >         super.setUp()
> >         stockService = new StockService()
> >     }
> >
> >     void testFindAllStockAvailable() {
> >         def resultados =
> > stockService.findAllStockAvailable(produtoVariasCores)
> >         assertEquals("Filtered result should return 2", 2,
> > resultados.size())
> >     }
> >
> >     void testFindAllStock() {
> >         def resultados = stockService.findAllStock(produtoVariasCores)
> >         assertEquals("Should be 3, because it's not filtered'", 3,
> > resultados.size())
> >     }
> >
> >    // There's more tests that uses both methods
> > }
> >
> > Do you think I'm using integration tests in a wrong way? Am I supposing
> > anything that isn't correctly?
> >
> >
> > Regards,
> > ---
> > Felipe Cypriano
> >
> > P.S. I've translated some names in the code, but don't botter if I miss
> > anyone and the code wouldn't work because of wrong names.

signature.asc (204 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Same session for different calls? (Causing problem with Hibernate Filters)

Felipe Cypriano
I think about it, but take a look at this line:
>> Estoque.withSession { session ->
> >                 // ... some other filter that are always activated, at least to this method not all services ...

All theses other filters that are enable for this service, but aren't necessary by the other services will still be enabled. This solution in the future will cause hard to find problems, for example, how would the (other) service knows what filters to disable?

I tried to find some method to disable all filters but I couldn't find. Do you think the interceptor approach is feasible?

Regards,
---
Felipe Cypriano


On Fri, Jun 5, 2009 at 2:18 PM, Burt Beckwith <[hidden email]> wrote:
Shouldn't you disable the filter?

  if (quantityMoreThanZero) {
     session.enableFilter("quantityMoreThanZero")
  }
  else {
     session.disableFilter("quantityMoreThanZero")
  }

This should have no effect if it's not enabled, and will fix the issue where you enable it and then make the call a second time in the same session after enabling it.

Burt

On Friday 05 June 2009 1:07:37 pm Felipe Cypriano wrote:
> It would be possible to implement a interceptor that is loaded only in test
> environment to correct this problem?
>
> Regards,
> ---
> Felipe Cypriano
>
>
> On Fri, Jun 5, 2009 at 8:59 AM, Felipe Cypriano <[hidden email]>wrote:
>
> > I'm declaring it in the class scope, just like you show. I'll explain more
> > about what I'm trying to do and what I'm trying to test.
> >
> > I've an interface that defines some methods about to get the stock of a
> > product, for example:
> >
> > public interface IStockService {
> >     public Set<Stock> findAllStock(Produto produto);
> >     public Set<Stock> findAllStockAvailable(Produto produto);
> > }
> >
> > The first method returns all records, and the second method should return
> > only the items which has more than zero in it's quantity property. Both
> > methods uses the same query but the second enables the availability filter,
> > so to obey the interface no matters who  nor what environment is calling the
> > methods should be behave as the interface dictates, right?
> >
> > This is a implementation's code:
> > public class StockService implements IStockService {
> >     // def sessionFactory // here is what I put the sessionFactory to test
> >
> >     public Set<Stock> findAllStock(Produto produto) {
> >         loadStock(produto, false)
> >     }
> >
> >     public Set<Stock> findAllStockAvailable(Produto produto) {
> >         loadStock(produto, true)
> >     }
> >
> >     private Set<Stock> loadStock(Produto produto, boolean
> > quantityMoreThanZero) {
> >         Set<Stock> resultado = new HashSet<Stock>()
> >         if (produto) {
> >             Estoque.withSession { session ->
> >                 // ... some other filter that are always activated, at
> > least to this method not all services ...
> >                 if (quantityMoreThanZero) {
> >                     session.enableFilter("quantityMoreThanZero")
> >                 }
> >
> >                 List<Estoque> list = Estoque.findAllByProduto(produto)
> >                 if (list?.size() > 0) {
> >                     resultado.addAll(list)
> >                 }
> >             }
> >         }
> >         return resultado
> >     }
> >
> > }
> >
> > The problem is when I call the findAllStockAvailable before calling the
> > findAllStock, the result of the second call is also filtered and it
> > shouldn't be, do you agree?
> >
> > Now the integration test:
> > public class StockServiceTests extends GroovyTestCase {
> >     private IStockService stockService
> >
> >     protected void setUp() {
> >         super.setUp()
> >         stockService = new StockService()
> >     }
> >
> >     void testFindAllStockAvailable() {
> >         def resultados =
> > stockService.findAllStockAvailable(produtoVariasCores)
> >         assertEquals("Filtered result should return 2", 2,
> > resultados.size())
> >     }
> >
> >     void testFindAllStock() {
> >         def resultados = stockService.findAllStock(produtoVariasCores)
> >         assertEquals("Should be 3, because it's not filtered'", 3,
> > resultados.size())
> >     }
> >
> >    // There's more tests that uses both methods
> > }
> >
> > Do you think I'm using integration tests in a wrong way? Am I supposing
> > anything that isn't correctly?
> >
> >
> > Regards,
> > ---
> > Felipe Cypriano
> >
> > P.S. I've translated some names in the code, but don't botter if I miss
> > anyone and the code wouldn't work because of wrong names.