Re: AW: Session Storage with Tapestry

2015-03-18 Thread Thiago H de Paula Figueiredo
On Wed, 18 Mar 2015 11:14:08 -0300, Poggenpohl, Daniel  
 wrote:


What I meant to say was they recommend @SessionState instead of  
@SessionAttribute because it is a complex object.


Who said that? Anyway, I think it's an incorrect statement. It should say  
"@SessionAttribute for primitive types and general-purpose classes like  
String and Date, @SessionState for everything else". String is a pretty  
complex class and it shouldn't be used with @SessionState.



one of my DAO services into my AppSession object.


Nope. You just need to call it in your layout class, probably in its  
setupRender() method.



Or wouldn't this work because my AppSession is not a page or component?


It would, but I don't like the idea of injecting data storage objects into  
session-persisted objects at all.


If this wouldn't work, then every time someone would use my AppSession  
user, he would have to get() the user and then do a manual merge() or  
via DAO on it.


Nope, just once per request, hence my suggestion on doing it on  
setupRender() of your Layout class.


@SessionState
private AppSession appSession;

@Inject
private EntityManager entityManager;

void setupRender() {
appSession.setUser(entityManager.merge(appSession.getUser());
}

--
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br

-
To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
For additional commands, e-mail: users-h...@tapestry.apache.org



AW: Session Storage with Tapestry

2015-03-18 Thread Poggenpohl, Daniel
Hi,

> You need to use @SessionState because @Persist is only valid for a given page 
> or component. Page1's @Persist private 
> User user; is stored in a different session attribute than Page2's @Persist 
> private User user;. If you want something 
> persisted across pages, you need to use @SessionState.  
> Being a complex object makes no difference about choosing one annotation or 
> the other.

Because I feared this answer would arrive, I separated my two topics Session 
and Memory into two separate mails :-)

What I meant to say was they recommend @SessionState instead of 
@SessionAttribute because it is a complex object. I never intended to use 
@Persist with the session state objects.

> @SessionState is keyed by type, not by field name, so @SessionState private 
> User user; and @SessionState private User 
> currentUser; will point to the same object, stored in the same session 
> attribute.

Just as I thought, thank you.

> The error isn't related to transactions nor Tapestry at all. It's related to 
> your Hibernate/JPA usage: one entity is loaded in 
> one request, one Hibernate session/JPA entity manager instance. Then, in 
> another request, another session/entity 
> manager instance, you try to load some lazy field.  
> You need to use the merge() method of org.hibernate.Session or EntityManager 
> to reattach the entity to the current 
> Hibernate session or JPA entity manager.

I've since reduced the @SessionState object to a user and removed the 
AppSession object because the login time was never used anywhere anyway. I hate 
it when people program something just because they think someone may need it 
some day.
This of course fixed the bug.

If I'd use the merge() method, I'd have to inject an EntityManager or one of my 
DAO services into my AppSession object.
Or wouldn't this work because my AppSession is not a page or component?
If this wouldn't work, then every time someone would use my AppSession user, he 
would have to get() the user and then do a manual merge() or via DAO on it.

Can I inject into my AppSession object or what would be the way to go here?

Regards,
Daniel P.

-Ursprüngliche Nachricht-
Von: Thiago H de Paula Figueiredo [mailto:thiag...@gmail.com] 
Gesendet: Mittwoch, 18. März 2015 14:17
An: Tapestry users
Betreff: Re: Session Storage with Tapestry

On Wed, 18 Mar 2015 07:21:06 -0300, Poggenpohl, Daniel 
 wrote:

> Hello again,

Hi!

> I need a session storage where I store the currently logged on user.  
> Reading about it in the documentation, they recommend using 
> @SessionState because my user is a complex object, also containing 
> lists of other entities.

You need to use @SessionState because @Persist is only valid for a given page 
or component. Page1's @Persist private User user; is stored in a different 
session attribute than Page2's @Persist private User user;. If you want 
something persisted across pages, you need to use @SessionState.  
Being a complex object makes no difference about choosing one annotation or the 
other.

