title: Implementing Spring Transactions with JAX-RS and Hibernate
body: <h2>Background</h2>
  
  <p>I am trying to implement a RESTful web service using Apache-CXF that interacts with a database to do some CRUD operations via Hibernate.  The web service consumes and produces JSON formatted objects using the Jackson JAX-RS Provider.</p>
  
  <p>I am currently receiving a <em>"failed to lazily initialize a collection... no session or session was closed"</em> exception that is bubbling up from the Jackson provider when it attempts to serialize the response object.</p>
  
  <p>I assumed that if I marked the service method with <code>@Transactional</code> that the session would be available to the Jackson provider when it serialized the response, but that does not appear to be the case.</p>
  
  <h2>Question</h2>
  
  <p>How do I get the hibernate session to be available while Jackson is walking the object during serialization?</p>
  
  <h2>What I've Tried</h2>
  
  <h3>Spring Configuration</h3>
  
  <pre><code>&lt;context:component-scan base-package="com.db.cif.mapper" /&gt;
  &lt;context:component-scan base-package="com.db.cif.mapper.repository" /&gt;
  &lt;context:annotation-config /&gt;
  
  &lt;tx:jta-transaction-manager&gt;
      &lt;property name="entityManagerFactory" ref="entityManagerFactory" /&gt;
  &lt;/tx:jta-transaction-manager&gt;
  
  &lt;tx:annotation-driven /&gt;
  
  &lt;bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"&gt;
      &lt;property name="persistenceUnitName" value="cifmapper" /&gt;
      &lt;property name="jpaDialect"&gt;
          &lt;bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" /&gt;
      &lt;/property&gt;
  &lt;/bean&gt;
  
  &lt;!-- JAX-RS Configuration --&gt;
  &lt;jaxrs:server id="mappingService" address="/"&gt;
      &lt;jaxrs:serviceBeans&gt;
          &lt;ref bean="mappingServiceBean" /&gt;
      &lt;/jaxrs:serviceBeans&gt;
      &lt;jaxrs:extensionMappings&gt;
          &lt;entry key="json" value="application/json" /&gt;
      &lt;/jaxrs:extensionMappings&gt;
      &lt;jaxrs:providers&gt;
          &lt;ref bean="jsonProvider" /&gt;
      &lt;/jaxrs:providers&gt;
  &lt;/jaxrs:server&gt;
  
  &lt;bean id="mappingServiceBean" class="com.db.cif.mapper.MappingService" /&gt;
  
  &lt;bean id="jsonProvider" class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" /&gt;
  </code></pre>
  
  <h3>Service Bean</h3>
  
  <pre><code>@Service("mappingService")
  @Transactional
  public class MappingService 
  {
      private static final Logger logger = Logger.getLogger(MappingService.class);
  
      @Autowired
      @Qualifier("mappingRepository")
      private MappingRepository mappingRepository;
  
      @GET
      @Path("/collections/{id}")
      @Produces(MediaType.APPLICATION_JSON)
      public Collection getCollection(@PathParam("id") String id)
      {
          if(logger.isDebugEnabled())
          {
              logger.debug(String.format("Invoked getCollection, Collection id: %s", id));
          }
  
          return this.mappingRepository.getCollection(id);
      }
  
      @POST
      @Path("/collections/")
      @Consumes(MediaType.APPLICATION_JSON)
      public Response addCollection(Collection collection)
      {
          if(logger.isDebugEnabled())
          {
              logger.debug(String.format("Invoked addCollection, Collection: %s", collection));
          }
  
          this.mappingRepository.createCollection(collection);
  
          return Response.ok(collection).build();
      }
  }
  </code></pre>
  
  <h3>Collection Bean</h3>
  
  <pre><code>@Entity
  @Table(schema = "CIFMAPPER", name = "COLLECTION")
  public class Collection implements Serializable
  {
      private static final long serialVersionUID = 1579878442412232635L;
  
      @Id
      @Column(name = "ID")
      private String id;
  
      @Column(name = "SRC_ENDPT_ID", nullable = false, insertable = false, updatable = false)
      private long sourceEndpointId;
  
      @Column(name = "DEST_ENDPT_ID", nullable = false, insertable = false, updatable = false)
      private long destinationEndpointId;
  
      @Column(name = "DESCRIPTION")
      private String description;
  
      @Column(name = "START_DATE", nullable = false)
      private Date startDate;
  
      @Column(name = "END_DATE")
      private Date endDate;
  
      @ManyToOne(optional = false)
      @JoinColumn(name = "SRC_ENDPT_ID")
      private Endpoint source;
  
      @ManyToOne(optional = false)
      @JoinColumn(name = "DEST_ENDPT_ID")
      private Endpoint destination;
  
      @OneToMany(mappedBy = "collection", targetEntity = MappingGroup.class, fetch = FetchType.EAGER)
      private List&lt;MappingGroup&gt; mappingGroups;
  
  //Getters and Setters Removed For Brevity
  }
  </code></pre>