From 256ffec5ca0630e03a556e662b67e2df876d74c8 Mon Sep 17 00:00:00 2001 From: Ivan Gomes Date: Sun, 7 Jun 2020 21:34:51 -0700 Subject: [PATCH 1/2] ST5AS-61 Fix ClassNotFoundException due to Hibernate proxies and JSON-LD serialization --- app/dao/impl/jpa/JpaCommitDao.java | 55 ++++++++++++++++++----------- app/dao/impl/jpa/JpaElementDao.java | 23 +++++++----- 2 files changed, 48 insertions(+), 30 deletions(-) diff --git a/app/dao/impl/jpa/JpaCommitDao.java b/app/dao/impl/jpa/JpaCommitDao.java index 670183dd..fcb0413a 100644 --- a/app/dao/impl/jpa/JpaCommitDao.java +++ b/app/dao/impl/jpa/JpaCommitDao.java @@ -23,19 +23,26 @@ import javax.persistence.criteria.Root; import java.lang.reflect.Method; import java.util.*; -import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; +import java.util.function.UnaryOperator; import java.util.stream.Collectors; import java.util.stream.Stream; @Singleton public class JpaCommitDao extends JpaDao implements CommitDao { // TODO Explore alternative to serializing lazy entity attributes that doesn't involve resolving all proxies one level. - static Consumer PROXY_RESOLVER = commit -> commit.getChanges().stream() - .filter(Objects::nonNull).map(ElementVersion::getData) - .filter(mof -> mof instanceof Element).map(mof -> (Element) mof) - .forEach(JpaElementDao.PROXY_RESOLVER); + static UnaryOperator PROXY_RESOLVER = commit -> { + commit.getChanges().stream() + .filter(Objects::nonNull) + .map(ElementVersion::getData) + .filter(mof -> mof instanceof Element) + .map(mof -> (Element) mof) + .map(JpaElementDao.PROXY_RESOLVER) + .forEach(e -> { + }); + return commit; + }; @Inject private JPAManager jpa; @@ -172,19 +179,27 @@ public void setIdentifier(UUID identifier) { });*/ return jpa.transact(em -> { - commit.getChanges().stream().map(ElementVersion::getData).filter(mof -> mof instanceof MofObjectImpl).map(mof -> (MofObjectImpl) mof).map(mof -> { - try { - MofObjectImpl firstPassMof = mof.getClass().getConstructor().newInstance(); - firstPassMof.setKey(mof.getKey()); - return firstPassMof; - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } - }).forEach(em::merge); - commit.setChanges(commit.getChanges().stream().map(em::merge).collect(Collectors.toSet())); + commit.getChanges().stream() + .map(ElementVersion::getData) + .filter(mof -> mof instanceof MofObjectImpl) + .map(mof -> (MofObjectImpl) mof) + .map(mof -> { + try { + MofObjectImpl firstPassMof = mof.getClass().getConstructor().newInstance(); + firstPassMof.setKey(mof.getKey()); + return firstPassMof; + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + }) + .forEach(em::merge); + commit.setChanges( + commit.getChanges().stream() + .map(em::merge) + .collect(Collectors.toSet()) + ); Optional persistedCommit = super.persist(commit, em); - persistedCommit.ifPresent(PROXY_RESOLVER); - return persistedCommit; + return persistedCommit.map(PROXY_RESOLVER); }); } @@ -253,8 +268,7 @@ public Optional findByProjectAndId(Project project, UUID id) { } catch (NoResultException e) { return Optional.empty(); } - commit.ifPresent(PROXY_RESOLVER); - return commit; + return commit.map(PROXY_RESOLVER); }); } @@ -273,8 +287,7 @@ public Optional findHeadByProject(Project project) { } catch (NoResultException e) { return Optional.empty(); } - commit.ifPresent(PROXY_RESOLVER); - return commit; + return commit.map(PROXY_RESOLVER); }); } diff --git a/app/dao/impl/jpa/JpaElementDao.java b/app/dao/impl/jpa/JpaElementDao.java index 00f70310..09a58a41 100644 --- a/app/dao/impl/jpa/JpaElementDao.java +++ b/app/dao/impl/jpa/JpaElementDao.java @@ -26,15 +26,21 @@ import javax.persistence.criteria.*; import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Consumer; import java.util.function.Function; +import java.util.function.UnaryOperator; import java.util.stream.Collectors; import java.util.stream.Stream; @Singleton public class JpaElementDao extends JpaDao implements ElementDao { // TODO Explore alternative to serializing lazy entity attributes that doesn't involve resolving all proxies one level. - static Consumer PROXY_RESOLVER = element -> JavaBeanHelper.getBeanPropertyValues(element).values().stream().flatMap(o -> o instanceof Collection ? ((Collection) o).stream() : Stream.of(o)).filter(o -> o instanceof Element).map(o -> (Element) o).forEach(Hibernate::unproxy); + static UnaryOperator PROXY_RESOLVER = element -> { + element = Hibernate.unproxy(element, Element.class); + JavaBeanHelper.getBeanPropertyValues(element).values().stream() + .flatMap(o -> o instanceof Collection ? ((Collection) o).stream() : Stream.of(o)).filter(o -> o instanceof Element) + .map(o -> (Element) o).forEach(Hibernate::unproxy); + return element; + }; @Inject private MetamodelProvider metamodelProvider; @@ -96,7 +102,7 @@ public Set findAllByCommit(Commit commit) { .map(ElementVersion::getData) .filter(mof -> mof instanceof Element) .map(mof -> (Element) mof) - .peek(PROXY_RESOLVER) + .map(PROXY_RESOLVER) .collect(Collectors.toSet()); }); } @@ -119,11 +125,10 @@ public Optional findByCommitAndId(Commit commit, UUID id) { ); try { return Optional.of(em.createQuery(query).getSingleResult()) - .map(ElementVersion::getData).filter(mof -> mof instanceof Element) - .map(mof -> (Element) mof).map(element -> { - PROXY_RESOLVER.accept(element); - return element; - }); + .map(ElementVersion::getData) + .filter(mof -> mof instanceof Element) + .map(mof -> (Element) mof) + .map(PROXY_RESOLVER); } catch (NoResultException e) { return Optional.empty(); } @@ -140,7 +145,7 @@ public Set findRootsByCommit(Commit commit) { .filter(mof -> mof instanceof Element) .map(mof -> (Element) mof) .filter(element -> element.getOwner() == null) - .peek(PROXY_RESOLVER) + .map(PROXY_RESOLVER) .collect(Collectors.toSet()); }); } From 63ab490da1f84044d6eb7b09fc45caec6fba9fc1 Mon Sep 17 00:00:00 2001 From: Ivan Gomes Date: Sun, 7 Jun 2020 21:37:48 -0700 Subject: [PATCH 2/2] Update version number to 2020-05-p1 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index cc3cba8a..a1fa9607 100644 --- a/build.sbt +++ b/build.sbt @@ -1,7 +1,7 @@ name := """SysML-v2-API-Services""" organization := "org.omg" -version := "2020-05" +version := "2020-05-p1" javacOptions ++= Seq("-source", "11", "-target", "11", "-Xlint")