> My user also is an entity in a database. So, when a user logs in, the 
> appropriate entity is retrieved from the database, an "AppSession"
> object is created containing, among e.g. the time of login, the user 
> object. Is this the right way to do it? Or should I only store the ID 
> in the session?

This is extremely dependent on how you're going to use your user information. 
If you're going to show their name in every page, for example, and you store 
just the id, you'll be querying the database for the same information every 
request (unless you use some kind of cache between your page or component or 
mixin and your database).

> Now when the SessionState object is created, it can be used in any 
> other page or component using the same SessionState annotation and the 
> same type. Does it need to be the same name I'd say it doesn't, as 
> I've not read otherwise.

@SessionState is keyed by type, not by field name, so @SessionState private 
User user; and @SessionState private User currentUser; will point to the same 
object, stored in the same session attribute.

> To do this, a service receives the user. The service tries to access 
> the lazy collection, but fails with a "failed to lazily initialize a 
> collection of role:".
> What I gather from this is, services don't operate within transactions?

The error isn't related to transactions nor Tapestry at all. It's related to 
your Hibernate/JPA usage: one entity is loaded in one request, one Hibernate 
session/JPA entity manager instance. Then, in another request, another 
session/entity manager instance, you try to load some lazy field.  
You need to use the merge() method of org.hibernate.Session or EntityManager to 
reattach t

Re: Session Storage with Tapestry

2015-03-18 Thread Thiago H de Paula Figueiredo
On Wed, 18 Mar 2015 07:21:06 -0300, Poggenpohl, Daniel  
 wrote:



Hello again,


Hi!

I need a session storage where I store the currently logged on user.  
Reading about it in the documentation, they recommend using  
@SessionState because my user is a complex object, also containing lists  
of other entities.


You need to use @SessionState because @Persist is only valid for a given  
page or component. Page1's @Persist private User user; is stored in a  
different session attribute than Page2's @Persist private User user;. If  
you want something persisted across pages, you need to use @SessionState.  
Being a complex object makes no difference about choosing one annotation  
or the other.


My user also is an entity in a database. So, when a user logs in, the  
appropriate entity is retrieved from the database, an "AppSession"  
object is created containing, among e.g. the time of login, the user  
object. Is this the right way to do it? Or should I only store the ID in  
the session?


This is extremely dependent on how you're going to use your user  
information. If you're going to show their name in every page, for  
example, and you store just the id, you'll be querying the database for  
the same information every request (unless you use some kind of cache  
between your page or component or mixin and your database).


Now when the SessionState object is created, it can be used in any other  
page or component using the same SessionState annotation and the same  
type. Does it need to be the same name

I'd say it doesn't, as I've not read otherwise.


@SessionState is keyed by type, not by field name, so @SessionState  
private User user; and @SessionState private User currentUser; will point  
to the same object, stored in the same session attribute.


To do this, a service receives the user. The service tries to access the  
lazy collection, but fails with a

"failed to lazily initialize a collection of role:".
What I gather from this is, services don't operate within transactions?


The error isn't related to transactions nor Tapestry at all. It's related  
to your Hibernate/JPA usage: one entity is loaded in one request, one  
Hibernate session/JPA entity manager instance. Then, in another request,  
another session/entity manager instance, you try to load some lazy field.  
You need to use the merge() method of org.hibernate.Session or  
EntityManager to reattach the entity to the current Hibernate session or  
JPA entity manager.


Services operate within transactions as long as you use @CommitAfter  
(tapestry-hibernate or tapestry-jpa) or something like that (other  
library).


--
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br

-
To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org
For additional commands, e-mail: users-h...@tapestry.apache.org



Re: Session Storage with Tapestry

2015-03-18 Thread Barry Books
For this to work you need to store an entity in the SessionState. It looks
like you are storing AppSession in the SessionState which contains the User
entity. The simple way to fix this would be to add a lastLogin property to
your User entity and then just make your SessionState a User object. If you
don't want lastLogin in the database you'll need to persist it some other
way.

