struts-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "CRANFORD, CHRIS" <Chris.Cranf...@setech.com>
Subject RE: Editing a JPA entity
Date Thu, 07 Jan 2016 23:26:06 GMT
In the case of non-versioned domain models or cases where you aren't concerned with state collisions,
the traditional lookup/render/lookup/merge workflow works quite well.  

The problem though comes into play when you are concerned about versioned models and more
importantly, controlling state transition across concurrent modifications.  What I have seen
developers do in the past is that they expose the @Version property to the form and have that
value posted back along with the changed attributes during the save/update operation.  This
approach works, but the security risk is you're exposing a critical piece of data that is
subject to user manipulation to bypass optimistic locking.  

A better approach is to follow a similar paradigm that JSF uses called conversation scopes.
 The struts2-conversation-plugin offers this kind of feature.

The plugin basically allows you to expose a set of action properties to a named scope.  The
plugin in combination with a few custom tags, allowed a form identifier to be placed as a
hidden field in your form when you render your view.  When the view's changes are posted back
to the save/update action, the plugin first takes the hidden field conversation id and looks
up the state from the session that was saved when the conversation was started.  Any field
flags to be included in the conversation will be rehydrated with the state it had when the
prior action was executed.  The struts framework then can use it's normal property injection
mechanism to set the appropriate state on the model.  Since the version of the domain model
isn't being exposed to the client, there is no concern with a user hijacking the optimistic
locking mechanism of your JPA provider to force changes  to occur when a collision should
happen.

A typical action might look like the following.  The annotations I show my now map exactly
to the plugin as we use a modified proprietary version here but the gist remains the same.

@ConversationSupport(conversation = "myconversion")
public class SomeAction extends ActionSupport implements ModelDriven<ViewModel> {

  private Long id;
  @ConversationField private DomainModel domainModel;
  @ConversationField private ViewModel viewModel;

  @BeginConversation(conversation = "myconversion")
  public String renderView() {
    try {
      this.domainModel = someService.find(id);
      this.viewModel = new ViewModel(domainModel);
      return SUCCESS;
    }
    catch(Exception ex) {
      addActionError(getText(ERROR_UNEXPECTED_EXCEPTION));
      return ERROR;
    }
  }

  @Conversation(conversation = "myconversion")
  public String saveView() {
    try {
      // copy values from this.viewModel to this.domainModel 
      someService.update(this.domainModel);
      return SUCCESS;
    }
   catch(OptimisticLockException ex) {
     // you could elect to find the domainModel again, update it and try to take 
     // the changes in domainModel + the changes from the user in viewModel
     // and merge them then send the user back to the view again letting them
     // know some fields were changed while they were making their changes.
     // They can verify their changes again and resubmit.   I don't do this here 
     // but instead just tell the user the record was changed and they need to 
     // leave and come back in, but its up to you.
     addActionError(getText(ERROR_RECORD_ALREADY_MODIFIED));
     return INPUT;
   }
   catch(Exception ex) {
     addActionError(getText(ERROR_UNEXPECTED_EXCEPTION));
     return ERROR;
   }
  }

  /* other stuffs */

}



-----Original Message-----
From: C N Davies [mailto:cnd@xcogia.com] 
Sent: Wednesday, January 06, 2016 10:24 PM
To: 'Christoph Nenning' <Christoph.Nenning@lex-com.net>; 'Struts Users Mailing List'
<user@struts.apache.org>
Subject: RE: Editing a JPA entity

Christoph I understand why this happens, I was simply asking if there was a better way to
do this using some struts session magic or such. Seems there isn't so I'll just do it the
old long winded way.


-----Original Message-----
From: Christoph Nenning [mailto:Christoph.Nenning@lex-com.net]
Sent: Tuesday, January 5, 2016 6:57 PM
To: Struts Users Mailing List <user@struts.apache.org>
Subject: Re: Editing a JPA entity

> I'm using an action to retrieve a list of entities and render these as 
> a list, the user can then select an edit button that calls an action 
> that retrieves the individual entity and renders the edit page. Once 
> the user
has
> completed editing they hit the save button which calls the action that
calls
> the entity manager's merge method to update the db. Each of these
actions
> call methods of the same action class, but the entity ends up in a
detached
> state so merge will fail. I could just retrieve the entity again and
then
> update each data member but this seems like a very messy way to do it. 
Is
> there a better way to do this with struts?
> 
> 
> 
> I'm using struts 2.3.20 with hibernate 4.3.11
> 
> 


Well, that is basic http. When data is SELECTed from DB and the html page is rendered the
server is done. That means at this point there are no more references to attached jpa objects.
In terms of http: the handling of GET request is completed.

When the user hits save the browser issues another http request, usually a POST request. On
the server side there is no more state or information that there has been a GET request before
and entities had been loaded.

So yes, you have to retrieve the entity again and update it.



Regards,
Christoph

This Email was scanned by Sophos Anti Virus


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Email secured by Check Point


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Mime
View raw message