View Javadoc

1   /* 
2    * Copyright (c) 2005-2011, Fraunhofer-Gesellschaft
3    * All rights reserved.
4    * 
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions are
7    * met:
8    * 
9    * (1) Redistributions of source code must retain the above copyright
10   *     notice, this list of conditions and the disclaimer at the end.
11   *     Redistributions in binary form must reproduce the above copyright
12   *     notice, this list of conditions and the following disclaimer in
13   *     the documentation and/or other materials provided with the
14   *     distribution.
15   * 
16   * (2) Neither the name of Fraunhofer nor the names of its
17   *     contributors may be used to endorse or promote products derived
18   *     from this software without specific prior written permission.
19   * 
20   * DISCLAIMER
21   * 
22   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33   *  
34   */
35  package org.ogf.graap.wsag.server.persistence.impl;
36  
37  import java.text.MessageFormat;
38  import java.util.Collection;
39  import java.util.Iterator;
40  
41  import javax.persistence.Basic;
42  import javax.persistence.Column;
43  import javax.persistence.Entity;
44  import javax.persistence.EntityManager;
45  import javax.persistence.FetchType;
46  import javax.persistence.GeneratedValue;
47  import javax.persistence.GenerationType;
48  import javax.persistence.Id;
49  import javax.persistence.Lob;
50  import javax.persistence.NamedQueries;
51  import javax.persistence.NamedQuery;
52  import javax.persistence.NoResultException;
53  import javax.persistence.Query;
54  import javax.persistence.RollbackException;
55  import javax.persistence.Table;
56  import javax.persistence.Transient;
57  import javax.persistence.UniqueConstraint;
58  
59  import org.apache.log4j.Logger;
60  import org.apache.xmlbeans.XmlException;
61  import org.apache.xmlbeans.XmlObject;
62  import org.apache.xmlbeans.XmlOptions;
63  import org.ogf.graap.wsag.api.Agreement;
64  import org.ogf.graap.wsag.api.exceptions.AgreementFactoryException;
65  import org.ogf.graap.wsag.api.logging.LogMessage;
66  import org.ogf.graap.wsag.api.types.AbstractAgreementType;
67  import org.ogf.graap.wsag.server.persistence.EmfRegistry;
68  import org.ogf.graap.wsag4j.types.engine.PersistenceAgreementContextDocument;
69  import org.ogf.graap.wsag4j.types.engine.PersistenceAgreementContextType;
70  import org.ogf.schemas.graap.wsAgreement.AgreementPropertiesType;
71  import org.ogf.schemas.graap.wsAgreement.AgreementStateType;
72  
73  /*
74   * TODO: the container should implement the CRUD operations
75   *       - the context element should be a transient XmlBean.
76   *       - the context element should be de/serialized on the 
77   *         CRUD operation invocation 
78   */
79  
80  /**
81   * Entity class for the agreement persistence. It defines the entity fields (the tables' columns), the
82   * named-queries used to access the stored data, and the corresponding getter/setter methods.
83   * 
84   * @author T.Weuffel
85   */
86  @Entity
87  @Table( name = "PERSISTENT_AGREEMENT_CONTAINER", uniqueConstraints = @UniqueConstraint(
88                  columnNames = "agreement_id" ) )
89  @NamedQueries( {
90      @NamedQuery( name = "PersistentAgreementContainer.findAll",
91                      query = "SELECT p FROM PersistentAgreementContainer p" ),
92      @NamedQuery( name = "PersistentAgreementContainer.findByAgreementId",
93                      query = "SELECT p FROM PersistentAgreementContainer p "
94                          + "WHERE p.agreementId = :agreementId" ),
95      @NamedQuery( name = "PersistentAgreementContainer.findByAgreementAndFactoryId",
96                      query = "SELECT p FROM PersistentAgreementContainer p "
97                          + "WHERE p.agreementId = :agreementId AND p.agreementFactoryId = :agreementFactoryId" ),
98      @NamedQuery( name = "PersistentAgreementContainer.findAllByAgreementFactoryId",
99                      query = "SELECT p FROM PersistentAgreementContainer p "
100                         + "WHERE p.agreementFactoryId = :agreementFactoryId" ) } )
101 public class PersistentAgreementContainer
102 {
103 
104     // the logger should not be persisted
105     @Transient
106     private static final Logger LOG = Logger.getLogger( PersistentAgreementContainer.class );
107 
108     @Transient
109     private static final int AGREEMENT_CONTEXT_SIZE = 1638400;
110 
111     @Transient
112     private PersistenceAgreementContextDocument persistenceContext;
113 
114     // primary-key of the stored entity
115     @Id
116     @Column( name = "id" )
117     @GeneratedValue( strategy = GenerationType.TABLE )
118     @Basic( optional = false )
119     private Integer id;
120 
121     // agreement id
122     @GeneratedValue( strategy = GenerationType.TABLE )
123     @Column( name = "agreement_id" )
124     @Basic( optional = false )
125     private String agreementId;
126 
127     // original agreement factory id
128     @Column( name = "agreement_factory_id", nullable = false )
129     @Basic( optional = false )
130     private String agreementFactoryId;
131 
132     //
133     // state of the agreement, this state is only used in db queries
134     //
135     @SuppressWarnings( "unused" )
136     @Column( name = "state", nullable = false )
137     @Basic( optional = false )
138     private String state;
139 
140     // original agreement class name
141     @Column( name = "agreement_class_name", nullable = false )
142     @Basic( optional = false )
143     private String agreementClassName;
144 
145     // context-type of the agreement
146     @Lob
147     @Column( name = "persisted_agreement_context_type", nullable = false, length = AGREEMENT_CONTEXT_SIZE )
148     @Basic( optional = false, fetch = FetchType.LAZY )
149     private String persistedAgreementContextType;
150 
151     /**
152      * The default constructor is required by the JPA2 environment. It is used to instantiate an instance of
153      * this entity. All values are then passed to this instance by setter-injection.
154      */
155     public PersistentAgreementContainer()
156     {
157         persistenceContext = PersistenceAgreementContextDocument.Factory.newInstance();
158         persistenceContext.addNewPersistenceAgreementContext();
159     }
160 
161     /**
162      * Creates a new {@link PersistentAgreementContainer} for the given agreement and agreement factory id.
163      * 
164      * @param agreement
165      *            the agreement for which the container will be created
166      * @param factoryId
167      *            the id of the factory that created the agreement
168      */
169     public PersistentAgreementContainer( Agreement agreement, String factoryId )
170     {
171         this.agreementFactoryId = factoryId;
172 
173         // build wrapper
174         persistenceContext = PersistenceAgreementContextDocument.Factory.newInstance();
175         PersistenceAgreementContextType context = persistenceContext.addNewPersistenceAgreementContext();
176 
177         // store agreement properties
178         context.addNewAgreementProperties();
179 
180         // store the whole agreement context itself
181         PersistenceAgreementContextType.Entry entry = context.addNewEntry();
182         entry.setValue( agreement.getContext() );
183         entry.setName( DatabasePersistentAgreement.AGREEMENT_CONTEXT_ENTRY );
184 
185         // store the agreement properties
186         entry = context.addNewEntry();
187 
188         AbstractAgreementType abstractAgreementType = agreement.getAgreementInstance();
189         entry.setValue( abstractAgreementType.getXMLObject() );
190         entry.setName( DatabasePersistentAgreement.AGREEMENT_PROPERTIES_ENTRY );
191         context.getAgreementProperties().set( abstractAgreementType.getXMLObject() );
192 
193         // set agreement class name
194         setAgreementClassName( abstractAgreementType.getClass().getName() );
195 
196         // set the current agreements' state and EPR
197         setState( agreement.getState() );
198 
199         //
200         // initial serialization of the xml object
201         //
202         this.persistedAgreementContextType = persistenceContext.xmlText();
203     }
204 
205     /**
206      * 
207      * @return the agreement id
208      */
209     public String getAgreementId()
210     {
211         return agreementId;
212     }
213 
214     /**
215      * 
216      * @return the agreement factory id
217      */
218     public String getAgreementFactoryId()
219     {
220         return agreementFactoryId;
221     }
222 
223     /**
224      * 
225      * @param agreementFactoryId
226      *            the factory id to set
227      */
228     public void setAgreementFactoryId( String agreementFactoryId )
229     {
230         this.agreementFactoryId = agreementFactoryId;
231     }
232 
233     /**
234      * 
235      * @return the agreement state
236      */
237     public AgreementStateType getState()
238     {
239         AgreementPropertiesType props =
240             persistenceContext.getPersistenceAgreementContext().getAgreementProperties();
241         return props.getAgreementState();
242     }
243 
244     /**
245      * 
246      * @param state
247      *            the agreement state to set
248      */
249     public void setState( AgreementStateType state )
250     {
251         AgreementPropertiesType props =
252             persistenceContext.getPersistenceAgreementContext().getAgreementProperties();
253         props.setAgreementState( state );
254         this.state = state.getState().toString();
255     }
256 
257     /**
258      * 
259      * @return the agreement implementation class name
260      */
261     public String getAgreementClassName()
262     {
263         return agreementClassName;
264     }
265 
266     /**
267      * 
268      * @param agreementClassName
269      *            the agreement implementation class name to set
270      */
271     public void setAgreementClassName( String agreementClassName )
272     {
273         this.agreementClassName = agreementClassName;
274     }
275 
276     /**
277      * 
278      * @return the context of the persistent agreement
279      */
280     public PersistenceAgreementContextType getPersistedAgreementContextType()
281     {
282         return persistenceContext.getPersistenceAgreementContext();
283     }
284 
285     /**
286      * 
287      * @param persistenceAgreementContextType
288      *            the context of the persistent agreement to set
289      */
290     public void setPersistedAgreementContextType( PersistenceAgreementContextType persistenceAgreementContextType )
291     {
292         this.persistenceContext.getPersistenceAgreementContext().set( persistenceAgreementContextType );
293         this.persistedAgreementContextType = persistenceContext.xmlText();
294     }
295 
296     /**
297      * Creates a new persistent container that stores the agreement properties document and the agreement
298      * execution context.
299      * 
300      * @param agreement
301      *            the agreement
302      * 
303      * @param factoryId
304      *            the id of the factory that created the agreement
305      * 
306      * @return the persistent container
307      * 
308      * @throws AgreementFactoryException
309      *             indicates that the persistent container could not be created
310      */
311     public static PersistentAgreementContainer createContainer( Agreement agreement, String factoryId )
312         throws AgreementFactoryException
313     {
314         if ( LOG.isDebugEnabled() )
315         {
316             LOG.debug( LogMessage.getMessage(
317                 "Try to persist the PersistentAgreementContainer for agreement ''{0}''.",
318                 agreement.getAgreementId() ) );
319         }
320 
321         PersistentAgreementContainer container = new PersistentAgreementContainer( agreement, factoryId );
322 
323         //
324         // serialize xml object
325         //
326         container.persistedAgreementContextType = container.persistenceContext.xmlText();
327 
328         // try to persist the wrapped agreement
329         EntityManager em = EmfRegistry.getEntityManager();
330         try
331         {
332             em.getTransaction().begin();
333             try
334             {
335                 LOG.trace( "original agreement id: " + container.getAgreementId() );
336 
337                 // persist and commit
338                 em.persist( container );
339                 em.getTransaction().commit();
340 
341                 String agreementId = container.getAgreementId();
342                 LOG.trace( "generated agreement id: " + agreementId );
343 
344             }
345             catch ( RollbackException ex )
346             {
347                 LOG.error( MessageFormat.format( "Could not persist the wrapped agreement with id ''{0}''.",
348                     agreement.getAgreementId() ), ex );
349 
350                 // roll back the persistment
351                 em.getTransaction().rollback();
352 
353                 throw new AgreementFactoryException( MessageFormat.format(
354                     "Could not persist the wrapped agreement with id ''{0}''.", agreement.getAgreementId() ) );
355             }
356 
357             // TODO: check if this can be done in one transaction
358             //
359             // update generated agreement ids
360             //
361             em.getTransaction().begin();
362             try
363             {
364                 //
365                 // update agreement id and serialize xml object
366                 //
367                 AgreementPropertiesType properties =
368                     container.persistenceContext.getPersistenceAgreementContext().getAgreementProperties();
369                 properties.setAgreementId( container.getAgreementId() );
370                 agreement.getAgreementInstance().setAgreementId( container.getAgreementId() );
371                 container.persistedAgreementContextType = container.persistenceContext.xmlText();
372                 em.merge( container );
373                 em.getTransaction().commit();
374 
375                 LOG.trace( "updated agreement id: " + container.getAgreementId() );
376             }
377             catch ( RollbackException ex )
378             {
379                 LOG.error( LogMessage.getMessage( "Could not persist the wrapped agreement with id ''{0}''.",
380                     agreement.getAgreementId() ), ex );
381 
382                 // roll back the persistment
383                 em.getTransaction().rollback();
384 
385                 String message = "Failed to update persistence context ''{0}'' with generated id.";
386                 String error = MessageFormat.format( message, new Object[] { agreement.getAgreementId() } );
387                 throw new AgreementFactoryException( error );
388             }
389         }
390         finally
391         {
392             em.close();
393         }
394 
395         return container;
396     }
397 
398     /**
399      * Loads a persistent container for the given agreement id and agreement factory id.
400      * 
401      * @param agreementId
402      *            the id of the agreement to load
403      * @param agreementFactoryId
404      *            the id of the factory that created the agreement
405      * @return the persistent container
406      * 
407      * @throws AgreementFactoryException
408      *             indicates that the agreement could not be loaded
409      */
410     public static PersistentAgreementContainer loadContainer( String agreementId, String agreementFactoryId )
411         throws AgreementFactoryException
412     {
413         //
414         // load the persisted agreement
415         //
416         EntityManager em = EmfRegistry.getEntityManager();
417         try
418         {
419             Query query = em.createNamedQuery( "PersistentAgreementContainer.findByAgreementId" );
420             query.setParameter( "agreementId", agreementId );
421 
422             try
423             {
424                 PersistentAgreementContainer container =
425                     (PersistentAgreementContainer) query.getSingleResult();
426 
427                 try
428                 {
429                     String xml = container.persistedAgreementContextType;
430                     container.persistenceContext =
431                         (PersistenceAgreementContextDocument) XmlObject.Factory.parse( xml );
432                 }
433                 catch ( XmlException ex )
434                 {
435                     LOG.error( "could not load persisted agreement context.", ex );
436                     throw new AgreementFactoryException( "could not load persisted agreement context.", ex );
437                 }
438 
439                 return container;
440 
441             }
442             catch ( NoResultException ex )
443             {
444                 //
445                 // not found, so we return null
446                 //
447                 return null;
448             }
449         }
450         finally
451         {
452             em.close();
453         }
454     }
455 
456     /**
457      * Loads a persistent container for the given agreement id and agreement factory id.
458      * 
459      * @param agreementId
460      *            the id of the agreement to load
461      * 
462      * @return the persistent container
463      * 
464      * @throws AgreementFactoryException
465      *             indicates that the agreement with the given id could not be loaded
466      */
467     public static PersistentAgreementContainer loadContainer( String agreementId )
468         throws AgreementFactoryException
469     {
470         //
471         // load the persisted agreement
472         //
473         EntityManager em = EmfRegistry.getEntityManager();
474         try
475         {
476             Query query = em.createNamedQuery( "PersistentAgreementContainer.findByAgreementId" );
477             query.setParameter( "agreementId", agreementId );
478 
479             try
480             {
481                 PersistentAgreementContainer persistentAgreementContainer =
482                     (PersistentAgreementContainer) query.getSingleResult();
483 
484                 try
485                 {
486                     String xml = persistentAgreementContainer.persistedAgreementContextType;
487                     persistentAgreementContainer.persistenceContext =
488                         (PersistenceAgreementContextDocument) XmlObject.Factory.parse( xml );
489                 }
490                 catch ( XmlException ex )
491                 {
492                     LOG.error( "could not load persisted agreement context.", ex );
493                     throw new AgreementFactoryException( "could not load persisted agreement context.", ex );
494                 }
495 
496                 return persistentAgreementContainer;
497 
498             }
499             catch ( NoResultException ex )
500             {
501                 //
502                 // not found, so we return null
503                 //
504                 return null;
505             }
506         }
507         finally
508         {
509             em.close();
510         }
511     }
512 
513     /**
514      * Creates a list of all persistent agreement containers.
515      * 
516      * @return the persisted containers
517      * 
518      * @throws AgreementFactoryException
519      *             indicates an error while listing the agreement containers
520      */
521     @SuppressWarnings( "unchecked" )
522     public static PersistentAgreementContainer[] listContainers() throws AgreementFactoryException
523     {
524         //
525         // load the persisted agreement
526         //
527         EntityManager em = EmfRegistry.getEntityManager();
528         try
529         {
530             Query query = em.createNamedQuery( "PersistentAgreementContainer.findAll" );
531 
532             Collection<PersistentAgreementContainer> containers = null;
533             try
534             {
535                 containers = query.getResultList();
536 
537                 for ( Iterator<PersistentAgreementContainer> iterator = containers.iterator(); iterator.hasNext(); )
538                 {
539                     PersistentAgreementContainer persistentAgreementContainer = iterator.next();
540 
541                     try
542                     {
543                         String xml = persistentAgreementContainer.persistedAgreementContextType;
544                         persistentAgreementContainer.persistenceContext =
545                             (PersistenceAgreementContextDocument) XmlObject.Factory.parse( xml );
546                     }
547                     catch ( XmlException ex )
548                     {
549                         LOG.error( "could not load persisted agreement context.", ex );
550                         throw new AgreementFactoryException( "could not load persisted agreement context.",
551                                                              ex );
552                     }
553                 }
554 
555                 return containers.toArray( new PersistentAgreementContainer[containers.size()] );
556 
557             }
558             catch ( NoResultException ex )
559             {
560                 //
561                 // not found, so we return null
562                 //
563                 return null;
564             }
565         }
566         finally
567         {
568             em.close();
569         }
570     }
571 
572     /**
573      * Lists all persistent agreement containers for a given factory
574      * 
575      * @param agreementFactoryId
576      *            the factory id
577      * 
578      * @return the container for the given factory id
579      * 
580      * @throws AgreementFactoryException
581      *             indicates an error while listing the persistent containers for the given factory id
582      */
583     @SuppressWarnings( "unchecked" )
584     public static PersistentAgreementContainer[] listContainers( String agreementFactoryId )
585         throws AgreementFactoryException
586     {
587         //
588         // load the persisted agreement
589         //
590         EntityManager em = EmfRegistry.getEntityManager();
591         try
592         {
593             Query query = em.createNamedQuery( "PersistentAgreementContainer.findAllByAgreementFactoryId" );
594             query.setParameter( "agreementFactoryId", agreementFactoryId );
595 
596             Collection<PersistentAgreementContainer> containers = null;
597             try
598             {
599                 containers = query.getResultList();
600 
601                 for ( Iterator<PersistentAgreementContainer> iterator = containers.iterator(); iterator.hasNext(); )
602                 {
603                     PersistentAgreementContainer persistentAgreementContainer =
604                         iterator.next();
605 
606                     try
607                     {
608                         String xml = persistentAgreementContainer.persistedAgreementContextType;
609                         persistentAgreementContainer.persistenceContext =
610                             (PersistenceAgreementContextDocument) XmlObject.Factory.parse( xml );
611                     }
612                     catch ( XmlException ex )
613                     {
614                         LOG.error( "could not load persisted agreement context.", ex );
615                         throw new AgreementFactoryException( "could not load persisted agreement context.",
616                                                              ex );
617                     }
618                 }
619 
620                 return containers.toArray( new PersistentAgreementContainer[containers.size()] );
621 
622             }
623             catch ( NoResultException ex )
624             {
625                 //
626                 // not found, so we return null
627                 //
628                 return null;
629             }
630         }
631         finally
632         {
633             em.close();
634         }
635     }
636 
637     /**
638      * Save the container instance.
639      * 
640      * @throws AgreementFactoryException
641      *             indicates an error saving the container
642      */
643     public void saveContainer() throws AgreementFactoryException
644     {
645         // try to persist the wrapped agreement
646         EntityManager em = EmfRegistry.getEntityManager();
647         try
648         {
649             em.getTransaction().begin();
650             try
651             {
652                 Query query = em.createNamedQuery( "PersistentAgreementContainer.findByAgreementId" );
653                 query.setParameter( "agreementId", agreementId );
654 
655                 PersistentAgreementContainer persistentAgreementContainer = null;
656                 try
657                 {
658                     persistentAgreementContainer = (PersistentAgreementContainer) query.getSingleResult();
659                 }
660                 catch ( NoResultException ex )
661                 {
662                     String error = "Persisted agreement not found in database. Update operation failed.";
663                     LOG.error( error );
664                     throw new AgreementFactoryException( error, ex );
665                 }
666 
667                 //
668                 // make sure the agreement id was not changed
669                 //
670                 AgreementPropertiesType agreementProperties =
671                     persistenceContext.getPersistenceAgreementContext().getAgreementProperties();
672 
673                 agreementProperties.setAgreementId( agreementId );
674                 persistentAgreementContainer.agreementClassName = agreementClassName;
675                 persistentAgreementContainer.agreementFactoryId = agreementFactoryId;
676                 persistentAgreementContainer.agreementId = agreementId;
677                 persistentAgreementContainer.id = id;
678                 persistentAgreementContainer.persistedAgreementContextType = persistenceContext.xmlText();
679                 persistentAgreementContainer.persistenceContext = persistenceContext;
680                 persistentAgreementContainer.state =
681                     agreementProperties.getAgreementState().getState().toString();
682 
683                 em.merge( persistentAgreementContainer );
684 
685                 em.getTransaction().commit();
686             }
687             catch ( Exception ex )
688             {
689                 LOG.error( LogMessage.getMessage( "Could not update the wrapped agreement with id ''{0}''.",
690                     getAgreementId() ), ex );
691 
692                 // roll back the persistment
693                 em.getTransaction().rollback();
694 
695                 throw new AgreementFactoryException( MessageFormat.format(
696                     "Could not persist the wrapped agreement with id ''{0}''.", getAgreementId() ) );
697             }
698 
699         }
700         finally
701         {
702             em.close();
703         }
704     }
705 
706     /**
707      * Deletes this container instance.
708      * 
709      * @throws AgreementFactoryException
710      *             indicates an error while deleting the container
711      */
712     public void deleteContainer() throws AgreementFactoryException
713     {
714         // try to persist the wrapped agreement
715         EntityManager em = EmfRegistry.getEntityManager();
716         try
717         {
718             em.getTransaction().begin();
719             try
720             {
721                 Query query = em.createNamedQuery( "PersistentAgreementContainer.findByAgreementId" );
722                 query.setParameter( "agreementId", agreementId );
723 
724                 try
725                 {
726                     PersistentAgreementContainer persistentAgreementContainer =
727                         (PersistentAgreementContainer) query.getSingleResult();
728                     em.remove( persistentAgreementContainer );
729                 }
730                 catch ( NoResultException ex )
731                 {
732                     LOG.warn( "Persisted agreement not found in database. Remove operation skipped." );
733                 }
734 
735                 em.getTransaction().commit();
736             }
737             catch ( Exception ex )
738             {
739                 LOG.error( LogMessage.getMessage( "Could not delete the wrapped agreement with id ''{0}''.",
740                     getAgreementId() ), ex );
741 
742                 // roll back the persistment
743                 em.getTransaction().rollback();
744 
745                 throw new AgreementFactoryException( MessageFormat.format(
746                     "Could not persist the wrapped agreement with id ''{0}''.", getAgreementId() ) );
747             }
748 
749         }
750         finally
751         {
752             em.close();
753         }
754     }
755 
756     /*
757      * (non-Javadoc)
758      * 
759      * @see java.lang.Object#toString()
760      */
761     @Override
762     public String toString()
763     {
764         return persistenceContext.xmlText( new XmlOptions().setSavePrettyPrint() );
765     }
766 
767 }