I usually make a service to hide all this stuff. I don't like having
@SessionState everywhere because it makes it difficult to refactor. In this
case you could make a service called UserSession with getAppSession() and
getUser(). Then instead of putting User in AppSession just put both in the
session.

On Wednesday, March 18, 2015, Poggenpohl, Daniel <
daniel.poggenp...@isst.fraunhofer.de> wrote:

> Hello again,
>
> oops, I didn't see this message, sorry.
> This here:
>
> http://tapestry.apache.org/5.3/apidocs/src-html/org/apache/tapestry5/jpa/JpaModule.html
> seems to indicate that the default for
> JpaSymbols.ENTITY_SESSION_STATE_PERSISTENCE_STRATEGY_ENABLED
> is "true", which is part of why my changes do not make a difference.
>
> Another part seems to be what you say, that I need to directly annotate an
> entity with @SessionState.
>
> I've found this here:
>
> http://tapestry.apache.org/5.3/apidocs/src-html/org/apache/tapestry5/internal/hibernate/EntityApplicationStatePersistenceStrategy.html#line.40
>
> public class EntityApplicationStatePersistenceStrategy extends
> SessionApplicationStatePersistenceStrategy
> {
> @Override
> public  T get(final Class ssoClass, final
> ApplicationStateCreator creator)
> {
> final Object persistedValue = getOrCreate(ssoClass, creator);
>
> if (persistedValue instanceof PersistedEntity)
> {
> final PersistedEntity persisted = (PersistedEntity)
> persistedValue;
>
> final Object restored =
> persisted.restore(entityManagerManager);
>
> // shall we maybe throw an exception instead?
> if (restored == null)
> {
> set(ssoClass, null);
> return (T) getOrCreate(ssoClass, creator);
> }
>
> return (T) restored;
> }
>
> return (T) persistedValue;
> }
> }
>
> Which tells me that entities contained in SSO annotated objects are
> basically out of luck, it seems.
>
> So, is my method of creating a session state object containing multiple
> values not a good way to do this?
> Or is it just that entities are used under-supported this way?
>
> Regards,
> Daniel P.
>
> -Ursprüngliche Nachricht-
> Von: Barry Books [mailto:trs...@gmail.com ]
> Gesendet: Mittwoch, 18. März 2015 12:05
> An: Tapestry users
> Betreff: Re: Session Storage with Tapestry
>
> If you are using Tapestry Hibernate it should just work if you put a
> Hibernate object into a SessionState variable. There is a configuration
> that contains the Hibernate entities so SessionState is able to store the
> primary key in the session and retrieve the object when needed. Services as
> well as pages/components should be able to lazy load from the SessionState
> object.
>
> Assuming you are using Tapestry Hibernate then somehow the object in your
> SessionState is disconnected from the Hibernate session. If you turn on
> show sql you should see the object fetched evertime you go to a new page.
> If you don't then something is wrong.
>
>
>
> On Wed, Mar 18, 2015 at 5:21 AM, Poggenpohl, Daniel <
> daniel.poggenp...@isst.fraunhofer.de > wrote:
>
> > Hello again,
> >
> > a slightly different topic as the last but with the same "undertones":
> >
> > I need a session storage where I store the currently logged on user.
> > Reading about it in the documentation, they recommend using
> > @SessionState because my user is a complex object, also containing
> > lists of other entities.
> >
> > My user also is an entity in a database. So, when a user logs in, the
> > appropriate entity is retrieved from the database, an "AppSession"
> > object is created containing, among e.g. the time of login, the user
> > object. Is this the right way to do it? Or should I only store the ID in
> the session?
> >
> > Now when the SessionState object is created, it can be used in any
> > other page or component using the same SessionState annotation and the
> same type.
> > Does it need to be the same name
> > I'd say it doesn't, as I've not read otherwise.
> >
> > My user contains lazy collections of other entities. Every page of my
> > 

AW: Session Storage with Tapestry

2015-03-18 Thread Poggenpohl, Daniel
Hello again,

