44 */
55package org .hibernate .type .format .jackson ;
66
7+ import java .util .List ;
8+
9+ import com .fasterxml .jackson .databind .Module ;
10+ import com .fasterxml .jackson .databind .ObjectMapper ;
711import org .checkerframework .checker .nullness .qual .Nullable ;
12+
813import org .hibernate .type .format .FormatMapper ;
914import org .hibernate .type .format .FormatMapperCreationContext ;
1015
@@ -36,72 +41,37 @@ private static boolean ableToLoadJacksonXMLMapper() {
3641 */
3742 private static boolean ableToLoadJacksonOSONFactory () {
3843 return ableToLoadJacksonJSONMapper () &&
39- canLoad ( "oracle.jdbc.provider.oson.OsonFactory" );
44+ canLoad ( "oracle.jdbc.provider.oson.OsonFactory" );
4045 }
4146
4247 public static @ Nullable FormatMapper getXMLJacksonFormatMapperOrNull (FormatMapperCreationContext creationContext ) {
4348 return JACKSON_XML_AVAILABLE
44- ? createFormatMapper ( "org.hibernate.type.format.jackson. JacksonXmlFormatMapper" , creationContext )
49+ ? new JacksonXmlFormatMapper ( creationContext )
4550 : null ;
4651 }
4752
4853 public static @ Nullable FormatMapper getJsonJacksonFormatMapperOrNull (FormatMapperCreationContext creationContext ) {
4954 return JACKSON_JSON_AVAILABLE
50- ? createFormatMapper ( "org.hibernate.type.format.jackson. JacksonJsonFormatMapper" , creationContext )
55+ ? new JacksonJsonFormatMapper ( creationContext )
5156 : null ;
5257 }
5358 public static @ Nullable FormatMapper getOsonJacksonFormatMapperOrNull (FormatMapperCreationContext creationContext ) {
5459 return JACKSON_OSON_AVAILABLE
55- ? createFormatMapper ( "org.hibernate.type.format.jackson. JacksonOsonFormatMapper" , creationContext )
60+ ? new JacksonOsonFormatMapper ( creationContext )
5661 : null ;
5762 }
5863
59- public static @ Nullable FormatMapper getXMLJacksonFormatMapperOrNull (boolean legacyFormat ) {
60- if ( JACKSON_XML_AVAILABLE ) {
61- try {
62- final Class <?> formatMapperClass = JacksonIntegration .class .getClassLoader ()
63- .loadClass ( "org.hibernate.type.format.jackson.JacksonXmlFormatMapper" );
64- return (FormatMapper ) formatMapperClass .getDeclaredConstructor ( boolean .class )
65- .newInstance ( legacyFormat );
66- }
67- catch (Exception e ) {
68- throw new RuntimeException ( "Couldn't instantiate Jackson XML FormatMapper" , e );
69- }
70- }
71- return null ;
72- }
73-
7464 public static @ Nullable FormatMapper getJsonJacksonFormatMapperOrNull () {
7565 return JACKSON_JSON_AVAILABLE
76- ? createFormatMapper ( "org.hibernate.type.format.jackson. JacksonJsonFormatMapper" , null )
66+ ? new JacksonJsonFormatMapper ( )
7767 : null ;
7868 }
7969 public static @ Nullable FormatMapper getOsonJacksonFormatMapperOrNull () {
8070 return JACKSON_OSON_AVAILABLE
81- ? createFormatMapper ( "org.hibernate.type.format.jackson. JacksonOsonFormatMapper" , null )
71+ ? new JacksonOsonFormatMapper ( )
8272 : null ;
8373 }
8474
85- private static FormatMapper createFormatMapper (String className , @ Nullable FormatMapperCreationContext creationContext ) {
86- try {
87- if ( creationContext == null ) {
88- final Class <?> formatMapperClass = JacksonIntegration .class .getClassLoader ()
89- .loadClass ( className );
90- return (FormatMapper ) formatMapperClass .getDeclaredConstructor ().newInstance ();
91- }
92- else {
93- return (FormatMapper ) creationContext .getBootstrapContext ()
94- .getClassLoaderAccess ()
95- .classForName ( className )
96- .getDeclaredConstructor ( FormatMapperCreationContext .class )
97- .newInstance ( creationContext );
98- }
99- }
100- catch (Exception e ) {
101- throw new RuntimeException ( "Couldn't instantiate Jackson FormatMapper" , e );
102- }
103- }
104-
10575 /**
10676 * Checks that Oracle OSON extension available
10777 *
@@ -124,4 +94,27 @@ private static boolean canLoad(String name) {
12494 return false ;
12595 }
12696 }
97+
98+ static List <Module > loadModules (FormatMapperCreationContext creationContext ) {
99+ final ClassLoader classLoader = JacksonIntegration .class .getClassLoader ();
100+ final ClassLoader contextClassLoader = Thread .currentThread ().getContextClassLoader ();
101+ if ( contextClassLoader != null && classLoader != contextClassLoader ) {
102+ try {
103+ // The context class loader represents the application class loader in a Jakarta EE deployment.
104+ // We have to check if the ObjectMapper that is visible to Hibernate ORM is the same that is visible
105+ // to the application class loader. Only if it is, we can use the application class loader or rather
106+ // our AggregatedClassLoader for loading Jackson Module via ServiceLoader, as otherwise the loaded
107+ // Jackson Module instances would have a different class loader, leading to a ClassCastException.
108+ if ( ObjectMapper .class == contextClassLoader .loadClass ( "com.fasterxml.jackson.databind.ObjectMapper" ) ) {
109+ return creationContext .getBootstrapContext ()
110+ .getClassLoaderService ()
111+ .<List <Module >>workWithClassLoader ( ObjectMapper ::findModules );
112+ }
113+ }
114+ catch (ClassNotFoundException | LinkageError e ) {
115+ // Ignore if the context/application class loader doesn't know Jackson classes
116+ }
117+ }
118+ return ObjectMapper .findModules ( classLoader );
119+ }
127120}
0 commit comments