oops, I didn't see this message, sorry.
This here:
http://tapestry.apache.org/5.3/apidocs/src-html/org/apache/tapestry5/jpa/JpaModule.html
seems to indicate that the default for 
JpaSymbols.ENTITY_SESSION_STATE_PERSISTENCE_STRATEGY_ENABLED
is "true", which is part of why my changes do not make a difference.

Another part seems to be what you say, that I need to directly annotate an 
entity with @SessionState.

I've found this here:
http://tapestry.apache.org/5.3/apidocs/src-html/org/apache/tapestry5/internal/hibernate/EntityApplicationStatePersistenceStrategy.html#line.40

public class EntityApplicationStatePersistenceStrategy extends
SessionApplicationStatePersistenceStrategy
{
@Override
public  T get(final Class ssoClass, final ApplicationStateCreator 
creator)
{
final Object persistedValue = getOrCreate(ssoClass, creator);

if (persistedValue instanceof PersistedEntity)
{
final PersistedEntity persisted = (PersistedEntity) persistedValue;

final Object restored = persisted.restore(entityManagerManager);

// shall we maybe throw an exception instead?
if (restored == null)
{
set(ssoClass, null);
return (T) getOrCreate(ssoClass, creator);
}

return (T) restored;
}

return (T) persistedValue;
}
}

Which tells me that entities contained in SSO annotated objects are basically 
out of luck, it seems.

So, is my method of creating a session state object containing multiple values 
not a good way to do this?
Or is it just that entities are used under-supported this way?

Regards,
Daniel P.

-Ursprüngliche Nachricht-
Von: Barry Books [mailto:trs...@gmail.com] 
Gesendet: Mittwoch, 18. März 2015 12:05
An: Tapestry users
Betreff: Re: Session Storage with Tapestry

If you are using Tapestry Hibernate it should just work if you put a Hibernate 
object into a SessionState variable. There is a configuration that contains the 
Hibernate entities so SessionState is able to store the primary key in the 
session and retrieve the object when needed. Services as well as 
pages/components should be able to lazy load from the SessionState object.

Assuming you are using Tapestry Hibernate then somehow the object in your 
SessionState is disconnected from the Hibernate session. If you turn on show 
sql you should see the object fetched evertime you go to a new page.
If you don't then something is wrong.



On Wed, Mar 18, 2015 at 5:21 AM, Poggenpohl, Daniel < 
daniel.poggenp...@isst.fraunhofer.de> wrote:

> Hello again,
>
> a slightly different topic as the last but with the same "undertones":
>
> I need a session storage where I store the currently logged on user.
> Reading about it in the documentation, they recommend using 
> @SessionState because my user is a complex object, also containing 
> lists of other entities.
>
> My user also is an entity in a database. So, when a user logs in, the 
> appropriate entity is retrieved from the database, an "AppSession" 
> object is created containing, among e.g. the time of login, the user 
> object. Is this the right way to do it? Or should I only store the ID in the 
> session?
>
> Now when the SessionState object is created, it can be used in any 
> other page or component using the same SessionState annotation and the same 
> type.
> Does it need to be the same name
> I'd say it doesn't, as I've not read otherwise.
>
> My user contains lazy collections of other entities. Every page of my 
> app contains the layout component which provides the login area and 
> serves to create the session object for the app, retrieving the user 
> entity in the process.
> A page containing the layout component itself contains another 
> component where these lazy collections are needed. The user logs in, 
> the SessionState object is created, the user entity is stored inside 
> the object. The page is requested again, and the component is 
> initialized/rendered. The component contains a reference to the 
> SessionState object. Inside the component, a tree should display objects of 
> the lazy collection.
> To do this, a service receives the user. The service tries to access 
> the lazy collection, but fails with a "failed to lazily initialize a 
> collection of role:".
>
> What I gather from this is, services don't operate within transactions?
>
> UPDATE: I tried to access the lazy collection from the component 
> itself, but the error was the same.
> Even from the page, the error still was present.
>
> This leads me to the point that I may be doing something wrong using 
> an entity in a session storage?
>
> Regards,
> Daniel Poggenpohl
>


AW: Session Storage with Tapestry

2015-03-18 Thread Poggenpohl, Daniel
Hi,

I've read about the Hibernate entity persistence strategy on
http://tapestry.apache.org/hibernate-user-guide.html
As I do not want to be Hibernate-specific, I searched for an equivalent for JPA 
and found it not in the guide, but searching in Eclipse:
JpaSymbols.ENTITY_SESSION_STATE_PERSISTENCE_STRATEGY_ENABLED
This seems to enable the entity persistence strategy for session state objects.
Applying this doesn't make the error go away, though.

I'm gonna include some code excerpts here, maybe I've done something horribly 
wrong.

In AppModule:
public static void contributeApplicationDefaults(
MappedConfiguration configuration)
{

configuration.add(JpaSymbols.ENTITY_SESSION_STATE_PERSISTENCE_STRATEGY_ENABLED, 
"true");
}

My session state object:

public class AppSession {
   
   private User loggedInUser;
   
   private Date loginDate;
   
   public AppSession(User loggedInUser) throws ClientProtocolException, 
IOException {
 this.loggedInUser = loggedInUser;
 this.loginDate = new Date();
   }

   public User getLoggedInUser() {
 return loggedInUser;
   }

   public Date getLoginDate() {
 return loginDate;
   }
}

The user entity:
@Entity
@NamedQueries ({
   @NamedQuery(name=User.FIND_BY_USERNAME, query="SELECT u FROM User u 
WHERE u.username = ?1")
})
public class User {
   
   public static final String FIND_BY_USERNAME = "User.findByUserName";

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

   @Validate(value="required")
   @Column(nullable=false,unique=true)
   private String username;
   
   @Lob
   @Column(nullable=false)
   private byte[] password;
   
   @Column(nullable=false)
   @Validate(value="email")
   private String email;
   
   @ManyToMany
   @JoinTable
   private Set groups;
   
   public User() {
 groups = new HashSet();
   }

   public Set getGroups() {
 return Collections.unmodifiableSet(groups);
   }
   

Creating the session in my layout component (excerpt):
   @SessionState
   AppSession session;

   public Object onActionFromLogout() {
 session = null;
 return Index.class;
   }

   void onValidateFromLoginForm() {
  authenticatedUser = appAuthenticator.authenticateUser(userName, 
password);
}

   Object onSuccessFromLoginForm() {
 session = new AppSession(authenticatedUser);
   }

Authenticating a user:
   public User authenticateUser(String username, String password) throws 
NoExistingUserException, CryptoUtilException {
   User user = userDAO.findUserByName(username);
   return CryptoUtil.checkHash(CryptoUtil.calculateHash(password), 
user.getPassword()) ? user : null;

Using the session state object in a page:
public class Hauptseite {

   @SessionState
   private AppSession session;

   void setupRender() {
 for (UserGroup group : session.getLoggedInUser().getGroups()) {
System.out.println(group.toString());
 }

   }

Any pointers? Do I have to use the user as a direct SessionState object? Can't 
I use a wrapper class?

Regards,
Daniel P.

Von: Poggenpohl, Daniel 
Gesendet: Mittwoch, 18. März 2015 11:21
An: users@tapestry.apache.org
Betreff: Session Storage with Tapestry

Hello again,

a slightly different topic as the last but with the same "undertones":

I need a session storage where I store the currently logged on user. Reading 
about it in the documentation, they recommend using @SessionState because my 
user is a complex object, also containing lists of other entities.

My user also is an entity in a database. So, when a user logs in, the 
appropriate entity is retrieved from the database, an "AppSession" object is 
created containing, among e.g. the time of login, the user object. Is this the 
right way to do it? Or should I only store the ID in the session?

Now when the SessionState object is created, it can be used in any other page 
or component using the same SessionState annotation and the same type. Does it 
need to be the same name
I'd say it doesn't, as I've not read otherwise.

My user contains lazy collections of other entities. Every page of my app 
contains the layout component which provides the login area and serves to 
create the session object for the app, retrieving the user entity in the 
process.
A page containing the layout component itself contains another component where 
these lazy collections are needed. The user logs in, the SessionState object is 
created, the user entity is stored inside the object. The page is requested 
again, and the component is

Re: Session Storage with Tapestry

2015-03-18 Thread Barry Books
If you are using Tapestry Hibernate it should just work if you put a
Hibernate object into a SessionState variable. There is a configuration
that contains the Hibernate entities so SessionState is able to store the
primary key in the session and retrieve the object when needed. Services as
well as pages/components should be able to lazy load from the SessionState
object.

Assuming you are using Tapestry Hibernate then somehow the object in your
SessionState is disconnected from the Hibernate session. If you turn on
show sql you should see the object fetched evertime you go to a new page.
If you don't then something is wrong.



On Wed, Mar 18, 2015 at 5:21 AM, Poggenpohl, Daniel <
daniel.poggenp...@isst.fraunhofer.de> wrote:

> Hello again,
>
> a slightly different topic as the last but with the same "undertones":
>
> I need a session storage where I store the currently logged on user.
> Reading about it in the documentation, they recommend using @SessionState
> because my user is a complex object, also containing lists of other
> entities.
>
> My user also is an entity in a database. So, when a user logs in, the
> appropriate entity is retrieved from the database, an "AppSession" object
> is created containing, among e.g. the time of login, the user object. Is
> this the right way to do it? Or should I only store the ID in the session?
>
> Now when the SessionState object is created, it can be used in any other
> page or component using the same SessionState annotation and the same type.
> Does it need to be the same name
> I'd say it doesn't, as I've not read otherwise.
>
> My user contains lazy collections of other entities. Every page of my app
> contains the layout component which provides the login area and serves to
> create the session object for the app, retrieving the user entity in the
> process.
> A page containing the layout component itself contains another component
> where these lazy collections are needed. The user logs in, the SessionState
> object is created, the user entity is stored inside the object. The page is
> requested again, and the component is initialized/rendered. The component
> contains a reference to the SessionState object. Inside the component, a
> tree should display objects of the lazy collection.
> To do this, a service receives the user. The service tries to access the
> lazy collection, but fails with a
> "failed to lazily initialize a collection of role:".
>
> What I gather from this is, services don't operate within transactions?
>
> UPDATE: I tried to access the lazy collection from the component itself,
> but the error was the same.
> Even from the page, the error still was present.
>
> This leads me to the point that I may be doing something wrong using an
> entity in a session storage?
>
> Regards,
> Daniel Poggenpohl
>


Session Storage with Tapestry

2015-03-18 Thread Poggenpohl, Daniel
Hello again,

a slightly different topic as the last but with the same "undertones":

I need a session storage where I store the currently logged on user. Reading 
about it in the documentation, they recommend using @SessionState because my 
user is a complex object, also containing lists of other entities.

My user also is an entity in a database. So, when a user logs in, the 
appropriate entity is retrieved from the database, an "AppSession" object is 
created containing, among e.g. the time of login, the user object. Is this the 
right way to do it? Or should I only store the ID in the session?

Now when the SessionState object is created, it can be used in any other page 
or component using the same SessionState annotation and the same type. Does it 
need to be the same name
I'd say it doesn't, as I've not read otherwise.

My user contains lazy collections of other entities. Every page of my app 
contains the layout component which provides the login area and serves to 
create the session object for the app, retrieving the user entity in the 
process.
A page containing the layout component itself contains another component where 
these lazy collections are needed. The user logs in, the SessionState object is 
created, the user entity is stored inside the object. The page is requested 
again, and the component is initialized/rendered. The component contains a 
reference to the SessionState object. Inside the component, a tree should 
display objects of the lazy collection.
To do this, a service receives the user. The service tries to access the lazy 
collection, but fails with a
"failed to lazily initialize a collection of role:".

What I gather from this is, services don't operate within transactions?

UPDATE: I tried to access the lazy collection from the component itself, but 
the error was the same.
Even from the page, the error still was present.

This leads me to the point that I may be doing something wrong using an entity 
in a session storage?

Regards,
Daniel Poggenpohl