Bug 472475: Make bean validation dependency optional is OSGi environment

Signed-off-by: Lukas Jungmann <lukas.jungmann@oracle.com>
Reviewed-by: Petros, Ondrej
diff --git a/moxy/eclipselink.moxy.test/antbuild.xml b/moxy/eclipselink.moxy.test/antbuild.xml
index f20dbbb..2013b80 100644
--- a/moxy/eclipselink.moxy.test/antbuild.xml
+++ b/moxy/eclipselink.moxy.test/antbuild.xml
@@ -328,6 +328,47 @@
     <target name="compile-and-run-oxm-deploymentxml-tl-tests" depends="compile-tests" description="build and run moxy (oxm) tl deployment xml tests">
         <run_oxm_deploymentxml_tl_tests runpathref="oxm.run.path"/>
     </target>
+
+    <target name="init-osgi">
+        <property environment="env"/>
+        <condition property="m2.home.exists" value="true">
+            <isset property="env.M2_HOME"/>
+        </condition>
+        <condition property="M2_HOME" value="${env.M2_HOME}">
+            <isset property="m2.home.exists"/>
+        </condition>
+    </target>
+    <target name="check-osgi" unless="m2.home.exists">
+        <echo message="Skipping OSGi Tests. M2_HOME is not set."/>
+    </target>
+    <target name="compile-and-run-osgi-tests">
+        <condition property="version.qualifier" value="${version.qualifier}" else="qualifier">
+            <isset property="version.qualifier"/>
+        </condition>
+        <echo message="Launching Maven build with the following parameters:"/>
+        <echo message="    -Dclassworlds.conf=${M2_HOME}/bin/m2.conf"/>
+        <echo message="    -Dmaven.home=${M2_HOME}"/>
+        <echo message="    -Dbuild.qualifier=${version.qualifier}"/>
+        <java dir="${basedir}" fork="true" failonerror="true" classname="org.codehaus.plexus.classworlds.launcher.Launcher">
+            <jvmarg value="-Dclassworlds.conf=${M2_HOME}/bin/m2.conf"/>
+            <jvmarg value="-Dmaven.home=${M2_HOME}"/>
+            <!--<arg line="-Dmaven.surefire.debug clean install"/>-->
+            <arg line="clean install"/>
+            <arg line="-Dmoxytest.2.common.plugins.dir=${basedir}/../../plugins/"/>
+            <arg line="-Djavax.validation.lib=${basedir}/${javax.validation.lib}"/>
+            <arg line="-Dbuild.qualifier=${version.qualifier}"/>
+            <arg line="-Drelease.version=${release.version}"/>
+            <arg line="-Djaxb-api.jar=${jaxb-api.jar}"/>
+            <arg line="-Djaxrs.jar=${jaxrs.jar}"/>
+            <arg line="-Dasm.jar=${asm.jar}"/>
+            <classpath>
+                <fileset dir="${M2_HOME}/boot">
+                    <include name="plexus-classworlds-*.jar"/>
+                </fileset>
+            </classpath>
+        </java>
+    </target>
+
     <target name="run-installer-tests">
         <tempfile property="unzip.temp.file" destDir="${java.io.tmpdir}" prefix="build"/>
         <mkdir dir="${unzip.temp.file}"/>
diff --git a/moxy/eclipselink.moxy.test/moxy.test.iml b/moxy/eclipselink.moxy.test/moxy.test.iml
index 5015693..3b095b3 100644
--- a/moxy/eclipselink.moxy.test/moxy.test.iml
+++ b/moxy/eclipselink.moxy.test/moxy.test.iml
@@ -257,5 +257,52 @@
         <SOURCES />
       </library>
     </orderEntry>
+    <orderEntry type="module-library">
+      <library>
+        <CLASSES>
+          <root url="jar://$MAVEN_REPOSITORY$/org/ops4j/pax/exam/pax-exam/4.5.0/pax-exam-4.5.0.jar!/" />
+        </CLASSES>
+        <JAVADOC />
+        <SOURCES />
+      </library>
+    </orderEntry>
+    <orderEntry type="module-library">
+      <library>
+        <CLASSES>
+          <root url="jar://$MAVEN_REPOSITORY$/org/ops4j/pax/exam/pax-exam-junit4/4.5.0/pax-exam-junit4-4.5.0.jar!/" />
+        </CLASSES>
+        <JAVADOC />
+        <SOURCES />
+      </library>
+    </orderEntry>
+    <orderEntry type="module-library">
+      <library>
+        <CLASSES>
+          <root url="jar://$MAVEN_REPOSITORY$/org/ops4j/pax/exam/pax-exam-spi/4.5.0/pax-exam-spi-4.5.0.jar!/" />
+        </CLASSES>
+        <JAVADOC />
+        <SOURCES />
+      </library>
+    </orderEntry>
+    <orderEntry type="module-library">
+      <library>
+        <CLASSES>
+          <root url="jar://$MAVEN_REPOSITORY$/org/osgi/org.osgi.core/6.0.0/org.osgi.core-6.0.0.jar!/" />
+        </CLASSES>
+        <JAVADOC />
+        <SOURCES>
+          <root url="jar://$MAVEN_REPOSITORY$/org/osgi/org.osgi.core/6.0.0/org.osgi.core-6.0.0.jar!/OSGI-OPT/src" />
+        </SOURCES>
+      </library>
+    </orderEntry>
+    <orderEntry type="module-library">
+      <library>
+        <CLASSES>
+          <root url="jar://$MAVEN_REPOSITORY$/org/glassfish/hk2/external/javax.inject/2.1.64/javax.inject-2.1.64.jar!/" />
+        </CLASSES>
+        <JAVADOC />
+        <SOURCES />
+      </library>
+    </orderEntry>
   </component>
 </module>
\ No newline at end of file
diff --git a/moxy/eclipselink.moxy.test/pom.xml b/moxy/eclipselink.moxy.test/pom.xml
new file mode 100644
index 0000000..9a60c3c
--- /dev/null
+++ b/moxy/eclipselink.moxy.test/pom.xml
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <modelVersion>4.0.0</modelVersion>
+
+    <name>EclipseLink MOXy OSGi Tests</name>
+    <groupId>org.eclipse.persistence</groupId>
+    <artifactId>eclipselink.moxy.test</artifactId>
+    <description>Tests for MOXy OSGi bundles</description>
+    <version>2.6.3-SNAPSHOT</version>
+
+    <properties>
+        <exam.version>4.5.0</exam.version>
+        <url.version>2.4.1</url.version>
+        <logback.version>1.1.3</logback.version>
+        <eclipselink.version>2.6.3-SNAPSHOT</eclipselink.version>
+    </properties>
+
+    <dependencies>
+        <!-- EclipseLink -->
+        <dependency>
+            <groupId>org.eclipse.persistence</groupId>
+            <artifactId>eclipselink</artifactId>
+            <version>${eclipselink.version}</version>
+            <scope>system</scope>
+            <systemPath>${basedir}/../../eclipselink.jar</systemPath>
+        </dependency>
+
+        <!-- Bean validation API -->
+        <dependency>
+            <groupId>javax.validation</groupId>
+            <artifactId>validation</artifactId>
+            <version>1.1</version>
+            <scope>system</scope>
+            <systemPath>${javax.validation.lib}</systemPath>
+        </dependency>
+
+        <!-- Hibernate validator and it's dependencies -->
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-validator</artifactId>
+            <version>5.2.0.CR1</version>
+        </dependency>
+        <dependency>
+            <groupId>javax.el</groupId>
+            <artifactId>javax.el-api</artifactId>
+            <version>3.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-api</artifactId>
+            <version>2.3</version>
+        </dependency>
+
+        <!-- javax.inject -->
+        <dependency>
+            <groupId>javax.inject</groupId>
+            <artifactId>javax.inject</artifactId>
+            <version>1</version>
+        </dependency>
+
+        <!-- Felix -->
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.framework</artifactId>
+            <version>5.0.0</version>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- PaxExam -->
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-container-native</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-junit4</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-link-mvn</artifactId>
+            <version>${exam.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.url</groupId>
+            <artifactId>pax-url-aether</artifactId>
+            <version>${url.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- Logging, required by Pax -->
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-core</artifactId>
+            <version>${logback.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <version>${logback.version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <testSourceDirectory>src/org/eclipse/persistence/testing/osgi</testSourceDirectory>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.3</version>
+                <configuration>
+                    <source>1.7</source>
+                    <target>1.7</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>prepare-osgi-bundles</id>
+                        <phase>generate-test-resources</phase>
+                        <goals>
+                            <goal>copy-dependencies</goal>
+                        </goals>
+                        <configuration>
+                            <outputDirectory>${project.build.directory}/testedBundles</outputDirectory>
+                            <stripVersion>true</stripVersion>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>2.13</version>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/beanvalidation/BeanValidationRuntimeTestCase.java b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/beanvalidation/BeanValidationRuntimeTestCase.java
index 3b0ca0a..15088a9 100644
--- a/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/beanvalidation/BeanValidationRuntimeTestCase.java
+++ b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/beanvalidation/BeanValidationRuntimeTestCase.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -14,6 +14,7 @@
 
 import org.eclipse.persistence.exceptions.BeanValidationException;
 import org.eclipse.persistence.jaxb.BeanValidationMode;
+import org.eclipse.persistence.jaxb.ConstraintViolationWrapper;
 import org.eclipse.persistence.jaxb.JAXBContextFactory;
 import org.eclipse.persistence.jaxb.JAXBContextProperties;
 import org.eclipse.persistence.jaxb.JAXBMarshaller;
@@ -27,7 +28,6 @@
 import org.junit.After;
 import org.junit.Before;
 
-import javax.validation.ConstraintViolation;
 import javax.validation.Validation;
 import javax.validation.ValidatorFactory;
 import javax.validation.groups.Default;
@@ -155,7 +155,7 @@
 
         /* Marshal w/o validation - creates file for the next part of the test. */
         marshallerValidOff.marshal(employeeInvalid, fileInvalid);
-        Set<? extends ConstraintViolation<?>> marshalCV = marshallerValidOff.getConstraintViolations();
+        Set<ConstraintViolationWrapper<Object>> marshalCV = marshallerValidOff.getConstraintViolations();
         assertTrue(marshalCV.isEmpty());
 
         /* Unmarshal w/ validation - doesn't pass (we want to check that). */
@@ -187,11 +187,12 @@
         assertEquals(employeeInvalid, employeeUnm);
     }
 
-    private void checkValidationMessages(Set<? extends ConstraintViolation<?>> constraintViolations,
+    private void checkValidationMessages(Set<ConstraintViolationWrapper<Object>> constraintViolations,
                                          List<String> expectedMessages) {
         List<String> violationMessages = new ArrayList<>();
-        for (final ConstraintViolation<?> cv : constraintViolations)
+        for (final ConstraintViolationWrapper cv : constraintViolations) {
             violationMessages.add(cv.getMessageTemplate());
+        }
 
         assertSame(expectedMessages.size(), violationMessages.size());
         assertTrue(violationMessages.containsAll(expectedMessages));
diff --git a/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/beanvalidation/BeanValidationSpecialtiesTestCase.java b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/beanvalidation/BeanValidationSpecialtiesTestCase.java
index 675bc51..04e1508 100644
--- a/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/beanvalidation/BeanValidationSpecialtiesTestCase.java
+++ b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/beanvalidation/BeanValidationSpecialtiesTestCase.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -12,16 +12,11 @@
  ******************************************************************************/
 package org.eclipse.persistence.testing.jaxb.beanvalidation;
 
-import org.eclipse.persistence.exceptions.BeanValidationException;
-import org.eclipse.persistence.jaxb.BeanValidationHelper;
-import org.eclipse.persistence.jaxb.JAXBContext;
-import org.eclipse.persistence.jaxb.JAXBContextFactory;
-import org.eclipse.persistence.jaxb.JAXBContextProperties;
-import org.eclipse.persistence.jaxb.JAXBMarshaller;
-import org.eclipse.persistence.testing.jaxb.beanvalidation.special.ConstructorAnnotatedEmployee;
-import org.eclipse.persistence.testing.jaxb.beanvalidation.special.CustomAnnotatedEmployee;
-import org.eclipse.persistence.testing.jaxb.beanvalidation.special.MethodAnnotatedEmployee;
-import org.eclipse.persistence.testing.jaxb.beanvalidation.special.NonConstrainedClass;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
 
 import javax.validation.ConstraintValidatorFactory;
 import javax.validation.ConstraintViolation;
@@ -35,11 +30,18 @@
 import javax.validation.executable.ExecutableValidator;
 import javax.validation.metadata.BeanDescriptor;
 import javax.validation.metadata.ConstraintDescriptor;
-import java.io.StringWriter;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
+
+import org.eclipse.persistence.exceptions.BeanValidationException;
+import org.eclipse.persistence.jaxb.BeanValidationHelper;
+import org.eclipse.persistence.jaxb.ConstraintViolationWrapper;
+import org.eclipse.persistence.jaxb.JAXBContext;
+import org.eclipse.persistence.jaxb.JAXBContextFactory;
+import org.eclipse.persistence.jaxb.JAXBContextProperties;
+import org.eclipse.persistence.jaxb.JAXBMarshaller;
+import org.eclipse.persistence.testing.jaxb.beanvalidation.special.ConstructorAnnotatedEmployee;
+import org.eclipse.persistence.testing.jaxb.beanvalidation.special.CustomAnnotatedEmployee;
+import org.eclipse.persistence.testing.jaxb.beanvalidation.special.MethodAnnotatedEmployee;
+import org.eclipse.persistence.testing.jaxb.beanvalidation.special.NonConstrainedClass;
 
 /**
  * Test case storing non-standard tests, i.e. those that didn't fit neither in
@@ -67,13 +69,13 @@
         } catch (BeanValidationException ignored) {
         }
 
-        Set<? extends ConstraintViolation<?>> violations = marshaller.getConstraintViolations();
+        Set<ConstraintViolationWrapper<Object>> violations = marshaller.getConstraintViolations();
 
         assertFalse("Some constraints were not validated, even though they should have been.", violations.isEmpty());
 
         // For all, i.e. one constraintViolations.
-        for (ConstraintViolation constraintViolation : violations) {
-            assertEquals(CUSTOM_ANNOTATION_MESSAGE, constraintViolation.getMessage());
+        for (ConstraintViolationWrapper cv : violations) {
+            assertEquals(CUSTOM_ANNOTATION_MESSAGE, cv.getMessage());
         }
     }
 
@@ -88,16 +90,17 @@
 
         try {
             marshaller.marshal(employee, new StringWriter());
+            assertFalse("Constraints-breaking class escaped validation -> fail.", true);
         } catch (BeanValidationException ignored) {
         }
 
-        Set<? extends ConstraintViolation<?>> violations = marshaller.getConstraintViolations();
+        Set<ConstraintViolationWrapper<Object>> violations = marshaller.getConstraintViolations();
 
         assertFalse(violations.isEmpty());
 
         // For all, i.e. one constraintViolations.
-        for (ConstraintViolation constraintViolation : violations) {
-            assertEquals(NOT_NULL_MESSAGE, constraintViolation.getMessageTemplate());
+        for (ConstraintViolationWrapper cv : violations) {
+            assertEquals(NOT_NULL_MESSAGE, cv.getMessageTemplate());
         }
     }
 
@@ -149,7 +152,7 @@
         } catch (BeanValidationException ignored) {
         }
 
-        Set<? extends ConstraintViolation<?>> violations = marshaller.getConstraintViolations();
+        Set<ConstraintViolationWrapper<Object>> violations = marshaller.getConstraintViolations();
 
         assertFalse(violations.isEmpty());
     }
diff --git a/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/beanvalidation/ValidationXMLTestCase.java b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/beanvalidation/ValidationXMLTestCase.java
index 47c2c05..4901aaf 100644
--- a/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/beanvalidation/ValidationXMLTestCase.java
+++ b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/jaxb/beanvalidation/ValidationXMLTestCase.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -13,6 +13,8 @@
 package org.eclipse.persistence.testing.jaxb.beanvalidation;
 
 import org.eclipse.persistence.exceptions.BeanValidationException;
+import org.eclipse.persistence.internal.cache.AdvancedProcessor;
+import org.eclipse.persistence.jaxb.ConstraintViolationWrapper;
 import org.eclipse.persistence.jaxb.JAXBContextFactory;
 import org.eclipse.persistence.jaxb.JAXBMarshaller;
 import org.eclipse.persistence.testing.jaxb.beanvalidation.special.ExternallyConstrainedEmployee;
@@ -20,7 +22,6 @@
 import org.junit.After;
 import org.junit.Before;
 
-import javax.validation.ConstraintViolation;
 import javax.validation.Validation;
 import java.io.File;
 import java.io.IOException;
@@ -85,7 +86,7 @@
         } catch (BeanValidationException ignored) {
         }
 
-        Set<ConstraintViolation<Object>> violations = marshaller.getConstraintViolations();
+        Set<ConstraintViolationWrapper<Object>> violations = marshaller.getConstraintViolations();
 
         try {
             marshaller.marshal(employee2, new StringWriter());
@@ -97,9 +98,9 @@
         assertFalse("Some constraints were not validated, even though they should have been.", violations.isEmpty());
 
         int i = 0;
-        for (ConstraintViolation constraintViolation : violations) {
-            if (NOT_NULL_MESSAGE.equals(constraintViolation.getMessageTemplate())) i += 0b1000;
-            if (MIN_MESSAGE.equals(constraintViolation.getMessageTemplate())) i += 0b0001;
+        for (ConstraintViolationWrapper<Object> cv : violations) {
+            if (NOT_NULL_MESSAGE.equals(cv.getMessageTemplate())) i += 0b1000;
+            if (MIN_MESSAGE.equals(cv.getMessageTemplate())) i += 0b0001;
         }
         assertTrue(i == 0b1001);
     }
diff --git a/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/osgi/OSGITestHelper.java b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/osgi/OSGITestHelper.java
new file mode 100644
index 0000000..68e9396
--- /dev/null
+++ b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/osgi/OSGITestHelper.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Dmitry Kornilov - initial implementation
+ ******************************************************************************/
+package org.eclipse.persistence.testing.osgi;
+
+import org.ops4j.pax.exam.Option;
+
+import static org.ops4j.pax.exam.CoreOptions.bundle;
+import static org.ops4j.pax.exam.CoreOptions.cleanCaches;
+import static org.ops4j.pax.exam.CoreOptions.junitBundles;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+
+/**
+ * Helper class with PAX options for different kind of OSGi tests.
+ *
+ * @author Dmitry Kornilov
+ * @since 2.7.0
+ */
+public class OSGITestHelper {
+    // Environment variables defined in antbuild.properties/antbuild.xml
+    private static final String PLUGINS_DIR = System.getProperty("moxytest.2.common.plugins.dir");
+    private static final String QUALIFIER = System.getProperty("build.qualifier", "qualifier");
+    private static final String RELEASE_VERSION = System.getProperty("release.version", "2.7.0");
+    private static final String JAXB_API_JAR = System.getProperty("jaxb-api.jar", "javax.xml.bind_2.2.12.v201410011542.jar");
+    private static final String JAXRS_JAR = System.getProperty("jaxrs.jar", "javax.ws.rs_1.1.1.v20101004-1200.jar");
+    private static final String ASM_JAR = System.getProperty("asm.jar", "org.eclipse.persistence.asm_5.0.1.v201405080102.jar");
+    private static final String BEAN_VALIDATION_LIB = System.getProperty("javax.validation.lib", "javax.validation_1.1.0.v201304101302.jar");
+
+    public static Option[] getDefaultOptions() {
+        return options(
+                // JAXB API
+                bundle("file:" + PLUGINS_DIR + JAXB_API_JAR),
+
+                // JAX-RS API
+                bundle("file:" + PLUGINS_DIR + JAXRS_JAR),
+
+                // EclipseLink bundles
+                bundle("file:" + PLUGINS_DIR + "org.eclipse.persistence.moxy_" + RELEASE_VERSION + "." + QUALIFIER + ".jar"),
+                bundle("file:" + PLUGINS_DIR + "org.eclipse.persistence.core_" + RELEASE_VERSION + "." + QUALIFIER + ".jar"),
+                bundle("file:" + PLUGINS_DIR + ASM_JAR),
+
+                cleanCaches(),
+                junitBundles());
+    }
+
+    public static Option[] getOptionsWithBeanValidation() {
+        return options(
+                mavenBundle().groupId("org.hibernate").artifactId("hibernate-validator").version("5.2.0.CR1"),
+                mavenBundle().groupId("com.fasterxml").artifactId("classmate").version("1.1.0"),
+                mavenBundle().groupId("javax.el").artifactId("javax.el-api").version("3.0.0"),
+                mavenBundle().groupId("org.jboss.logging").artifactId("jboss-logging").version("3.2.1.Final"),
+                mavenBundle().groupId("org.apache.logging.log4j").artifactId("log4j-api").version("2.3"),
+                mavenBundle().groupId("org.apache.logging.log4j").artifactId("log4j-core").version("2.3"),
+
+                // JAXB API
+                bundle("file:" + PLUGINS_DIR + JAXB_API_JAR),
+
+                // JAX-RS API
+                bundle("file:" + PLUGINS_DIR + JAXRS_JAR),
+
+                // EclipseLink bundles
+                bundle("file:" + PLUGINS_DIR + "org.eclipse.persistence.moxy_" + RELEASE_VERSION + "." + QUALIFIER + ".jar"),
+                bundle("file:" + PLUGINS_DIR + "org.eclipse.persistence.core_" + RELEASE_VERSION + "." + QUALIFIER + ".jar"),
+                bundle("file:" + PLUGINS_DIR + ASM_JAR),
+                bundle("file:" + BEAN_VALIDATION_LIB),
+
+                cleanCaches(),
+                junitBundles()
+        );
+    }
+}
diff --git a/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/osgi/OSGiBundleTest.java b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/osgi/OSGiBundleTest.java
new file mode 100644
index 0000000..69393c7
--- /dev/null
+++ b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/osgi/OSGiBundleTest.java
@@ -0,0 +1,213 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Marcel Valovy - 2.6 - initial implementation
+ ******************************************************************************/
+package org.eclipse.persistence.testing.osgi;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.inject.Inject;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.Version;
+
+/**
+ * Tests that all MOXy exported bundles can be properly loaded by OSGi framework.
+ *
+ * @author Marcel Valovy - marcel.valovy@oracle.com
+ * @since 2.7.0
+ */
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+public class OSGiBundleTest {
+    // MOXy bundle symbolic name
+    private static final String MOXY_BUNDLE_NAME = "org.eclipse.persistence.moxy";
+
+    // MOXy bundle
+    private Bundle moxyBundle;
+
+    @Inject
+    private static BundleContext ctx;
+
+    @Configuration
+    public static Option[] config() {
+        return OSGITestHelper.getDefaultOptions();
+    }
+
+    @Test
+    public void testAsmVersion() {
+        Class<?> c = loadClass("org.eclipse.persistence.internal.libraries.asm.AnnotationVisitor");
+        assertClassLoadedByBundle(c, "org.eclipse.persistence.asm", "5.0.1.v201405080102");
+    }
+
+    @Test
+    public void testInternalJaxb() {
+        Class<?> c = loadClass("org.eclipse.persistence.internal.jaxb.AttributeNodeImpl");
+        assertClassLoadedByBundle(c, MOXY_BUNDLE_NAME);
+    }
+
+    @Test
+    public void testInternalJaxbMany() {
+        Class<?> c = loadClass("org.eclipse.persistence.internal.jaxb.many.ArrayValue");
+        assertClassLoadedByBundle(c, MOXY_BUNDLE_NAME);
+    }
+
+    @Test
+    public void testJaxb() {
+        Class<?> c = loadClass("org.eclipse.persistence.jaxb.JAXBContext");
+        assertClassLoadedByBundle(c, MOXY_BUNDLE_NAME);
+    }
+
+    @Test
+    public void testJaxbAttachment() {
+        Class<?> c = loadClass("org.eclipse.persistence.jaxb.attachment.AttachmentMarshallerAdapter");
+        assertClassLoadedByBundle(c, MOXY_BUNDLE_NAME);
+    }
+
+    @Test
+    public void testJaxbCompiler() {
+        Class<?> c = loadClass("org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor");
+        assertClassLoadedByBundle(c, MOXY_BUNDLE_NAME);
+    }
+
+    @Test
+    public void testJaxbDynamic() {
+        Class<?> c = loadClass("org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext");
+        assertClassLoadedByBundle(c, MOXY_BUNDLE_NAME);
+    }
+
+    @Test
+    public void testJaxbDynamicMetadata() {
+        Class<?> c = loadClass("org.eclipse.persistence.jaxb.dynamic.metadata.Metadata");
+        assertClassLoadedByBundle(c, MOXY_BUNDLE_NAME);
+    }
+
+    @Test
+    public void testJaxbJavamodel() {
+        Class<?> c = loadClass("org.eclipse.persistence.jaxb.javamodel.AnnotationProxy");
+        assertClassLoadedByBundle(c, MOXY_BUNDLE_NAME);
+    }
+
+    @Test
+    public void testJaxbJavamodelOxm() {
+        Class<?> c = loadClass("org.eclipse.persistence.jaxb.javamodel.oxm.OXMJavaClassImpl");
+        assertClassLoadedByBundle(c, MOXY_BUNDLE_NAME);
+    }
+
+    @Test
+    public void testJaxbJavamodelReflection() {
+        Class<?> c = loadClass("org.eclipse.persistence.jaxb.javamodel.reflection.AnnotationHelper");
+        assertClassLoadedByBundle(c, MOXY_BUNDLE_NAME);
+    }
+
+    @Test
+    public void testJaxbMetadata() throws ClassNotFoundException {
+        Class<?> c = loadClass("org.eclipse.persistence.jaxb.metadata.MetadataSource");
+        assertClassLoadedByBundle(c, MOXY_BUNDLE_NAME);
+    }
+
+    @Test
+    public void testJaxbRs() {
+        Class<?> c = loadClass("org.eclipse.persistence.jaxb.rs.MOXyJsonProvider");
+        assertClassLoadedByBundle(c, MOXY_BUNDLE_NAME);
+    }
+
+    @Test
+    public void testJaxbXmlmodel() {
+        Class<?> c = loadClass("org.eclipse.persistence.jaxb.xmlmodel.JavaAttribute");
+        assertClassLoadedByBundle(c, MOXY_BUNDLE_NAME);
+    }
+
+    @Test
+    public void testJavaxXmlParsers() {
+        Class<?> c = loadClass("javax.xml.parsers.ParserConfigurationException");
+        assertClassLoadedBySystemBundle(c);
+    }
+
+    @Test
+    public void testJavaxNaming() {
+        Class<?> c = loadClass("javax.naming.InitialContext");
+        assertClassLoadedBySystemBundle(c);
+    }
+
+    @Test
+    public void testOrgXmlSaxHelpers() {
+        Class<?> c = loadClass("org.xml.sax.helpers.DefaultHandler");
+        assertClassLoadedBySystemBundle(c);
+    }
+
+    /**
+     * Loads a class from MOXy bundle. Fails the test if not loaded.
+     */
+    private Class<?> loadClass(String className) {
+        try {
+            return getMoxyBundle().loadClass(className);
+        } catch (ClassNotFoundException ex) {
+            Logger.getLogger(OSGiBundleTest.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
+            Assert.fail("Cannot find and load class: " + className);
+        }
+        return null;
+    }
+
+    /**
+     * Returns MOXy bundle ('org.eclipse.persistence.moxy').
+     */
+    private Bundle getMoxyBundle() {
+        if (this.moxyBundle != null) {
+            return this.moxyBundle;
+        }
+
+        for (Bundle b : ctx.getBundles()) {
+            if (b.getSymbolicName().equals(MOXY_BUNDLE_NAME)) {
+                this.moxyBundle = b;
+                return b;
+            }
+        }
+
+        return null;
+    }
+
+    private void assertClassLoadedBySystemBundle(Class<?> c) {
+        Assert.assertNotNull(c);
+
+        // Class is there but loaded from the system bundle
+        Assert.assertNull("Class " + c.getName() + " was not loaded from JDK", FrameworkUtil.getBundle(c));
+    }
+
+    private void assertClassLoadedByBundle(Class<?> c, String bundle) {
+        Assert.assertNotNull(c);
+        Bundle b = FrameworkUtil.getBundle(c);
+        Assert.assertEquals("Class '" + c.getName() + "' was loaded by '" + b.getSymbolicName() +
+                        "', expected was '" + bundle + "'", bundle, b.getSymbolicName());
+        Assert.assertEquals("Bundle '" + bundle + "' is not running", Bundle.ACTIVE, b.getState());
+    }
+
+    private void assertClassLoadedByBundle(Class<?> c, String bundle, String version) {
+        Bundle b = FrameworkUtil.getBundle(c);
+        Version v = b.getVersion();
+        Assert.assertEquals("Class '" + c.getName() + "' was loaded by '" + b.getSymbolicName() +
+                        "', expected was '" + bundle + "'", bundle, b.getSymbolicName());
+        Assert.assertEquals("Class '" + c.getName() + "' was loaded by '"  + b.getSymbolicName() + "', version '"
+                        + v.toString() + "' expected was '" + bundle + "', version '" + v.toString() + "'.", version, v.toString());
+        Assert.assertEquals("Bundle '" + bundle + "' is not running", Bundle.ACTIVE, b.getState());
+    }
+}
\ No newline at end of file
diff --git a/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/osgi/beanvalidation/BaseBeanValidationTest.java b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/osgi/beanvalidation/BaseBeanValidationTest.java
new file mode 100644
index 0000000..1b499cc
--- /dev/null
+++ b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/osgi/beanvalidation/BaseBeanValidationTest.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Dmitry Kornilov - initial implementation
+ ******************************************************************************/
+package org.eclipse.persistence.testing.osgi.beanvalidation;
+
+/**
+ * Base class for OSGi bean validation tests. Contains test data.
+ *
+ * @author Dmitry Kornilov
+ * @since 2.7.0
+ */
+public class BaseBeanValidationTest {
+    static final String CUSTOMER_VALID_XML = "<customer id=\"1\"><name>John Doe</name></customer>";
+    static final String CUSTOMER_INVALID_XML = "<customer><name>X</name></customer>";
+
+    Customer createInvalidCustomer() {
+        Customer customer = new Customer();
+        customer.setId(null);
+        customer.setName("X");
+        return customer;
+    }
+
+    Customer createValidCustomer() {
+        Customer customer = new Customer();
+        customer.setId("1");
+        customer.setName("John Doe");
+        return customer;
+    }
+}
diff --git a/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/osgi/beanvalidation/BeanValidationTest.java b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/osgi/beanvalidation/BeanValidationTest.java
new file mode 100644
index 0000000..4060f2f
--- /dev/null
+++ b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/osgi/beanvalidation/BeanValidationTest.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Dmitry Kornilov - initial implementation
+ ******************************************************************************/
+package org.eclipse.persistence.testing.osgi.beanvalidation;
+
+import org.eclipse.persistence.exceptions.BeanValidationException;
+import org.eclipse.persistence.jaxb.JAXBContextFactory;
+import org.eclipse.persistence.jaxb.MarshallerProperties;
+import org.eclipse.persistence.testing.osgi.OSGITestHelper;
+import org.hibernate.validator.HibernateValidator;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+
+import javax.validation.Validation;
+import javax.validation.ValidationProviderResolver;
+import javax.validation.ValidatorFactory;
+import javax.validation.spi.ValidationProvider;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Marshal/unmarshal + validation tests in OSGi container with installed bean validation implementation bundles.
+ * The purpose of these tests is to make sure that bean validation works in OSGi environment.
+ *
+ * @author Dmitry Kornilov
+ * @since 2.7.0
+ */
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+public class BeanValidationTest extends BaseBeanValidationTest {
+    private static JAXBContext jaxbContext;
+
+    @Configuration
+    public static Option[] config() {
+        return OSGITestHelper.getOptionsWithBeanValidation();
+    }
+
+    @BeforeClass
+    public static void setUp() throws Exception {
+        Class[] classes = new Class[1];
+        classes[0] = Customer.class;
+        jaxbContext = JAXBContextFactory.createContext(classes, null);
+    }
+
+    @Test(expected = BeanValidationException.class)
+    public void testMarshalInvalid() throws JAXBException {
+        StringWriter xml = new StringWriter();
+        Marshaller marshaller = jaxbContext.createMarshaller();
+        marshaller.setProperty(MarshallerProperties.BEAN_VALIDATION_FACTORY, getValidatorFactory());
+        marshaller.marshal(createInvalidCustomer(), xml);
+    }
+
+    @Test
+    public void testMarshalValid() throws JAXBException {
+        StringWriter xml = new StringWriter();
+        Marshaller marshaller = jaxbContext.createMarshaller();
+        marshaller.setProperty(MarshallerProperties.BEAN_VALIDATION_FACTORY, getValidatorFactory());
+        marshaller.marshal(createValidCustomer(), xml);
+        assertTrue(xml.toString().contains(CUSTOMER_VALID_XML));
+    }
+
+    @Test(expected = JAXBException.class)
+    public void testUnmarshalInvalid() throws JAXBException {
+        StringReader xml = new StringReader(CUSTOMER_INVALID_XML);
+        Unmarshaller unmarshaler = jaxbContext.createUnmarshaller();
+        unmarshaler.setProperty(MarshallerProperties.BEAN_VALIDATION_FACTORY, getValidatorFactory());
+        unmarshaler.unmarshal(xml);
+    }
+
+    @Test
+    public void testUnmarshalValid() throws JAXBException {
+        StringReader xml = new StringReader(CUSTOMER_VALID_XML);
+        Unmarshaller unmarshaler = jaxbContext.createUnmarshaller();
+        unmarshaler.setProperty(MarshallerProperties.BEAN_VALIDATION_FACTORY, getValidatorFactory());
+        Customer testCustomer = (Customer)unmarshaler.unmarshal(xml);
+        assertTrue(createValidCustomer().equals(testCustomer));
+    }
+
+    private ValidatorFactory getValidatorFactory() {
+        return Validation.byProvider(HibernateValidator.class)
+                .providerResolver(new BeanValidationTest.MyValidationProviderResolver())
+                .configure()
+                .buildValidatorFactory();
+    }
+
+    private static class MyValidationProviderResolver implements ValidationProviderResolver {
+        @Override
+        public List<ValidationProvider<?>> getValidationProviders() {
+            return Collections.<ValidationProvider<?>>singletonList(new HibernateValidator());
+        }
+    }
+}
diff --git a/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/osgi/beanvalidation/Customer.java b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/osgi/beanvalidation/Customer.java
new file mode 100644
index 0000000..0b64086
--- /dev/null
+++ b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/osgi/beanvalidation/Customer.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Dmitry Kornilov - initial implementation
+ ******************************************************************************/
+package org.eclipse.persistence.testing.osgi.beanvalidation;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * Test class for OSGi tests with javax.validation in class path and without it.
+ *
+ * @author Dmitry Kornilov
+ * @since 2.7
+ */
+@XmlRootElement
+public class Customer {
+
+    @NotNull
+    @XmlAttribute
+    private String id;
+
+    @NotNull
+    @Size(min = 3, max = 15)
+    @XmlElement
+    private String name;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Customer customer = (Customer) o;
+
+        if (id != null ? !id.equals(customer.id) : customer.id != null) return false;
+        return !(name != null ? !name.equals(customer.name) : customer.name != null);
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = id != null ? id.hashCode() : 0;
+        result = 31 * result + (name != null ? name.hashCode() : 0);
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/osgi/beanvalidation/NoBeanValidationTest.java b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/osgi/beanvalidation/NoBeanValidationTest.java
new file mode 100644
index 0000000..e75fee7
--- /dev/null
+++ b/moxy/eclipselink.moxy.test/src/org/eclipse/persistence/testing/osgi/beanvalidation/NoBeanValidationTest.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Dmitry Kornilov - initial implementation
+ ******************************************************************************/
+package org.eclipse.persistence.testing.osgi.beanvalidation;
+
+import org.eclipse.persistence.jaxb.JAXBContextFactory;
+import org.eclipse.persistence.testing.osgi.OSGITestHelper;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
+import org.ops4j.pax.exam.spi.reactors.PerClass;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Marshal/unmarshal tests in OSGi container without installed bean validation implementation bundles.
+ * The purpose of these tests is to make sure that javax.validation import is optional.
+ *
+ * @author Dmitry Kornilov
+ * @since 2.7.0
+ */
+@RunWith(PaxExam.class)
+@ExamReactorStrategy(PerClass.class)
+public class NoBeanValidationTest extends BaseBeanValidationTest {
+    private static JAXBContext jaxbContext;
+
+    @Configuration
+    public static Option[] config() {
+        return OSGITestHelper.getDefaultOptions();
+    }
+
+    @BeforeClass
+    public static void setUp() throws Exception {
+        Class[] classes = new Class[1];
+        classes[0] = Customer.class;
+        jaxbContext = JAXBContextFactory.createContext(classes, null);
+    }
+
+    @Test
+    public void testMarshalValid() throws JAXBException {
+        StringWriter xml = new StringWriter();
+        Marshaller marshaller = jaxbContext.createMarshaller();
+        marshaller.marshal(createValidCustomer(), xml);
+        assertTrue(xml.toString().contains(CUSTOMER_VALID_XML));
+    }
+
+    @Test
+    public void testMarshalInvalid() throws JAXBException {
+        StringWriter xml = new StringWriter();
+        Marshaller marshaller = jaxbContext.createMarshaller();
+        marshaller.marshal(createInvalidCustomer(), xml);
+        assertTrue(xml.toString().contains(CUSTOMER_INVALID_XML));
+    }
+
+    @Test
+    public void testUnmarshalValid() throws JAXBException {
+        StringReader xml = new StringReader(CUSTOMER_VALID_XML);
+        Customer testCustomer = (Customer) jaxbContext.createUnmarshaller().unmarshal(xml);
+        assertTrue(createValidCustomer().equals(testCustomer));
+    }
+
+    @Test
+    public void testUnmarshalInvalid() throws JAXBException {
+        StringReader xml = new StringReader(CUSTOMER_INVALID_XML);
+        Customer testCustomer = (Customer) jaxbContext.createUnmarshaller().unmarshal(xml);
+        assertTrue(createInvalidCustomer().equals(testCustomer));
+    }
+}
diff --git a/moxy/org.eclipse.persistence.moxy/META-INF/MANIFEST.MF b/moxy/org.eclipse.persistence.moxy/META-INF/MANIFEST.MF
index 6c9f4e2..ad3e75e 100644
--- a/moxy/org.eclipse.persistence.moxy/META-INF/MANIFEST.MF
+++ b/moxy/org.eclipse.persistence.moxy/META-INF/MANIFEST.MF
@@ -38,6 +38,7 @@
  javax.validation;resolution:=optional;version="1.1.0",
  javax.validation.constraints;resolution:=optional;version="1.1.0",
  javax.validation.groups;resolution:=optional;version="1.1.0",
+ javax.validation.metadata;resolution:=optional;version="1.1.0",
  javax.ws.rs;resolution:=optional,
  javax.ws.rs.core;resolution:=optional,
  javax.ws.rs.ext;resolution:=optional,
@@ -47,7 +48,7 @@
  javax.xml.bind.attachment,
  javax.xml.bind.helpers,
  javax.xml.namespace;resolution:=optional,
- javax.xml.parsers;resolution:=optional,
+ javax.xml.parsers,
  javax.xml.stream;resolution:=optional,
  javax.xml.transform;resolution:=optional,
  javax.xml.transform.dom;resolution:=optional,
diff --git a/moxy/org.eclipse.persistence.moxy/src/org/eclipse/persistence/jaxb/ConstraintViolationWrapper.java b/moxy/org.eclipse.persistence.moxy/src/org/eclipse/persistence/jaxb/ConstraintViolationWrapper.java
new file mode 100644
index 0000000..6415fa2
--- /dev/null
+++ b/moxy/org.eclipse.persistence.moxy/src/org/eclipse/persistence/jaxb/ConstraintViolationWrapper.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Dmitry Kornilov - initial implementation
+ ******************************************************************************/
+package org.eclipse.persistence.jaxb;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.Path;
+import javax.validation.metadata.ConstraintDescriptor;
+
+/**
+ * Wrapper over {@link ConstraintViolation} class. Required due to optional nature of javax.validation bundle.
+ *
+ * @author Dmitry Kornilov
+ * @since 2.7.0
+ */
+public class ConstraintViolationWrapper<T> {
+    private ConstraintViolation<T> constraintViolation;
+
+    /**
+     * Creates a new wrapper.
+     * @param constraintViolation original object
+     */
+    public ConstraintViolationWrapper(ConstraintViolation<T> constraintViolation) {
+        this.constraintViolation = constraintViolation;
+    }
+
+    /**
+     * {@see ConstraintViolation#getMessage}
+     */
+    public String getMessage() {
+        return constraintViolation.getMessage();
+    }
+
+    /**
+     * {@see ConstraintViolation#getMessageTemplate}
+     */
+    public String getMessageTemplate() {
+        return constraintViolation.getMessageTemplate();
+    }
+
+    /**
+     * {@see ConstraintViolation#getRootBean}
+     */
+    public T getRootBean() {
+        return constraintViolation.getRootBean();
+    }
+
+    /**
+     * {@see ConstraintViolation#getRootBeanClass}
+     */
+    public Class<T> getRootBeanClass() {
+        return constraintViolation.getRootBeanClass();
+    }
+
+    /**
+     * {@see ConstraintViolation#getLeafBean}
+     */
+    public Object getLeafBean() {
+        return constraintViolation.getLeafBean();
+    }
+
+    /**
+     * {@see ConstraintViolation#getExecutableParameters}
+     */
+    public Object[] getExecutableParameters() {
+        return constraintViolation.getExecutableParameters();
+    }
+
+    /**
+     * {@see ConstraintViolation#getExecutableReturnValue}
+     */
+    public Object getExecutableReturnValue() {
+        return constraintViolation.getExecutableReturnValue();
+    }
+
+    /**
+     * {@see ConstraintViolation#getPropertyPath}
+     */
+    public Path getPropertyPath() {
+        return constraintViolation.getPropertyPath();
+    }
+
+    /**
+     * {@see ConstraintViolation#getInvalidValue}
+     */
+    public Object getInvalidValue() {
+        return constraintViolation.getInvalidValue();
+    }
+
+    /**
+     * {@see ConstraintViolation#getConstraintDescriptor}
+     */
+    public ConstraintDescriptor<?> getConstraintDescriptor() {
+        return constraintViolation.getConstraintDescriptor();
+    }
+
+    /**
+     * Unwraps original object and returns it.
+     */
+    public ConstraintViolation<T> unwrap() {
+        return constraintViolation;
+    }
+}
diff --git a/moxy/org.eclipse.persistence.moxy/src/org/eclipse/persistence/jaxb/JAXBBeanValidator.java b/moxy/org.eclipse.persistence.moxy/src/org/eclipse/persistence/jaxb/JAXBBeanValidator.java
index a551f31..b7ad4f4 100644
--- a/moxy/org.eclipse.persistence.moxy/src/org/eclipse/persistence/jaxb/JAXBBeanValidator.java
+++ b/moxy/org.eclipse.persistence.moxy/src/org/eclipse/persistence/jaxb/JAXBBeanValidator.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -29,6 +29,7 @@
 import java.security.PrivilegedAction;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.Set;
@@ -185,8 +186,8 @@
      * @param beanValidationMode Bean validation mode - allowed values AUTO, CALLBACK, NONE.
      * @param value validated object. It is passed because validation on some objects may be skipped, 
      *              e.g. non-constrained objects (like XmlBindings).
-     * @param preferredValidatorFactory May be null. Will use this factory as the preferred provider;
-     *                                  if null, will use javax defaults.
+     * @param preferredValidatorFactory Must be {@link ValidatorFactory} or null. Will use this factory as the
+     *                                  preferred provider; if null, will use javax defaults.
      * @param noOptimisation if true, bean validation optimisations that skip non-constrained objects will not be
      *                       performed
      * @return 
@@ -196,7 +197,7 @@
      * @since 2.6
      */
     boolean shouldValidate (Object value, BeanValidationMode beanValidationMode,
-                            ValidatorFactory preferredValidatorFactory,
+                            Object preferredValidatorFactory,
                             boolean noOptimisation) throws BeanValidationException {
 
         if (isValidationEffectivelyOff(beanValidationMode)) return false;
@@ -207,9 +208,8 @@
 
         /* Mode or validator factory was changed externally (or it's the first time this method is called). */
         if (this.beanValidationMode != beanValidationMode || this.validatorFactory != preferredValidatorFactory) {
-
             this.beanValidationMode = beanValidationMode;
-            this.validatorFactory = preferredValidatorFactory;
+            this.validatorFactory = (ValidatorFactory)preferredValidatorFactory;
             changeInternalState();
         }
 
@@ -262,11 +262,15 @@
      * Stores the result of validation in {@link #constraintViolations}.
      *
      * @param value Object to be validated.
-     * @param groups Target groups as per BV spec. Must not be null, may be empty.
+     * @param groups Target groups as per BV spec. If null {@link #DEFAULT_GROUP_ARRAY} is used.
      * @throws BeanValidationException {@link BeanValidationException#constraintViolation}
      */
     void validate(Object value, Class<?>... groups) throws BeanValidationException {
-        constraintViolations = validator.validate(value, groups);
+        Class<?>[] grp = groups;
+        if (grp == null || grp.length == 0) {
+            grp = DEFAULT_GROUP_ARRAY;
+        }
+        constraintViolations = validator.validate(value, grp);
         if (!constraintViolations.isEmpty())
             throw buildConstraintViolationException();
     }
@@ -274,8 +278,12 @@
     /**
      * @return constraintViolations from the last {@link #validate} call.
      */
-    Set<ConstraintViolation<Object>> getConstraintViolations() {
-        return constraintViolations;
+    Set<ConstraintViolationWrapper<Object>> getConstraintViolations() {
+        Set<ConstraintViolationWrapper<Object>> result = new HashSet<>(constraintViolations.size());
+        for (ConstraintViolation cv : constraintViolations) {
+            result.add(new ConstraintViolationWrapper<>(cv));
+        }
+        return result;
     }
 
     /**
diff --git a/moxy/org.eclipse.persistence.moxy/src/org/eclipse/persistence/jaxb/JAXBMarshaller.java b/moxy/org.eclipse.persistence.moxy/src/org/eclipse/persistence/jaxb/JAXBMarshaller.java
index fea8e3c..24188c3 100644
--- a/moxy/org.eclipse.persistence.moxy/src/org/eclipse/persistence/jaxb/JAXBMarshaller.java
+++ b/moxy/org.eclipse.persistence.moxy/src/org/eclipse/persistence/jaxb/JAXBMarshaller.java
@@ -1,16 +1,16 @@
-/*******************************************************************************

- * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.

- * This program and the accompanying materials are made available under the

- * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0

- * which accompanies this distribution.

- * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html

- * and the Eclipse Distribution License is available at

- * http://www.eclipse.org/org/documents/edl-v10.php.

- *

- * Contributors:

- *     Oracle - initial API and implementation from Oracle TopLink

- *     Marcel Valovy - 2.6.0 - added case insensitive unmarshalling property,

- *                             added Bean Validation support.

+/*******************************************************************************
+ * Copyright (c) 1998, 2016 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation from Oracle TopLink
+ *     Marcel Valovy - 2.6.0 - added case insensitive unmarshalling property,
+ *                             added Bean Validation support.
  ******************************************************************************/
 package org.eclipse.persistence.jaxb;
 
@@ -22,24 +22,23 @@
 import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import javax.validation.ConstraintViolation;
-import javax.validation.ValidatorFactory;
-import javax.xml.bind.JAXBElement;

-import javax.xml.bind.JAXBException;

-import javax.xml.bind.MarshalException;

-import javax.xml.bind.Marshaller;

-import javax.xml.bind.PropertyException;

-import javax.xml.bind.ValidationEventHandler;

-import javax.xml.bind.annotation.adapters.XmlAdapter;

-import javax.xml.bind.attachment.AttachmentMarshaller;

-import javax.xml.namespace.QName;

-import javax.xml.stream.XMLEventWriter;

-import javax.xml.stream.XMLStreamWriter;

+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.MarshalException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.PropertyException;
+import javax.xml.bind.ValidationEventHandler;
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+import javax.xml.bind.attachment.AttachmentMarshaller;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLEventWriter;
+import javax.xml.stream.XMLStreamWriter;
 import javax.xml.transform.Result;
 import javax.xml.validation.Schema;
 
@@ -73,235 +72,245 @@
 
 /**
  * INTERNAL:
- * <p>

- * <b>Purpose:</b>To Provide an implementation of the JAXB 2.0 Marshaller

- * Interface

- * <p>

- * <b>Responsibilities:</b>

- * <ul>

- * <li>Provide a JAXB wrapper on the XMLMarshaller API</li>

- * <li>Perform Object to XML Conversions</li>

- * </ul>

- * <p>This implementation of the JAXB 2.1/2.2 Marshaller interface provides the

- * required functionality by acting as a thin wrapper on the existing 

- * XMLMarshaller API.</p>

- * 

- * @author mmacivor

- * @since Oracle TopLink 11.1.1.0.0

- * @see javax.xml.bind.Marshaller

- * @see org.eclipse.persistence.jaxb.MarshallerProperties

- * @see org.eclipse.persistence.oxm.XMLMarshaller

- */

-

-public class JAXBMarshaller implements javax.xml.bind.Marshaller {

-

-    private final JAXBBeanValidator beanValidator;

-

-    private BeanValidationMode beanValidationMode;

-    private ValidatorFactory prefValidatorFactory;

-    private boolean bvNoOptimisation = false;

-    private Class<?>[] beanValidationGroups = JAXBBeanValidator.DEFAULT_GROUP_ARRAY;

-

-    private final XMLMarshaller xmlMarshaller;

-    private final JAXBContext jaxbContext;

-    private ValidationEventHandler validationEventHandler;

-

-    public static final String XML_JAVATYPE_ADAPTERS = "xml-javatype-adapters";

-

-    private static final String SUN_NAMESPACE_PREFIX_MAPPER = "com.sun.xml.bind.namespacePrefixMapper";

-    private static final String SUN_JSE_NAMESPACE_PREFIX_MAPPER = "com.sun.xml.internal.bind.namespacePrefixMapper";

-

-    private static final String SUN_INDENT_STRING = "com.sun.xml.bind.indentString";

-    private static final String SUN_JSE_INDENT_STRING = "com.sun.xml.internal.bind.indentString";

-

-    private static final String SUN_CHARACTER_ESCAPE_HANDLER_MARSHALLER = "com.sun.xml.bind.marshaller.CharacterEscapeHandler";

-    private static final String SUN_JSE_CHARACTER_ESCAPE_HANDLER_MARSHALLER = "com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler";

-

-    private static final String SUN_CHARACTER_ESCAPE_HANDLER= "com.sun.xml.bind.characterEscapeHandler";

-    private static final String SUN_JSE_CHARACTER_ESCAPE_HANDLER = "com.sun.xml.internal.bind.characterEscapeHandler";

-    

-    // XML_DECLARATION is the "opposite" to JAXB_FRAGMENT.  If XML_DECLARATION is set to false it means JAXB_FRAGMENT should be set to true.

-    private static final String XML_DECLARATION = "com.sun.xml.bind.xmlDeclaration";

-

-    private static final String XML_HEADERS = "com.sun.xml.bind.xmlHeaders";

-

-    private static final String OBJECT_IDENTITY_CYCLE_DETECTION = "com.sun.xml.bind.objectIdentitityCycleDetection";

-

-    /**

-     * This constructor initializes various settings on the XML marshaller.

-     *

-     * @param newXMLMarshaller xml marshaller

-     * @param jaxbContext jaxb context

-     */

-    public JAXBMarshaller(XMLMarshaller newXMLMarshaller, JAXBContext jaxbContext) {

-        this.jaxbContext = jaxbContext;

-        validationEventHandler = JAXBContext.DEFAULT_VALIDATION_EVENT_HANDLER;

-        beanValidationMode = BeanValidationMode.AUTO;

-        beanValidator = JAXBBeanValidator.getMarshallingBeanValidator(jaxbContext);

-        xmlMarshaller = newXMLMarshaller;

-        xmlMarshaller.setErrorHandler(new JAXBErrorHandler(validationEventHandler));

-        xmlMarshaller.setEncoding("UTF-8");

-        xmlMarshaller.setFormattedOutput(false);

-        xmlMarshaller.getProperties().put(Constants.JAXB_MARSHALLER, this);

-    }

-

-    /**

-     * Create an instance of XMLRoot populated from the contents of the provided

-     * JAXBElement. XMLRoot will be used to hold the contents of the JAXBElement

-     * while the marshal operation is performed by TopLink OXM. This will avoid

-     * adding any runtime dependencies to TopLink.

-     * 

-     * @param elt

-     * @return

-     */

-    private Root createXMLRootFromJAXBElement(JAXBElement elt) {

-        // create an XMLRoot to hand into the marshaller

-    	Root xmlroot = new Root();

-        Object objectValue = elt.getValue();

-        xmlroot.setObject(objectValue);

-        QName qname = elt.getName();

-        xmlroot.setLocalName(qname.getLocalPart());

-        xmlroot.setNamespaceURI(qname.getNamespaceURI());

-        xmlroot.setDeclaredType(elt.getDeclaredType());

-        xmlroot.setNil(elt.isNil());

-        if (elt.getDeclaredType() == CoreClassConstants.ABYTE || elt.getDeclaredType() == CoreClassConstants.APBYTE || 

-                elt.getDeclaredType().getCanonicalName().equals("javax.activation.DataHandler") ||

-                elt.getDeclaredType().isEnum()) {

-            // need a binary data mapping so need to wrap

-            Class generatedClass = getClassToGeneratedClasses().get(elt.getDeclaredType().getCanonicalName());

-            if(!elt.getDeclaredType().isEnum()) {

-                xmlroot.setSchemaType(Constants.BASE_64_BINARY_QNAME);

-            }

-            if (generatedClass != null && WrappedValue.class.isAssignableFrom(generatedClass)) {

-                ClassDescriptor desc = xmlMarshaller.getXMLContext().getSession(generatedClass).getDescriptor(generatedClass);

-                Object newObject = desc.getInstantiationPolicy().buildNewInstance();

-                ((WrappedValue) newObject).setValue(objectValue);

-                xmlroot.setObject(newObject);

-                return xmlroot;

-            }

-        } else {

-            xmlroot.setSchemaType((QName) org.eclipse.persistence.internal.oxm.XMLConversionManager.getDefaultJavaTypes().get(elt.getDeclaredType()));

-        }

-

-        if (elt instanceof WrappedValue) {

-            xmlroot.setObject(elt);

-            return xmlroot;

-        }

-        Map<QName, Class> qNameToGeneratedClasses = jaxbContext.getQNameToGeneratedClasses();

-        if (qNameToGeneratedClasses != null) {

-            Class theClass = qNameToGeneratedClasses.get(qname);

-            if (theClass != null && WrappedValue.class.isAssignableFrom(theClass)) {

-                ClassDescriptor desc = xmlMarshaller.getXMLContext().getSession(theClass).getDescriptor(theClass);

-                Object newObject = desc.getInstantiationPolicy().buildNewInstance();

-                ((WrappedValue) newObject).setValue(objectValue);

-                xmlroot.setObject(newObject);

-                return xmlroot;

-            }

-        }

-

-        Class generatedClass = null;

-        if (jaxbContext.getTypeMappingInfoToGeneratedType() != null) {

-            if (jaxbContext.getTypeToTypeMappingInfo() != null) {

-                if (elt.getDeclaredType() != null && elt.getDeclaredType().isArray()) {

-                    TypeMappingInfo tmi = jaxbContext.getTypeToTypeMappingInfo().get(elt.getDeclaredType());

-                    generatedClass = jaxbContext.getTypeMappingInfoToGeneratedType().get(tmi);

-                } else if (elt instanceof JAXBTypeElement) {

-                    Type objectType = ((JAXBTypeElement) elt).getType();

-                    TypeMappingInfo tmi = jaxbContext.getTypeToTypeMappingInfo().get(objectType);

-                    generatedClass = jaxbContext.getTypeMappingInfoToGeneratedType().get(tmi);

-                }

-            }

-        } else {

-            if (elt.getDeclaredType() != null && elt.getDeclaredType().isArray()) {

-                if (jaxbContext.getArrayClassesToGeneratedClasses() != null) {

-                    generatedClass = jaxbContext.getArrayClassesToGeneratedClasses().get(elt.getDeclaredType().getCanonicalName());

-                }

-            } else if (elt instanceof JAXBTypeElement) {

-                Type objectType = ((JAXBTypeElement) elt).getType();

-                generatedClass = jaxbContext.getCollectionClassesToGeneratedClasses().get(objectType);

-            }

-        }

-

-        if (generatedClass != null) {

-            ClassDescriptor desc = xmlMarshaller.getXMLContext().getSession(generatedClass).getDescriptor(generatedClass);

-            Object newObject = desc.getInstantiationPolicy().buildNewInstance();

-            ((ManyValue) newObject).setItem(objectValue);

-            xmlroot.setObject(newObject);

-        }

-

-        return xmlroot;

-    }

-

-    public XmlAdapter getAdapter(Class javaClass) {

-        HashMap result = (HashMap) xmlMarshaller.getProperty(XML_JAVATYPE_ADAPTERS);

-        if (result == null) {

-            return null;

-        }

-        return (XmlAdapter) result.get(javaClass);

-    }

-

-    public AttachmentMarshaller getAttachmentMarshaller() {

-        if (xmlMarshaller.getAttachmentMarshaller() == null) {

-            return null;

-        }

-        return ((AttachmentMarshallerAdapter) xmlMarshaller.getAttachmentMarshaller()).getAttachmentMarshaller();

-    }

-

-    public ValidationEventHandler getEventHandler() throws JAXBException {

-        return validationEventHandler;

-    }

-

-    public Marshaller.Listener getListener() {

-        XMLMarshalListener xmlMarshalListener = xmlMarshaller.getMarshalListener();

-        if(null != xmlMarshalListener) {

-            return ((JAXBMarshalListener) xmlMarshalListener).getListener();

-        }

-        return null;

-    }

-

-    public Node getNode(Object object) throws JAXBException {

-        throw new UnsupportedOperationException();

-    }

-

-    /**

-     * Get a property from the JAXBMarshaller. Attempting to get any unsupported

-     * property will result in a javax.xml.bind.PropertyException 

-     * @see org.eclipse.persistence.jaxb.MarshallerProperties

-     */

-    public Object getProperty(String key) throws PropertyException {

-        if (key == null) {

-            throw new IllegalArgumentException();

-        } else if (JAXB_FORMATTED_OUTPUT.equals(key)) {

-            return xmlMarshaller.isFormattedOutput();

-        } else if (JAXB_ENCODING.equals(key)) {

-            return xmlMarshaller.getEncoding();

-        } else if (JAXB_SCHEMA_LOCATION.equals(key)) {

-            return xmlMarshaller.getSchemaLocation();

-        } else if (JAXB_NO_NAMESPACE_SCHEMA_LOCATION.equals(key)) {

-            return xmlMarshaller.getNoNamespaceSchemaLocation();

-        } else if (Constants.JAXB_FRAGMENT.equals(key)) {

-            return xmlMarshaller.isFragment();

-        } else if (MarshallerProperties.MEDIA_TYPE.equals(key)) {

-            return xmlMarshaller.getMediaType();

-        } else if (MarshallerProperties.NAMESPACE_PREFIX_MAPPER.equals(key)) {

-            return xmlMarshaller.getNamespacePrefixMapper();

-        } else if (MarshallerProperties.INDENT_STRING.equals(key) || SUN_INDENT_STRING.equals(key) || SUN_JSE_INDENT_STRING.equals(key)) {

-            return xmlMarshaller.getIndentString();

-        } else if (MarshallerProperties.CHARACTER_ESCAPE_HANDLER.equals(key)) {

-            return xmlMarshaller.getCharacterEscapeHandler();

-        } else if (XML_DECLARATION.equals(key)) {

-            return !xmlMarshaller.isFragment();

-        } else if (XML_HEADERS.equals(key)) {

-            return xmlMarshaller.getXmlHeader();

-        } else if (OBJECT_IDENTITY_CYCLE_DETECTION.equals(key)) {

-            return xmlMarshaller.isEqualUsingIdenity();

-        } else if (MarshallerProperties.JSON_ATTRIBUTE_PREFIX.equals(key)) {

-            return xmlMarshaller.getAttributePrefix();

-        } else if (MarshallerProperties.JSON_INCLUDE_ROOT.equals(key)) {

-            return xmlMarshaller.isIncludeRoot();

-        } else if (MarshallerProperties.JSON_VALUE_WRAPPER.equals(key)) {

-            return xmlMarshaller.getValueWrapper(); 

-        } else if (MarshallerProperties.JSON_NAMESPACE_SEPARATOR.equals(key)) {

+ * <p>
+ * <b>Purpose:</b>To Provide an implementation of the JAXB 2.0 Marshaller
+ * Interface
+ * <p>
+ * <b>Responsibilities:</b>
+ * <ul>
+ * <li>Provide a JAXB wrapper on the XMLMarshaller API</li>
+ * <li>Perform Object to XML Conversions</li>
+ * </ul>
+ * <p>This implementation of the JAXB 2.1/2.2 Marshaller interface provides the
+ * required functionality by acting as a thin wrapper on the existing
+ * XMLMarshaller API.</p>
+ *
+ * @author mmacivor
+ * @since Oracle TopLink 11.1.1.0.0
+ * @see javax.xml.bind.Marshaller
+ * @see org.eclipse.persistence.jaxb.MarshallerProperties
+ * @see org.eclipse.persistence.oxm.XMLMarshaller
+ */
+
+public class JAXBMarshaller implements javax.xml.bind.Marshaller {
+
+    private JAXBBeanValidator beanValidator;
+
+    private BeanValidationMode beanValidationMode;
+
+    // The actual type is ValidatorFactory. It's done due to optional nature of javax.validation.
+    private Object prefValidatorFactory;
+    private boolean bvNoOptimisation = false;
+    private Class<?>[] beanValidationGroups;
+
+    private final XMLMarshaller xmlMarshaller;
+    private final JAXBContext jaxbContext;
+    private ValidationEventHandler validationEventHandler;
+
+    public static final String XML_JAVATYPE_ADAPTERS = "xml-javatype-adapters";
+
+    private static final String SUN_NAMESPACE_PREFIX_MAPPER = "com.sun.xml.bind.namespacePrefixMapper";
+    private static final String SUN_JSE_NAMESPACE_PREFIX_MAPPER = "com.sun.xml.internal.bind.namespacePrefixMapper";
+
+    private static final String SUN_INDENT_STRING = "com.sun.xml.bind.indentString";
+    private static final String SUN_JSE_INDENT_STRING = "com.sun.xml.internal.bind.indentString";
+
+    private static final String SUN_CHARACTER_ESCAPE_HANDLER_MARSHALLER = "com.sun.xml.bind.marshaller.CharacterEscapeHandler";
+    private static final String SUN_JSE_CHARACTER_ESCAPE_HANDLER_MARSHALLER = "com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler";
+
+    private static final String SUN_CHARACTER_ESCAPE_HANDLER= "com.sun.xml.bind.characterEscapeHandler";
+    private static final String SUN_JSE_CHARACTER_ESCAPE_HANDLER = "com.sun.xml.internal.bind.characterEscapeHandler";
+
+    // XML_DECLARATION is the "opposite" to JAXB_FRAGMENT.  If XML_DECLARATION is set to false it means JAXB_FRAGMENT should be set to true.
+    private static final String XML_DECLARATION = "com.sun.xml.bind.xmlDeclaration";
+
+    private static final String XML_HEADERS = "com.sun.xml.bind.xmlHeaders";
+
+    private static final String OBJECT_IDENTITY_CYCLE_DETECTION = "com.sun.xml.bind.objectIdentitityCycleDetection";
+
+    /**
+     * This constructor initializes various settings on the XML marshaller.
+     *
+     * @param newXMLMarshaller xml marshaller
+     * @param jaxbContext jaxb context
+     */
+    public JAXBMarshaller(XMLMarshaller newXMLMarshaller, JAXBContext jaxbContext) {
+        this.jaxbContext = jaxbContext;
+        validationEventHandler = JAXBContext.DEFAULT_VALIDATION_EVENT_HANDLER;
+        beanValidationMode = BeanValidationMode.AUTO;
+        if (BeanValidationChecker.isBeanValidationPresent()) {
+            beanValidator = JAXBBeanValidator.getMarshallingBeanValidator(jaxbContext);
+        }
+        xmlMarshaller = newXMLMarshaller;
+        xmlMarshaller.setErrorHandler(new JAXBErrorHandler(validationEventHandler));
+        xmlMarshaller.setEncoding("UTF-8");
+        xmlMarshaller.setFormattedOutput(false);
+        xmlMarshaller.getProperties().put(Constants.JAXB_MARSHALLER, this);
+    }
+
+    /**
+     * Create an instance of XMLRoot populated from the contents of the provided
+     * JAXBElement. XMLRoot will be used to hold the contents of the JAXBElement
+     * while the marshal operation is performed by TopLink OXM. This will avoid
+     * adding any runtime dependencies to TopLink.
+     *
+     * @param elt
+     * @return
+     */
+    private Root createXMLRootFromJAXBElement(JAXBElement elt) {
+        // create an XMLRoot to hand into the marshaller
+        Root xmlroot = new Root();
+        Object objectValue = elt.getValue();
+        xmlroot.setObject(objectValue);
+        QName qname = elt.getName();
+        xmlroot.setLocalName(qname.getLocalPart());
+        xmlroot.setNamespaceURI(qname.getNamespaceURI());
+        xmlroot.setDeclaredType(elt.getDeclaredType());
+        xmlroot.setNil(elt.isNil());
+        if (elt.getDeclaredType() == CoreClassConstants.ABYTE || elt.getDeclaredType() == CoreClassConstants.APBYTE ||
+                elt.getDeclaredType().getCanonicalName().equals("javax.activation.DataHandler") ||
+                elt.getDeclaredType().isEnum()) {
+            // need a binary data mapping so need to wrap
+            Class generatedClass = getClassToGeneratedClasses().get(elt.getDeclaredType().getCanonicalName());
+            if(!elt.getDeclaredType().isEnum()) {
+                xmlroot.setSchemaType(Constants.BASE_64_BINARY_QNAME);
+            }
+            if (generatedClass != null && WrappedValue.class.isAssignableFrom(generatedClass)) {
+                ClassDescriptor desc = xmlMarshaller.getXMLContext().getSession(generatedClass).getDescriptor(generatedClass);
+                Object newObject = desc.getInstantiationPolicy().buildNewInstance();
+                ((WrappedValue) newObject).setValue(objectValue);
+                xmlroot.setObject(newObject);
+                return xmlroot;
+            }
+        } else {
+            xmlroot.setSchemaType((QName) org.eclipse.persistence.internal.oxm.XMLConversionManager.getDefaultJavaTypes().get(elt.getDeclaredType()));
+        }
+
+        if (elt instanceof WrappedValue) {
+            xmlroot.setObject(elt);
+            return xmlroot;
+        }
+        Map<QName, Class> qNameToGeneratedClasses = jaxbContext.getQNameToGeneratedClasses();
+        if (qNameToGeneratedClasses != null) {
+            Class theClass = qNameToGeneratedClasses.get(qname);
+            if (theClass != null && WrappedValue.class.isAssignableFrom(theClass)) {
+                ClassDescriptor desc = xmlMarshaller.getXMLContext().getSession(theClass).getDescriptor(theClass);
+                Object newObject = desc.getInstantiationPolicy().buildNewInstance();
+                ((WrappedValue) newObject).setValue(objectValue);
+                xmlroot.setObject(newObject);
+                return xmlroot;
+            }
+        }
+
+        Class generatedClass = null;
+        if (jaxbContext.getTypeMappingInfoToGeneratedType() != null) {
+            if (jaxbContext.getTypeToTypeMappingInfo() != null) {
+                if (elt.getDeclaredType() != null && elt.getDeclaredType().isArray()) {
+                    TypeMappingInfo tmi = jaxbContext.getTypeToTypeMappingInfo().get(elt.getDeclaredType());
+                    generatedClass = jaxbContext.getTypeMappingInfoToGeneratedType().get(tmi);
+                } else if (elt instanceof JAXBTypeElement) {
+                    Type objectType = ((JAXBTypeElement) elt).getType();
+                    TypeMappingInfo tmi = jaxbContext.getTypeToTypeMappingInfo().get(objectType);
+                    generatedClass = jaxbContext.getTypeMappingInfoToGeneratedType().get(tmi);
+                }
+            }
+        } else {
+            if (elt.getDeclaredType() != null && elt.getDeclaredType().isArray()) {
+                if (jaxbContext.getArrayClassesToGeneratedClasses() != null) {
+                    generatedClass = jaxbContext.getArrayClassesToGeneratedClasses().get(elt.getDeclaredType().getCanonicalName());
+                }
+            } else if (elt instanceof JAXBTypeElement) {
+                Type objectType = ((JAXBTypeElement) elt).getType();
+                generatedClass = jaxbContext.getCollectionClassesToGeneratedClasses().get(objectType);
+            }
+        }
+
+        if (generatedClass != null) {
+            ClassDescriptor desc = xmlMarshaller.getXMLContext().getSession(generatedClass).getDescriptor(generatedClass);
+            Object newObject = desc.getInstantiationPolicy().buildNewInstance();
+            ((ManyValue) newObject).setItem(objectValue);
+            xmlroot.setObject(newObject);
+        }
+
+        return xmlroot;
+    }
+
+    @Override
+    public XmlAdapter getAdapter(Class javaClass) {
+        HashMap result = (HashMap) xmlMarshaller.getProperty(XML_JAVATYPE_ADAPTERS);
+        if (result == null) {
+            return null;
+        }
+        return (XmlAdapter) result.get(javaClass);
+    }
+
+    @Override
+    public AttachmentMarshaller getAttachmentMarshaller() {
+        if (xmlMarshaller.getAttachmentMarshaller() == null) {
+            return null;
+        }
+        return ((AttachmentMarshallerAdapter) xmlMarshaller.getAttachmentMarshaller()).getAttachmentMarshaller();
+    }
+
+    @Override
+    public ValidationEventHandler getEventHandler() throws JAXBException {
+        return validationEventHandler;
+    }
+
+    @Override
+    public Marshaller.Listener getListener() {
+        XMLMarshalListener xmlMarshalListener = xmlMarshaller.getMarshalListener();
+        if(null != xmlMarshalListener) {
+            return ((JAXBMarshalListener) xmlMarshalListener).getListener();
+        }
+        return null;
+    }
+
+    @Override
+    public Node getNode(Object object) throws JAXBException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Get a property from the JAXBMarshaller. Attempting to get any unsupported
+     * property will result in a javax.xml.bind.PropertyException
+     * @see org.eclipse.persistence.jaxb.MarshallerProperties
+     */
+    @Override
+    public Object getProperty(String key) throws PropertyException {
+        if (key == null) {
+            throw new IllegalArgumentException();
+        } else if (JAXB_FORMATTED_OUTPUT.equals(key)) {
+            return xmlMarshaller.isFormattedOutput();
+        } else if (JAXB_ENCODING.equals(key)) {
+            return xmlMarshaller.getEncoding();
+        } else if (JAXB_SCHEMA_LOCATION.equals(key)) {
+            return xmlMarshaller.getSchemaLocation();
+        } else if (JAXB_NO_NAMESPACE_SCHEMA_LOCATION.equals(key)) {
+            return xmlMarshaller.getNoNamespaceSchemaLocation();
+        } else if (Constants.JAXB_FRAGMENT.equals(key)) {
+            return xmlMarshaller.isFragment();
+        } else if (MarshallerProperties.MEDIA_TYPE.equals(key)) {
+            return xmlMarshaller.getMediaType();
+        } else if (MarshallerProperties.NAMESPACE_PREFIX_MAPPER.equals(key)) {
+            return xmlMarshaller.getNamespacePrefixMapper();
+        } else if (MarshallerProperties.INDENT_STRING.equals(key) || SUN_INDENT_STRING.equals(key) || SUN_JSE_INDENT_STRING.equals(key)) {
+            return xmlMarshaller.getIndentString();
+        } else if (MarshallerProperties.CHARACTER_ESCAPE_HANDLER.equals(key)) {
+            return xmlMarshaller.getCharacterEscapeHandler();
+        } else if (XML_DECLARATION.equals(key)) {
+            return !xmlMarshaller.isFragment();
+        } else if (XML_HEADERS.equals(key)) {
+            return xmlMarshaller.getXmlHeader();
+        } else if (OBJECT_IDENTITY_CYCLE_DETECTION.equals(key)) {
+            return xmlMarshaller.isEqualUsingIdenity();
+        } else if (MarshallerProperties.JSON_ATTRIBUTE_PREFIX.equals(key)) {
+            return xmlMarshaller.getAttributePrefix();
+        } else if (MarshallerProperties.JSON_INCLUDE_ROOT.equals(key)) {
+            return xmlMarshaller.isIncludeRoot();
+        } else if (MarshallerProperties.JSON_VALUE_WRAPPER.equals(key)) {
+            return xmlMarshaller.getValueWrapper();
+        } else if (MarshallerProperties.JSON_NAMESPACE_SEPARATOR.equals(key)) {
             return xmlMarshaller.getNamespaceSeparator();
         } else if (MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME.equals(key)) {
             return xmlMarshaller.isWrapperAsCollectionName();
@@ -312,29 +321,29 @@
         } else if (SUN_CHARACTER_ESCAPE_HANDLER.equals(key) || SUN_JSE_CHARACTER_ESCAPE_HANDLER.equals(key) ||SUN_CHARACTER_ESCAPE_HANDLER_MARSHALLER.equals(key) || SUN_JSE_CHARACTER_ESCAPE_HANDLER_MARSHALLER.equals(key)) {
             if (xmlMarshaller.getCharacterEscapeHandler() instanceof CharacterEscapeHandlerWrapper) {
                 CharacterEscapeHandlerWrapper wrapper = (CharacterEscapeHandlerWrapper) xmlMarshaller.getCharacterEscapeHandler();
-                return wrapper.getHandler();

-            }

-            return xmlMarshaller.getCharacterEscapeHandler();

-        } else if (SUN_NAMESPACE_PREFIX_MAPPER.equals(key) || SUN_JSE_NAMESPACE_PREFIX_MAPPER.equals(key)) {

-            NamespacePrefixMapperWrapper wrapper = (NamespacePrefixMapperWrapper) xmlMarshaller.getNamespacePrefixMapper();

-            if(wrapper == null){

-            	return null;

-            }

-            return wrapper.getPrefixMapper();

-        } else if (MarshallerProperties.OBJECT_GRAPH.equals(key)) {

-            Object graph = xmlMarshaller.getMarshalAttributeGroup();

-            if(graph instanceof CoreAttributeGroup) {

-                return new ObjectGraphImpl((CoreAttributeGroup)graph);

-            }

-            return graph;

-        } else if (MarshallerProperties.BEAN_VALIDATION_MODE.equals(key)) {

-            return this.beanValidationMode;

-        } else if (MarshallerProperties.BEAN_VALIDATION_FACTORY.equals(key)) {

-            return this.prefValidatorFactory;

-        } else if (MarshallerProperties.BEAN_VALIDATION_GROUPS.equals(key)) {

-            return this.beanValidationGroups;

-        } else if (MarshallerProperties.BEAN_VALIDATION_NO_OPTIMISATION.equals(key)) {

-            return this.bvNoOptimisation;

+                return wrapper.getHandler();
+            }
+            return xmlMarshaller.getCharacterEscapeHandler();
+        } else if (SUN_NAMESPACE_PREFIX_MAPPER.equals(key) || SUN_JSE_NAMESPACE_PREFIX_MAPPER.equals(key)) {
+            NamespacePrefixMapperWrapper wrapper = (NamespacePrefixMapperWrapper) xmlMarshaller.getNamespacePrefixMapper();
+            if(wrapper == null){
+            	return null;
+            }
+            return wrapper.getPrefixMapper();
+        } else if (MarshallerProperties.OBJECT_GRAPH.equals(key)) {
+            Object graph = xmlMarshaller.getMarshalAttributeGroup();
+            if(graph instanceof CoreAttributeGroup) {
+                return new ObjectGraphImpl((CoreAttributeGroup)graph);
+            }
+            return graph;
+        } else if (MarshallerProperties.BEAN_VALIDATION_MODE.equals(key)) {
+            return this.beanValidationMode;
+        } else if (MarshallerProperties.BEAN_VALIDATION_FACTORY.equals(key)) {
+            return this.prefValidatorFactory;
+        } else if (MarshallerProperties.BEAN_VALIDATION_GROUPS.equals(key)) {
+            return this.beanValidationGroups;
+        } else if (MarshallerProperties.BEAN_VALIDATION_NO_OPTIMISATION.equals(key)) {
+            return this.bvNoOptimisation;
         }
         throw new PropertyException(key);
     }
@@ -342,537 +351,551 @@
     public Schema getSchema() {
         return xmlMarshaller.getSchema();
     }
-

-    public void marshal(Object object, ContentHandler contentHandler) throws JAXBException {

-        if (object == null || contentHandler == null) {

-            throw new IllegalArgumentException();

-        }

-

-        Listener listener = getListener();

-        if(listener != null) {

-            if(object instanceof JAXBElement) {

-                listener.beforeMarshal(object);

-            }

-        }

-

-        Object oxmObject = validateAndTransformIfNeeded(object); // xml bindings + object

-        try {

-            xmlMarshaller.marshal(oxmObject, contentHandler);

-        } catch (BeanValidationException bve) {

-            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);

-        } catch (Exception e) {

-            throw new MarshalException(e);

-        }

-

-        if(listener != null) {

-            if(object instanceof JAXBElement) {

-                listener.afterMarshal(object);

-            }

-        }

-    }

-

-    private Object wrapEnumeration(Object object, Class enumerationClass) {

-        Class generatedClass = this.getClassToGeneratedClasses().get(enumerationClass.getName());

-        if (generatedClass != null && WrappedValue.class.isAssignableFrom(generatedClass)) {

-            ClassDescriptor desc = xmlMarshaller.getXMLContext().getSession(generatedClass).getDescriptor(generatedClass);

-            Object newObject = desc.getInstantiationPolicy().buildNewInstance();

-            ((WrappedValue) newObject).setValue(object);

-            object = newObject;

-        }

-        return object;

-    }

-

-    public void marshal(Object object, XMLEventWriter eventWriter) throws JAXBException {

-        if (object == null || eventWriter == null) {

-            throw new IllegalArgumentException();

-        }

-

-        Listener listener = getListener();

-        if(listener != null) {

-            if(object instanceof JAXBElement) {

-                listener.beforeMarshal(object);

-            }

-        }

-

-        Object oxmObject = validateAndTransformIfNeeded(object); // xml bindings + object

-        try {

-            XMLEventWriterRecord record = new XMLEventWriterRecord(eventWriter);

-            record.setMarshaller(this.xmlMarshaller);

-            this.xmlMarshaller.marshal(oxmObject, record);

-        } catch (BeanValidationException bve) {

-            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);

-        } catch (Exception ex) {

-            throw new MarshalException(ex);

-        }

-

-        if(listener != null) {

-            if(object instanceof JAXBElement) {

-                listener.afterMarshal(object);

-            }

-        }

-    }

-

-    public void marshal(Object object, XMLEventWriter eventWriter, TypeMappingInfo type) throws JAXBException {

-        if (jaxbContext.getTypeMappingInfoToGeneratedType() == null) {

-            marshal(object, eventWriter);

-        } else {

-            JAXBElement element = null;

-            Object value = object;

-            if (object instanceof JAXBElement) {

-                // use the JAXBElement's properties to populate an XMLRoot

-                element = (JAXBElement) object;

-                value = element.getValue();

-            }

-

-            RootLevelXmlAdapter adapter = jaxbContext.getTypeMappingInfoToJavaTypeAdapters().get(type);

-            if (adapter != null) {

-                try {

-                    value = adapter.getXmlAdapter().marshal(value);

-                } catch (Exception ex) {

-                    throw new JAXBException(XMLMarshalException.marshalException(ex));

-                }

-            }

-

-            value = wrapObject(value, element, type);

-            marshal(value, eventWriter);

-        }

-    }

-

-    public void marshal(Object object, Node node) throws JAXBException {

-        if (object == null || node == null) {

-            throw new IllegalArgumentException();

-        }

-

-        Listener listener = getListener();

-        if(listener != null) {

-            if(object instanceof JAXBElement) {

-                listener.beforeMarshal(object);

-            }

-        }

-

-        Object oxmObject = validateAndTransformIfNeeded(object); // xml bindings + object

-        try {

-            xmlMarshaller.marshal(oxmObject, node);

-        } catch (BeanValidationException bve) {

-            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);

-        } catch (Exception e) {

-            throw new MarshalException(e);

-        }

-

-        if(listener != null) {

-            if(object instanceof JAXBElement) {

-                listener.afterMarshal(object);

-            }

-        }

-    }

-

-    public void marshal(Object object, OutputStream outputStream) throws JAXBException {

-        if (object == null || outputStream == null) {

-            throw new IllegalArgumentException();

-        }

-

-        Listener listener = getListener();

-        if(listener != null) {

-            if(object instanceof JAXBElement) {

-                listener.beforeMarshal(object);

-            }

-        }

-

-        Object oxmObject = validateAndTransformIfNeeded(object); // xml bindings + object

-        try {

-            xmlMarshaller.marshal(oxmObject, outputStream);

-        } catch (BeanValidationException bve) {

-            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);

-        } catch (Exception e) {

-            throw new MarshalException(e);

-        }

-

-        if(listener != null) {

-            if(object instanceof JAXBElement) {

-                listener.afterMarshal(object);

-            }

-        }

-    }

-

-    public void marshal(Object object, File file) throws JAXBException {

-        try {

-            FileOutputStream outputStream = new FileOutputStream(file);

-            try {

-                marshal(object, outputStream); // link to the other one

-            } finally {

-                outputStream.close();

-            }

-        } catch (BeanValidationException bve) {

-            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);

-        } catch (Exception ex) {

-            throw new MarshalException(ex);

-        }

-    }

-

-    public void marshal(Object object, Result result) throws JAXBException {

-        if (object == null || result == null) {

-            throw new IllegalArgumentException();

-        }

-        object = validateAndTransformIfNeeded(object); // xml bindings + json object

-

-        try {

-            xmlMarshaller.marshal(object, result);

-        } catch (BeanValidationException bve) {

-            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);

-        } catch (Exception e) {

-            throw new MarshalException(e);

-        }

-    }

-

-    public void marshal(Object object, Result result, TypeMappingInfo type) throws JAXBException {

-        if (jaxbContext.getTypeMappingInfoToGeneratedType() == null) {

-            marshal(object, result);

-        } else {

-            JAXBElement element = null;

-            Object value = object;

-            if (object instanceof JAXBElement) {

-                // use the JAXBElement's properties to populate an XMLRoot

-                element = (JAXBElement) object;

-                value = element.getValue();

-            }

-

-            if(jaxbContext.getTypeMappingInfoToJavaTypeAdapters().size() > 0){

-                RootLevelXmlAdapter adapter = jaxbContext.getTypeMappingInfoToJavaTypeAdapters().get(type);

-           

-	            if (adapter != null) {

-	                try {

-	                    value = adapter.getXmlAdapter().marshal(value);

-	                } catch (Exception ex) {

-	                    throw new JAXBException(XMLMarshalException.marshalException(ex));

-	                }

-	            }

-            }

-            value = wrapObject(value, element, type);            

-            marshal(value, result);

-        }

-    }

-

-    public void marshal(Object object, XMLStreamWriter streamWriter) throws JAXBException {

-        if (object == null || streamWriter == null) {

-            throw new IllegalArgumentException();

-        }

-

-        Listener listener = getListener();

-        if(listener != null) {

-            if(object instanceof JAXBElement) {

-                listener.beforeMarshal(object);

-            }

-        }

-

-        Object oxmObject = validateAndTransformIfNeeded(object); // xml bindings + object

-        try {

-            XMLStreamWriterRecord record = new XMLStreamWriterRecord(streamWriter);

-            record.setMarshaller(this.xmlMarshaller);

-            this.xmlMarshaller.marshal(oxmObject, record);

-        } catch (BeanValidationException bve) {

-            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);

-        } catch (Exception ex) {

-            throw new MarshalException(ex);

-        }

-

-        if(listener != null) {

-            if(object instanceof JAXBElement) {

-                listener.afterMarshal(object);

-            }

-        }

-    }

-

-    private Object validateAndTransformIfNeeded(Object obj) throws BeanValidationException {

-        Object result = modifyObjectIfNeeded(obj);

-        if (beanValidator.shouldValidate(obj, beanValidationMode, prefValidatorFactory, bvNoOptimisation)) {

-            beanValidator.validate(result, beanValidationGroups);

-        }

-        return result;

-    }

-

-    private Object modifyObjectIfNeeded(Object obj) {

-        if (obj instanceof Collection) {

-            Collection objectList = (Collection) obj;

-            List newList = new ArrayList(objectList.size());

-            for (Object o : objectList) {

-                newList.add(modifySingleObjectIfNeeded(o));

-            }

-            return newList;

-        } else if (obj.getClass().isArray()) {

-            int arraySize = Array.getLength(obj);

-            List newList = new ArrayList(arraySize);

-            for (int x = 0; x < arraySize; x++) {

-                newList.add(modifySingleObjectIfNeeded(Array.get(obj, x)));

-            }

-            return newList;

-        } else {

-            return modifySingleObjectIfNeeded(obj);

-        }

-    }

-

-    private Object modifySingleObjectIfNeeded(Object obj){

-	// let the JAXBIntrospector determine if the object is a JAXBElement

-        if (obj instanceof JAXBElement) {

-            // use the JAXBElement's properties to populate an XMLRoot

-            return createXMLRootFromJAXBElement((JAXBElement) obj);

-        } else if(obj != null && obj.getClass().isEnum()) {

-        	return wrapEnumeration(obj, obj.getClass());

-        } else if (obj instanceof JSONWithPadding){

-        	Object nestedObject = ((JSONWithPadding)obj).getObject();

-        	if(nestedObject != null){

-	        	Object newNestedObject = modifyObjectIfNeeded(nestedObject);

-	        	if(nestedObject != newNestedObject){

-	        		return new JSONWithPadding(newNestedObject,((JSONWithPadding)obj).getCallbackName());

-	        	}

-        	}             

-        }

-    	return obj;

-    }

-

-    public void marshal(Object object, XMLStreamWriter streamWriter, TypeMappingInfo type) throws JAXBException {

-        if (jaxbContext.getTypeMappingInfoToGeneratedType() == null) {

-            marshal(object, streamWriter);

-        } else {

-            JAXBElement element = null;

-            Object value = object;

-            if (object instanceof JAXBElement) {

-                // use the JAXBElement's properties to populate an XMLRoot

-                element = (JAXBElement) object;

-                value = element.getValue();

-            }

-            if(jaxbContext.getTypeMappingInfoToJavaTypeAdapters().size() > 0){

-                RootLevelXmlAdapter adapter = jaxbContext.getTypeMappingInfoToJavaTypeAdapters().get(type);

-	            if (adapter != null) {

-	                try {

-	                    value = adapter.getXmlAdapter().marshal(value);

-	                } catch (Exception ex) {

-	                    throw new JAXBException(XMLMarshalException.marshalException(ex));

-	                }

-	            }

-            }

-

-            value = wrapObject(value, element, type);

-            marshal(value, streamWriter);

-        }

-    }

-

-    private Object wrapObject(Object object, JAXBElement wrapperElement, TypeMappingInfo typeMappingInfo) {

-    	if(jaxbContext.getTypeMappingInfoToGeneratedType().size() > 0){

-	        Class generatedClass = jaxbContext.getTypeMappingInfoToGeneratedType().get(typeMappingInfo);

-	        if(generatedClass != null && object == null && wrapperElement != null) {

-            return wrapObjectInXMLRoot(wrapperElement, object, typeMappingInfo);

-	        }

-    	

-	        if (generatedClass != null && WrappedValue.class.isAssignableFrom(generatedClass)) {

-	            ClassDescriptor desc = xmlMarshaller.getXMLContext().getSession(generatedClass).getDescriptor(generatedClass);

-	            Object newObject = desc.getInstantiationPolicy().buildNewInstance();

-	            ((WrappedValue) newObject).setValue(object);

-	            object = newObject;

-	        } else if (generatedClass != null) {

-	            // should be a many value

-	            ClassDescriptor desc = xmlMarshaller.getXMLContext().getSession(generatedClass).getDescriptor(generatedClass);

-	            Object newObject = desc.getInstantiationPolicy().buildNewInstance();

-	            ((ManyValue) newObject).setItem(object);

-	            object = newObject;

-	        }

-    	}

-

-        if (null == wrapperElement) {

-        	Root xmlRoot = new Root();

-            QName xmlTagName = typeMappingInfo.getXmlTagName();

-            if (null == xmlTagName) {

-                return object;

-            }

-            xmlRoot.setNamespaceURI(typeMappingInfo.getXmlTagName().getNamespaceURI());

-            xmlRoot.setLocalName(typeMappingInfo.getXmlTagName().getLocalPart());

-            xmlRoot.setObject(object);

-            return xmlRoot;

-

-        }

-        return wrapObjectInXMLRoot(wrapperElement, object, typeMappingInfo);

-    }

-

-    private Root wrapObjectInXMLRoot(JAXBElement wrapperElement, Object value, TypeMappingInfo typeMappingInfo) {

-    	Root xmlroot = new Root();

-        Object objectValue = value;

-        xmlroot.setObject(objectValue);

-        QName qname = wrapperElement.getName();

-        xmlroot.setLocalName(qname.getLocalPart());

-        xmlroot.setNamespaceURI(qname.getNamespaceURI());

-        xmlroot.setDeclaredType(wrapperElement.getDeclaredType());

-        if(typeMappingInfo != null){

-        	xmlroot.setSchemaType(typeMappingInfo.getSchemaType());

-        } else if(value != null) {

-            if (value.getClass() == CoreClassConstants.ABYTE || value.getClass() == CoreClassConstants.APBYTE || 

-                    value.getClass().getCanonicalName().equals("javax.activation.DataHandler")) {

-                xmlroot.setSchemaType(Constants.BASE_64_BINARY_QNAME);

-            }

-        }

-        return xmlroot;

-    }

-

-    public void marshal(Object object, Writer writer) throws JAXBException {

-        if (object == null || writer == null) {

-            throw new IllegalArgumentException();

-        }

-

-        Listener listener = getListener();

-        if(listener != null) {

-            if(object instanceof JAXBElement) {

-                listener.beforeMarshal(object);

-            }

-        }

-

-        Object oxmObject = validateAndTransformIfNeeded(object); // xml bindings + object

-        try {

-            xmlMarshaller.marshal(oxmObject, writer);

-        } catch (BeanValidationException bve) {

-            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);

-        } catch (Exception e) {

-            throw new MarshalException(e);

-        }

-

-        if(listener != null) {

-            if(object instanceof JAXBElement) {

-                listener.afterMarshal(object);

-            }

-        }

-    }

-

-    public void marshal(Object object, MarshalRecord record) throws JAXBException {

-        if (object == null || record == null) {

-            throw new IllegalArgumentException();

-        }

-        object = validateAndTransformIfNeeded(object); // xml bindings + object

-

-        try {

-            record.setMarshaller(xmlMarshaller);

-            xmlMarshaller.marshal(object, record);

-        } catch (BeanValidationException bve) {

-            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);

-        } catch (Exception e) {

-            throw new MarshalException(e);

-        }

-    }

-

-    public void marshal(Object object, MarshalRecord record, TypeMappingInfo type) throws JAXBException {

-        if (jaxbContext.getTypeMappingInfoToGeneratedType() == null) {

-            marshal(object, record);

-        } else {

-            JAXBElement element = null;

-            Object value = object;

-            if (object instanceof JAXBElement) {

-                // use the JAXBElement's properties to populate an XMLRoot

-                element = (JAXBElement) object;

-                value = element.getValue();

-            }

-            RootLevelXmlAdapter adapter = jaxbContext.getTypeMappingInfoToJavaTypeAdapters().get(type);

-            if (adapter != null) {

-                try {

-                    value = adapter.getXmlAdapter().marshal(value);

-                } catch (Exception ex) {

-                    throw new JAXBException(XMLMarshalException.marshalException(ex));

-                }

-            }

-            value = wrapObject(value, element, type);

-            marshal(value, record);            

-        }

-    }

-    

-    public void setAdapter(Class javaClass, XmlAdapter adapter) {

-        HashMap result = (HashMap) xmlMarshaller.getProperty(XML_JAVATYPE_ADAPTERS);

-        if (result == null) {

-            result = new HashMap();

-            xmlMarshaller.getProperties().put(XML_JAVATYPE_ADAPTERS, result);

-        }

-        result.put(javaClass, adapter);

-    }

-

-    public void setAdapter(XmlAdapter adapter) {

-        setAdapter(adapter.getClass(), adapter);

-    }

-

-    public void setAttachmentMarshaller(AttachmentMarshaller attachmentMarshaller) {

-        if (attachmentMarshaller == null) {

-            xmlMarshaller.setAttachmentMarshaller(null);

-        } else {

-            xmlMarshaller.setAttachmentMarshaller(new AttachmentMarshallerAdapter(attachmentMarshaller));

-        }

-    }

-

-    public void setEventHandler(ValidationEventHandler newValidationEventHandler) throws JAXBException {

-        if (null == newValidationEventHandler) {

-            validationEventHandler = JAXBContext.DEFAULT_VALIDATION_EVENT_HANDLER;

-        } else {

-            validationEventHandler = newValidationEventHandler;

-        }

-        xmlMarshaller.setErrorHandler(new JAXBErrorHandler(validationEventHandler));

-    }

-

-    public void setListener(Marshaller.Listener listener) {

-        if(xmlMarshaller.getMarshalListener() == null) {

-            xmlMarshaller.setMarshalListener(new JAXBMarshalListener(jaxbContext, this));

-        }

-        ((JAXBMarshalListener) xmlMarshaller.getMarshalListener()).setListener(listener);

-    }

-

-    public void setMarshalCallbacks(Map callbacks) {

-        if(callbacks == null || callbacks.isEmpty()) {

-            return;

-        }

-        if(xmlMarshaller.getMarshalListener() == null) {

-            xmlMarshaller.setMarshalListener(new JAXBMarshalListener(jaxbContext, this));

-        }

-        ((JAXBMarshalListener) xmlMarshaller.getMarshalListener()).setClassBasedMarshalEvents(callbacks);

-    }

-

-    /**

-     * Set a property on the JAXBMarshaller. Attempting to set any unsupported

-     * property will result in a javax.xml.bind.PropertyException 

-     * @see org.eclipse.persistence.jaxb.MarshallerProperties

-     */

-    public void setProperty(String key, Object value) throws PropertyException {

-        try {

-            if (key == null) {

-                throw new IllegalArgumentException();

-            } else if (Constants.JAXB_FRAGMENT.equals(key)) {

-            	if(value == null){

-                 	throw new PropertyException(key, Constants.EMPTY_STRING);                	

-                }         

-                Boolean fragment = (Boolean) value;

-                xmlMarshaller.setFragment(fragment.booleanValue());

-            } else if (JAXB_FORMATTED_OUTPUT.equals(key)) {

-            	if(value == null){

-                 	throw new PropertyException(key, Constants.EMPTY_STRING);                	

-                 }

-                Boolean formattedOutput = (Boolean) value;

-                xmlMarshaller.setFormattedOutput(formattedOutput.booleanValue());

-            } else if (JAXB_ENCODING.equals(key)) {

-                xmlMarshaller.setEncoding((String) value);

-            } else if (JAXB_SCHEMA_LOCATION.equals(key)) {

-                xmlMarshaller.setSchemaLocation((String) value);

-            } else if (JAXB_NO_NAMESPACE_SCHEMA_LOCATION.equals(key)) {

-                xmlMarshaller.setNoNamespaceSchemaLocation((String) value);

-            } else if(MarshallerProperties.NAMESPACE_PREFIX_MAPPER.equals(key)) { 

-            	if(value == null){

-            		xmlMarshaller.setNamespacePrefixMapper(null);

-            	}else if(value instanceof Map){

-            		NamespacePrefixMapper namespacePrefixMapper = new MapNamespacePrefixMapper((Map)value);

-            		xmlMarshaller.setNamespacePrefixMapper(namespacePrefixMapper);

-            	}else{

-                    xmlMarshaller.setNamespacePrefixMapper((NamespacePrefixMapper)value);

-            	}

-            } else if(SUN_NAMESPACE_PREFIX_MAPPER.equals(key) || SUN_JSE_NAMESPACE_PREFIX_MAPPER.equals(key)) {

-            	if(value == null){

-            		xmlMarshaller.setNamespacePrefixMapper(null);

-            	}else{

-                    xmlMarshaller.setNamespacePrefixMapper(new NamespacePrefixMapperWrapper(value));

-            	}

-            } else if (MarshallerProperties.INDENT_STRING.equals(key) || SUN_INDENT_STRING.equals(key) || SUN_JSE_INDENT_STRING.equals(key)) {

-                xmlMarshaller.setIndentString((String) value);

-            } else if (MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS.equals(key)){

-            	xmlMarshaller.setMarshalEmptyCollections((Boolean) value);

-            } else if (MarshallerProperties.JSON_REDUCE_ANY_ARRAYS.equals(key)){

+
+    @Override
+    public void marshal(Object object, ContentHandler contentHandler) throws JAXBException {
+        if (object == null || contentHandler == null) {
+            throw new IllegalArgumentException();
+        }
+
+        Listener listener = getListener();
+        if(listener != null) {
+            if(object instanceof JAXBElement) {
+                listener.beforeMarshal(object);
+            }
+        }
+
+        Object oxmObject = validateAndTransformIfNeeded(object); // xml bindings + object
+        try {
+            xmlMarshaller.marshal(oxmObject, contentHandler);
+        } catch (BeanValidationException bve) {
+            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
+        } catch (Exception e) {
+            throw new MarshalException(e);
+        }
+
+        if(listener != null) {
+            if(object instanceof JAXBElement) {
+                listener.afterMarshal(object);
+            }
+        }
+    }
+
+    private Object wrapEnumeration(Object object, Class enumerationClass) {
+        Class generatedClass = this.getClassToGeneratedClasses().get(enumerationClass.getName());
+        if (generatedClass != null && WrappedValue.class.isAssignableFrom(generatedClass)) {
+            ClassDescriptor desc = xmlMarshaller.getXMLContext().getSession(generatedClass).getDescriptor(generatedClass);
+            Object newObject = desc.getInstantiationPolicy().buildNewInstance();
+            ((WrappedValue) newObject).setValue(object);
+            object = newObject;
+        }
+        return object;
+    }
+
+    @Override
+    public void marshal(Object object, XMLEventWriter eventWriter) throws JAXBException {
+        if (object == null || eventWriter == null) {
+            throw new IllegalArgumentException();
+        }
+
+        Listener listener = getListener();
+        if(listener != null) {
+            if(object instanceof JAXBElement) {
+                listener.beforeMarshal(object);
+            }
+        }
+
+        Object oxmObject = validateAndTransformIfNeeded(object); // xml bindings + object
+        try {
+            XMLEventWriterRecord record = new XMLEventWriterRecord(eventWriter);
+            record.setMarshaller(this.xmlMarshaller);
+            this.xmlMarshaller.marshal(oxmObject, record);
+        } catch (BeanValidationException bve) {
+            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
+        } catch (Exception ex) {
+            throw new MarshalException(ex);
+        }
+
+        if(listener != null) {
+            if(object instanceof JAXBElement) {
+                listener.afterMarshal(object);
+            }
+        }
+    }
+
+    public void marshal(Object object, XMLEventWriter eventWriter, TypeMappingInfo type) throws JAXBException {
+        if (jaxbContext.getTypeMappingInfoToGeneratedType() == null) {
+            marshal(object, eventWriter);
+        } else {
+            JAXBElement element = null;
+            Object value = object;
+            if (object instanceof JAXBElement) {
+                // use the JAXBElement's properties to populate an XMLRoot
+                element = (JAXBElement) object;
+                value = element.getValue();
+            }
+
+            RootLevelXmlAdapter adapter = jaxbContext.getTypeMappingInfoToJavaTypeAdapters().get(type);
+            if (adapter != null) {
+                try {
+                    value = adapter.getXmlAdapter().marshal(value);
+                } catch (Exception ex) {
+                    throw new JAXBException(XMLMarshalException.marshalException(ex));
+                }
+            }
+
+            value = wrapObject(value, element, type);
+            marshal(value, eventWriter);
+        }
+    }
+
+    @Override
+    public void marshal(Object object, Node node) throws JAXBException {
+        if (object == null || node == null) {
+            throw new IllegalArgumentException();
+        }
+
+        Listener listener = getListener();
+        if(listener != null) {
+            if(object instanceof JAXBElement) {
+                listener.beforeMarshal(object);
+            }
+        }
+
+        Object oxmObject = validateAndTransformIfNeeded(object); // xml bindings + object
+        try {
+            xmlMarshaller.marshal(oxmObject, node);
+        } catch (BeanValidationException bve) {
+            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
+        } catch (Exception e) {
+            throw new MarshalException(e);
+        }
+
+        if(listener != null) {
+            if(object instanceof JAXBElement) {
+                listener.afterMarshal(object);
+            }
+        }
+    }
+
+    @Override
+    public void marshal(Object object, OutputStream outputStream) throws JAXBException {
+        if (object == null || outputStream == null) {
+            throw new IllegalArgumentException();
+        }
+
+        Listener listener = getListener();
+        if(listener != null) {
+            if(object instanceof JAXBElement) {
+                listener.beforeMarshal(object);
+            }
+        }
+
+        Object oxmObject = validateAndTransformIfNeeded(object); // xml bindings + object
+        try {
+            xmlMarshaller.marshal(oxmObject, outputStream);
+        } catch (BeanValidationException bve) {
+            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
+        } catch (Exception e) {
+            throw new MarshalException(e);
+        }
+
+        if(listener != null) {
+            if(object instanceof JAXBElement) {
+                listener.afterMarshal(object);
+            }
+        }
+    }
+
+    @Override
+    public void marshal(Object object, File file) throws JAXBException {
+        try {
+            FileOutputStream outputStream = new FileOutputStream(file);
+            try {
+                marshal(object, outputStream); // link to the other one
+            } finally {
+                outputStream.close();
+            }
+        } catch (BeanValidationException bve) {
+            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
+        } catch (Exception ex) {
+            throw new MarshalException(ex);
+        }
+    }
+
+    @Override
+    public void marshal(Object object, Result result) throws JAXBException {
+        if (object == null || result == null) {
+            throw new IllegalArgumentException();
+        }
+        object = validateAndTransformIfNeeded(object); // xml bindings + json object
+
+        try {
+            xmlMarshaller.marshal(object, result);
+        } catch (BeanValidationException bve) {
+            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
+        } catch (Exception e) {
+            throw new MarshalException(e);
+        }
+    }
+
+    public void marshal(Object object, Result result, TypeMappingInfo type) throws JAXBException {
+        if (jaxbContext.getTypeMappingInfoToGeneratedType() == null) {
+            marshal(object, result);
+        } else {
+            JAXBElement element = null;
+            Object value = object;
+            if (object instanceof JAXBElement) {
+                // use the JAXBElement's properties to populate an XMLRoot
+                element = (JAXBElement) object;
+                value = element.getValue();
+            }
+
+            if(jaxbContext.getTypeMappingInfoToJavaTypeAdapters().size() > 0){
+                RootLevelXmlAdapter adapter = jaxbContext.getTypeMappingInfoToJavaTypeAdapters().get(type);
+
+                if (adapter != null) {
+                    try {
+                        value = adapter.getXmlAdapter().marshal(value);
+                    } catch (Exception ex) {
+                        throw new JAXBException(XMLMarshalException.marshalException(ex));
+                    }
+                }
+            }
+            value = wrapObject(value, element, type);
+            marshal(value, result);
+        }
+    }
+
+    @Override
+    public void marshal(Object object, XMLStreamWriter streamWriter) throws JAXBException {
+        if (object == null || streamWriter == null) {
+            throw new IllegalArgumentException();
+        }
+
+        Listener listener = getListener();
+        if(listener != null) {
+            if(object instanceof JAXBElement) {
+                listener.beforeMarshal(object);
+            }
+        }
+
+        Object oxmObject = validateAndTransformIfNeeded(object); // xml bindings + object
+        try {
+            XMLStreamWriterRecord record = new XMLStreamWriterRecord(streamWriter);
+            record.setMarshaller(this.xmlMarshaller);
+            this.xmlMarshaller.marshal(oxmObject, record);
+        } catch (BeanValidationException bve) {
+            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
+        } catch (Exception ex) {
+            throw new MarshalException(ex);
+        }
+
+        if(listener != null) {
+            if(object instanceof JAXBElement) {
+                listener.afterMarshal(object);
+            }
+        }
+    }
+
+    private Object validateAndTransformIfNeeded(Object obj) throws BeanValidationException {
+        Object result = modifyObjectIfNeeded(obj);
+        if (beanValidator != null && beanValidator.shouldValidate(obj, beanValidationMode, prefValidatorFactory, bvNoOptimisation)) {
+            beanValidator.validate(result, beanValidationGroups);
+        }
+        return result;
+    }
+
+    private Object modifyObjectIfNeeded(Object obj) {
+        if (obj instanceof Collection) {
+            Collection objectList = (Collection) obj;
+            List newList = new ArrayList(objectList.size());
+            for (Object o : objectList) {
+                newList.add(modifySingleObjectIfNeeded(o));
+            }
+            return newList;
+        } else if (obj.getClass().isArray()) {
+            int arraySize = Array.getLength(obj);
+            List newList = new ArrayList(arraySize);
+            for (int x = 0; x < arraySize; x++) {
+                newList.add(modifySingleObjectIfNeeded(Array.get(obj, x)));
+            }
+            return newList;
+        } else {
+            return modifySingleObjectIfNeeded(obj);
+        }
+    }
+
+    private Object modifySingleObjectIfNeeded(Object obj){
+    // let the JAXBIntrospector determine if the object is a JAXBElement
+        if (obj instanceof JAXBElement) {
+            // use the JAXBElement's properties to populate an XMLRoot
+            return createXMLRootFromJAXBElement((JAXBElement) obj);
+        } else if(obj != null && obj.getClass().isEnum()) {
+            return wrapEnumeration(obj, obj.getClass());
+        } else if (obj instanceof JSONWithPadding){
+            Object nestedObject = ((JSONWithPadding)obj).getObject();
+            if(nestedObject != null){
+                Object newNestedObject = modifyObjectIfNeeded(nestedObject);
+                if(nestedObject != newNestedObject){
+                    return new JSONWithPadding(newNestedObject,((JSONWithPadding)obj).getCallbackName());
+                }
+            }
+        }
+        return obj;
+    }
+
+    public void marshal(Object object, XMLStreamWriter streamWriter, TypeMappingInfo type) throws JAXBException {
+        if (jaxbContext.getTypeMappingInfoToGeneratedType() == null) {
+            marshal(object, streamWriter);
+        } else {
+            JAXBElement element = null;
+            Object value = object;
+            if (object instanceof JAXBElement) {
+                // use the JAXBElement's properties to populate an XMLRoot
+                element = (JAXBElement) object;
+                value = element.getValue();
+            }
+            if(jaxbContext.getTypeMappingInfoToJavaTypeAdapters().size() > 0){
+                RootLevelXmlAdapter adapter = jaxbContext.getTypeMappingInfoToJavaTypeAdapters().get(type);
+                if (adapter != null) {
+                    try {
+                        value = adapter.getXmlAdapter().marshal(value);
+                    } catch (Exception ex) {
+                        throw new JAXBException(XMLMarshalException.marshalException(ex));
+                    }
+                }
+            }
+
+            value = wrapObject(value, element, type);
+            marshal(value, streamWriter);
+        }
+    }
+
+    private Object wrapObject(Object object, JAXBElement wrapperElement, TypeMappingInfo typeMappingInfo) {
+        if(jaxbContext.getTypeMappingInfoToGeneratedType().size() > 0){
+            Class generatedClass = jaxbContext.getTypeMappingInfoToGeneratedType().get(typeMappingInfo);
+            if(generatedClass != null && object == null && wrapperElement != null) {
+            return wrapObjectInXMLRoot(wrapperElement, null, typeMappingInfo);
+            }
+
+            if (generatedClass != null && WrappedValue.class.isAssignableFrom(generatedClass)) {
+                ClassDescriptor desc = xmlMarshaller.getXMLContext().getSession(generatedClass).getDescriptor(generatedClass);
+                Object newObject = desc.getInstantiationPolicy().buildNewInstance();
+                ((WrappedValue) newObject).setValue(object);
+                object = newObject;
+            } else if (generatedClass != null) {
+                // should be a many value
+                ClassDescriptor desc = xmlMarshaller.getXMLContext().getSession(generatedClass).getDescriptor(generatedClass);
+                Object newObject = desc.getInstantiationPolicy().buildNewInstance();
+                ((ManyValue) newObject).setItem(object);
+                object = newObject;
+            }
+        }
+
+        if (null == wrapperElement) {
+            Root xmlRoot = new Root();
+            QName xmlTagName = typeMappingInfo.getXmlTagName();
+            if (null == xmlTagName) {
+                return object;
+            }
+            xmlRoot.setNamespaceURI(typeMappingInfo.getXmlTagName().getNamespaceURI());
+            xmlRoot.setLocalName(typeMappingInfo.getXmlTagName().getLocalPart());
+            xmlRoot.setObject(object);
+            return xmlRoot;
+
+        }
+        return wrapObjectInXMLRoot(wrapperElement, object, typeMappingInfo);
+    }
+
+    private Root wrapObjectInXMLRoot(JAXBElement wrapperElement, Object value, TypeMappingInfo typeMappingInfo) {
+        Root xmlroot = new Root();
+        Object objectValue = value;
+        xmlroot.setObject(objectValue);
+        QName qname = wrapperElement.getName();
+        xmlroot.setLocalName(qname.getLocalPart());
+        xmlroot.setNamespaceURI(qname.getNamespaceURI());
+        xmlroot.setDeclaredType(wrapperElement.getDeclaredType());
+        if(typeMappingInfo != null){
+            xmlroot.setSchemaType(typeMappingInfo.getSchemaType());
+        } else if(value != null) {
+            if (value.getClass() == CoreClassConstants.ABYTE || value.getClass() == CoreClassConstants.APBYTE ||
+                    value.getClass().getCanonicalName().equals("javax.activation.DataHandler")) {
+                xmlroot.setSchemaType(Constants.BASE_64_BINARY_QNAME);
+            }
+        }
+        return xmlroot;
+    }
+
+    @Override
+    public void marshal(Object object, Writer writer) throws JAXBException {
+        if (object == null || writer == null) {
+            throw new IllegalArgumentException();
+        }
+
+        Listener listener = getListener();
+        if(listener != null) {
+            if(object instanceof JAXBElement) {
+                listener.beforeMarshal(object);
+            }
+        }
+
+        Object oxmObject = validateAndTransformIfNeeded(object); // xml bindings + object
+        try {
+            xmlMarshaller.marshal(oxmObject, writer);
+        } catch (BeanValidationException bve) {
+            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
+        } catch (Exception e) {
+            throw new MarshalException(e);
+        }
+
+        if(listener != null) {
+            if(object instanceof JAXBElement) {
+                listener.afterMarshal(object);
+            }
+        }
+    }
+
+    public void marshal(Object object, MarshalRecord record) throws JAXBException {
+        if (object == null || record == null) {
+            throw new IllegalArgumentException();
+        }
+        object = validateAndTransformIfNeeded(object); // xml bindings + object
+
+        try {
+            record.setMarshaller(xmlMarshaller);
+            xmlMarshaller.marshal(object, record);
+        } catch (BeanValidationException bve) {
+            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
+        } catch (Exception e) {
+            throw new MarshalException(e);
+        }
+    }
+
+    public void marshal(Object object, MarshalRecord record, TypeMappingInfo type) throws JAXBException {
+        if (jaxbContext.getTypeMappingInfoToGeneratedType() == null) {
+            marshal(object, record);
+        } else {
+            JAXBElement element = null;
+            Object value = object;
+            if (object instanceof JAXBElement) {
+                // use the JAXBElement's properties to populate an XMLRoot
+                element = (JAXBElement) object;
+                value = element.getValue();
+            }
+            RootLevelXmlAdapter adapter = jaxbContext.getTypeMappingInfoToJavaTypeAdapters().get(type);
+            if (adapter != null) {
+                try {
+                    value = adapter.getXmlAdapter().marshal(value);
+                } catch (Exception ex) {
+                    throw new JAXBException(XMLMarshalException.marshalException(ex));
+                }
+            }
+            value = wrapObject(value, element, type);
+            marshal(value, record);
+        }
+    }
+
+    @Override
+    public void setAdapter(Class javaClass, XmlAdapter adapter) {
+        HashMap result = (HashMap) xmlMarshaller.getProperty(XML_JAVATYPE_ADAPTERS);
+        if (result == null) {
+            result = new HashMap();
+            xmlMarshaller.getProperties().put(XML_JAVATYPE_ADAPTERS, result);
+        }
+        result.put(javaClass, adapter);
+    }
+
+    @Override
+    public void setAdapter(XmlAdapter adapter) {
+        setAdapter(adapter.getClass(), adapter);
+    }
+
+    @Override
+    public void setAttachmentMarshaller(AttachmentMarshaller attachmentMarshaller) {
+        if (attachmentMarshaller == null) {
+            xmlMarshaller.setAttachmentMarshaller(null);
+        } else {
+            xmlMarshaller.setAttachmentMarshaller(new AttachmentMarshallerAdapter(attachmentMarshaller));
+        }
+    }
+
+    @Override
+    public void setEventHandler(ValidationEventHandler newValidationEventHandler) throws JAXBException {
+        if (null == newValidationEventHandler) {
+            validationEventHandler = JAXBContext.DEFAULT_VALIDATION_EVENT_HANDLER;
+        } else {
+            validationEventHandler = newValidationEventHandler;
+        }
+        xmlMarshaller.setErrorHandler(new JAXBErrorHandler(validationEventHandler));
+    }
+
+    @Override
+    public void setListener(Marshaller.Listener listener) {
+        if(xmlMarshaller.getMarshalListener() == null) {
+            xmlMarshaller.setMarshalListener(new JAXBMarshalListener(jaxbContext, this));
+        }
+        ((JAXBMarshalListener) xmlMarshaller.getMarshalListener()).setListener(listener);
+    }
+
+    public void setMarshalCallbacks(Map callbacks) {
+        if(callbacks == null || callbacks.isEmpty()) {
+            return;
+        }
+        if(xmlMarshaller.getMarshalListener() == null) {
+            xmlMarshaller.setMarshalListener(new JAXBMarshalListener(jaxbContext, this));
+        }
+        ((JAXBMarshalListener) xmlMarshaller.getMarshalListener()).setClassBasedMarshalEvents(callbacks);
+    }
+
+    /**
+     * Set a property on the JAXBMarshaller. Attempting to set any unsupported
+     * property will result in a javax.xml.bind.PropertyException
+     * @see org.eclipse.persistence.jaxb.MarshallerProperties
+     */
+    @Override
+    public void setProperty(String key, Object value) throws PropertyException {
+        try {
+            if (key == null) {
+                throw new IllegalArgumentException();
+            } else if (Constants.JAXB_FRAGMENT.equals(key)) {
+                if(value == null){
+                     throw new PropertyException(key, Constants.EMPTY_STRING);
+                }
+                Boolean fragment = (Boolean) value;
+                xmlMarshaller.setFragment(fragment.booleanValue());
+            } else if (JAXB_FORMATTED_OUTPUT.equals(key)) {
+                if(value == null){
+                     throw new PropertyException(key, Constants.EMPTY_STRING);
+                 }
+                Boolean formattedOutput = (Boolean) value;
+                xmlMarshaller.setFormattedOutput(formattedOutput.booleanValue());
+            } else if (JAXB_ENCODING.equals(key)) {
+                xmlMarshaller.setEncoding((String) value);
+            } else if (JAXB_SCHEMA_LOCATION.equals(key)) {
+                xmlMarshaller.setSchemaLocation((String) value);
+            } else if (JAXB_NO_NAMESPACE_SCHEMA_LOCATION.equals(key)) {
+                xmlMarshaller.setNoNamespaceSchemaLocation((String) value);
+            } else if(MarshallerProperties.NAMESPACE_PREFIX_MAPPER.equals(key)) {
+                if(value == null){
+                    xmlMarshaller.setNamespacePrefixMapper(null);
+                }else if(value instanceof Map){
+                    NamespacePrefixMapper namespacePrefixMapper = new MapNamespacePrefixMapper((Map)value);
+                    xmlMarshaller.setNamespacePrefixMapper(namespacePrefixMapper);
+                }else{
+                    xmlMarshaller.setNamespacePrefixMapper((NamespacePrefixMapper)value);
+                }
+            } else if(SUN_NAMESPACE_PREFIX_MAPPER.equals(key) || SUN_JSE_NAMESPACE_PREFIX_MAPPER.equals(key)) {
+                if(value == null){
+                    xmlMarshaller.setNamespacePrefixMapper(null);
+                }else{
+                    xmlMarshaller.setNamespacePrefixMapper(new NamespacePrefixMapperWrapper(value));
+                }
+            } else if (MarshallerProperties.INDENT_STRING.equals(key) || SUN_INDENT_STRING.equals(key) || SUN_JSE_INDENT_STRING.equals(key)) {
+                xmlMarshaller.setIndentString((String) value);
+            } else if (MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS.equals(key)){
+                xmlMarshaller.setMarshalEmptyCollections((Boolean) value);
+            } else if (MarshallerProperties.JSON_REDUCE_ANY_ARRAYS.equals(key)){
                 xmlMarshaller.setReduceAnyArrays((Boolean) value);
             } else if (MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME.equals(key)) {
                 xmlMarshaller.setWrapperAsCollectionName((Boolean) value);
@@ -883,122 +906,126 @@
             } else if (MarshallerProperties.CHARACTER_ESCAPE_HANDLER.equals(key)) {
                 xmlMarshaller.setCharacterEscapeHandler((CharacterEscapeHandler) value);
             } else if (SUN_CHARACTER_ESCAPE_HANDLER.equals(key) || SUN_JSE_CHARACTER_ESCAPE_HANDLER.equals(key)  ||SUN_CHARACTER_ESCAPE_HANDLER_MARSHALLER.equals(key) || SUN_JSE_CHARACTER_ESCAPE_HANDLER_MARSHALLER.equals(key)) {
-                if (value == null) {

-                    xmlMarshaller.setCharacterEscapeHandler(null);

-                } else {

-                    xmlMarshaller.setCharacterEscapeHandler(new CharacterEscapeHandlerWrapper(value));

-                }

-            } else if (XML_DECLARATION.equals(key)) {

-            	if(value == null){

-                 	throw new PropertyException(key, Constants.EMPTY_STRING);                	

-                 }

-                Boolean fragment = !(Boolean) value;

-                xmlMarshaller.setFragment(fragment.booleanValue());

-            } else if (XML_HEADERS.equals(key)) {

-                xmlMarshaller.setXmlHeader((String) value);

-            } else if (OBJECT_IDENTITY_CYCLE_DETECTION.equals(key)) {

-            	if(value == null){

-                 	throw new PropertyException(key, Constants.EMPTY_STRING);                	

-                 }

-                xmlMarshaller.setEqualUsingIdenity(((Boolean) value).booleanValue());

-            } else if (MarshallerProperties.MEDIA_TYPE.equals(key)) {

-                MediaType mType = null;

-                if(value instanceof MediaType) {

-                    mType = (MediaType) value;

-                } else if(value instanceof String) {

-                    mType = MediaType.getMediaType((String)value);

-                }

-                if(mType == null){

-                	throw new PropertyException(key, Constants.EMPTY_STRING);                	

-                }                 

-                xmlMarshaller.setMediaType(mType);

-            } else if (MarshallerProperties.JSON_ATTRIBUTE_PREFIX.equals(key)) {

-                xmlMarshaller.setAttributePrefix((String)value);

-            } else if (MarshallerProperties.JSON_INCLUDE_ROOT.equals(key)) {

-		 if(value == null){

-			throw new PropertyException(key, Constants.EMPTY_STRING);

-                 }

-                xmlMarshaller.setIncludeRoot((Boolean)value);

-            } else if(MarshallerProperties.JSON_VALUE_WRAPPER.equals(key)){

-                if(value == null || (((String)value).length() == 0)){

-                    throw new PropertyException(key, Constants.EMPTY_STRING);

-                }

-                xmlMarshaller.setValueWrapper((String)value);

-            } else if(MarshallerProperties.JSON_NAMESPACE_SEPARATOR.equals(key)){

-		if(value == null){

-			throw new PropertyException(key, Constants.EMPTY_STRING);

-                 }

-                xmlMarshaller.setNamespaceSeparator((Character)value);

-            } else if(MarshallerProperties.OBJECT_GRAPH.equals(key)) {

-                if(value == null) {

-                    xmlMarshaller.setMarshalAttributeGroup(null);

-                } else if(value instanceof ObjectGraphImpl) {

-                    xmlMarshaller.setMarshalAttributeGroup(((ObjectGraphImpl)value).getAttributeGroup());

-                } else if(value.getClass() == ClassConstants.STRING){

-                    xmlMarshaller.setMarshalAttributeGroup(value);

-                } else {

-                    throw org.eclipse.persistence.exceptions.JAXBException.invalidValueForObjectGraph(value);

-                }

-            } else if (MarshallerProperties.BEAN_VALIDATION_MODE.equals(key)) {

-                if(value == null){

-                    throw new PropertyException(key, Constants.EMPTY_STRING);

-                }

-                this.beanValidationMode = ((BeanValidationMode) value);

-            } else if (MarshallerProperties.BEAN_VALIDATION_FACTORY.equals(key)) {

-                //noinspection StatementWithEmptyBody

+                if (value == null) {
+                    xmlMarshaller.setCharacterEscapeHandler(null);
+                } else {
+                    xmlMarshaller.setCharacterEscapeHandler(new CharacterEscapeHandlerWrapper(value));
+                }
+            } else if (XML_DECLARATION.equals(key)) {
+            	if(value == null){
+                 	throw new PropertyException(key, Constants.EMPTY_STRING);                	
+                 }
+                Boolean fragment = !(Boolean) value;
+                xmlMarshaller.setFragment(fragment.booleanValue());
+            } else if (XML_HEADERS.equals(key)) {
+                xmlMarshaller.setXmlHeader((String) value);
+            } else if (OBJECT_IDENTITY_CYCLE_DETECTION.equals(key)) {
+            	if(value == null){
+                 	throw new PropertyException(key, Constants.EMPTY_STRING);                	
+                 }
+                xmlMarshaller.setEqualUsingIdenity(((Boolean) value).booleanValue());
+            } else if (MarshallerProperties.MEDIA_TYPE.equals(key)) {
+                MediaType mType = null;
+                if(value instanceof MediaType) {
+                    mType = (MediaType) value;
+                } else if(value instanceof String) {
+                    mType = MediaType.getMediaType((String)value);
+                }
+                if(mType == null){
+                	throw new PropertyException(key, Constants.EMPTY_STRING);                	
+                }                 
+                xmlMarshaller.setMediaType(mType);
+            } else if (MarshallerProperties.JSON_ATTRIBUTE_PREFIX.equals(key)) {
+                xmlMarshaller.setAttributePrefix((String)value);
+            } else if (MarshallerProperties.JSON_INCLUDE_ROOT.equals(key)) {
+		 if(value == null){
+			throw new PropertyException(key, Constants.EMPTY_STRING);
+                 }
+                xmlMarshaller.setIncludeRoot((Boolean)value);
+            } else if(MarshallerProperties.JSON_VALUE_WRAPPER.equals(key)){
+                if(value == null || (((String)value).length() == 0)){
+                    throw new PropertyException(key, Constants.EMPTY_STRING);
+                }
+                xmlMarshaller.setValueWrapper((String)value);
+            } else if(MarshallerProperties.JSON_NAMESPACE_SEPARATOR.equals(key)){
+		if(value == null){
+			throw new PropertyException(key, Constants.EMPTY_STRING);
+                 }
+                xmlMarshaller.setNamespaceSeparator((Character)value);
+            } else if(MarshallerProperties.OBJECT_GRAPH.equals(key)) {
                 if(value == null) {
-                    // Allow null value for preferred validation factory.

-                }

-                this.prefValidatorFactory = ((ValidatorFactory)value);
-            } else if (MarshallerProperties.BEAN_VALIDATION_GROUPS.equals(key)) {

-                if(value == null){

-                    throw new PropertyException(key, Constants.EMPTY_STRING);

-                }

-                this.beanValidationGroups = ((Class<?>[]) value);

-            } else if (MarshallerProperties.BEAN_VALIDATION_NO_OPTIMISATION.equals(key)) {

-                if(value == null){

-                    throw new PropertyException(key, Constants.EMPTY_STRING);

-                }

-                this.bvNoOptimisation = ((boolean) value);

-            } else {

-                throw new PropertyException(key, value);

-            }

-        } catch (ClassCastException exception) {

-            throw new PropertyException(key, exception);

-        }

-    }

-

-    public void setSchema(Schema schema) {

-        this.xmlMarshaller.setSchema(schema);

-    }

-

-    private Map<String, Class> getClassToGeneratedClasses() {

-        return jaxbContext.getClassToGeneratedClasses();

-    }

-

-    public JAXBContext getJaxbContext() {

-        return jaxbContext;

-    }

-

-    public XMLMarshaller getXMLMarshaller() {

-        return this.xmlMarshaller;

-    }

-

-    /**

-     * Returns constraint violations stored in the underlying

-     * {@link org.eclipse.persistence.jaxb.JAXBBeanValidator} instance.

-     *

-     * @return set of constraint violations from last unmarshal

-     */

-    public Set<ConstraintViolation<Object>> getConstraintViolations() {
-        return beanValidator.getConstraintViolations();

-    }

-

-    private static class CharacterEscapeHandlerWrapper extends org.eclipse.persistence.internal.oxm.record.CharacterEscapeHandlerWrapper implements CharacterEscapeHandler {

-

-        public CharacterEscapeHandlerWrapper(Object sunHandler) {

-            super(sunHandler);

-        }

-

-    }

-}

+                    xmlMarshaller.setMarshalAttributeGroup(null);
+                } else if(value instanceof ObjectGraphImpl) {
+                    xmlMarshaller.setMarshalAttributeGroup(((ObjectGraphImpl)value).getAttributeGroup());
+                } else if(value.getClass() == ClassConstants.STRING){
+                    xmlMarshaller.setMarshalAttributeGroup(value);
+                } else {
+                    throw org.eclipse.persistence.exceptions.JAXBException.invalidValueForObjectGraph(value);
+                }
+            } else if (MarshallerProperties.BEAN_VALIDATION_MODE.equals(key)) {
+                if(value == null){
+                    throw new PropertyException(key, Constants.EMPTY_STRING);
+                }
+                this.beanValidationMode = ((BeanValidationMode) value);
+            } else if (MarshallerProperties.BEAN_VALIDATION_FACTORY.equals(key)) {
+                //noinspection StatementWithEmptyBody
+                if(value == null) {
+                    // Allow null value for preferred validation factory.
+                }
+                this.prefValidatorFactory = value;
+            } else if (MarshallerProperties.BEAN_VALIDATION_GROUPS.equals(key)) {
+                if(value == null){
+                    throw new PropertyException(key, Constants.EMPTY_STRING);
+                }
+                this.beanValidationGroups = ((Class<?>[]) value);
+            } else if (MarshallerProperties.BEAN_VALIDATION_NO_OPTIMISATION.equals(key)) {
+                if(value == null){
+                    throw new PropertyException(key, Constants.EMPTY_STRING);
+                }
+                this.bvNoOptimisation = ((boolean) value);
+            } else {
+                throw new PropertyException(key, value);
+            }
+        } catch (ClassCastException exception) {
+            throw new PropertyException(key, exception);
+        }
+    }
+
+    @Override
+    public void setSchema(Schema schema) {
+        this.xmlMarshaller.setSchema(schema);
+    }
+
+    private Map<String, Class> getClassToGeneratedClasses() {
+        return jaxbContext.getClassToGeneratedClasses();
+    }
+
+    public JAXBContext getJaxbContext() {
+        return jaxbContext;
+    }
+
+    public XMLMarshaller getXMLMarshaller() {
+        return this.xmlMarshaller;
+    }
+
+    /**
+     * Returns constraint violations stored in the underlying
+     * {@link org.eclipse.persistence.jaxb.JAXBBeanValidator} instance.
+     *
+     * @return set of constraint violations from last unmarshal
+     */
+    public Set<ConstraintViolationWrapper<Object>> getConstraintViolations() {
+        if (beanValidator != null) {
+            return beanValidator.getConstraintViolations();
+        }
+        return Collections.emptySet();
+    }
+
+    private static class CharacterEscapeHandlerWrapper extends org.eclipse.persistence.internal.oxm.record.CharacterEscapeHandlerWrapper implements CharacterEscapeHandler {
+
+        public CharacterEscapeHandlerWrapper(Object sunHandler) {
+            super(sunHandler);
+        }
+
+    }
+}
diff --git a/moxy/org.eclipse.persistence.moxy/src/org/eclipse/persistence/jaxb/JAXBUnmarshaller.java b/moxy/org.eclipse.persistence.moxy/src/org/eclipse/persistence/jaxb/JAXBUnmarshaller.java
index 9ab0a24..35ab727 100644
--- a/moxy/org.eclipse.persistence.moxy/src/org/eclipse/persistence/jaxb/JAXBUnmarshaller.java
+++ b/moxy/org.eclipse.persistence.moxy/src/org/eclipse/persistence/jaxb/JAXBUnmarshaller.java
@@ -21,6 +21,7 @@
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.net.URL;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
@@ -28,8 +29,6 @@
 import java.util.Set;
 import java.util.StringTokenizer;
 
-import javax.validation.ConstraintViolation;
-import javax.validation.ValidatorFactory;
 import javax.xml.bind.JAXBElement;
 import javax.xml.bind.JAXBException;
 import javax.xml.bind.PropertyException;
@@ -97,12 +96,14 @@
  */
 public class JAXBUnmarshaller implements Unmarshaller {
 
-    private final JAXBBeanValidator beanValidator;
+    private JAXBBeanValidator beanValidator;
 
     private BeanValidationMode beanValidationMode;
-    private ValidatorFactory prefValidatorFactory;
+
+    // The actual type is ValidatorFactory. It's done due to optional nature of javax.validation.
+    private Object prefValidatorFactory;
     private boolean bvNoOptimisation = false;
-    private Class<?>[] beanValidationGroups = JAXBBeanValidator.DEFAULT_GROUP_ARRAY;
+    private Class<?>[] beanValidationGroups;
 
     private final XMLUnmarshaller xmlUnmarshaller;
     private final JAXBContext jaxbContext;
@@ -118,7 +119,9 @@
         this.jaxbContext = jaxbContext;
         validationEventHandler = JAXBContext.DEFAULT_VALIDATION_EVENT_HANDLER;
         beanValidationMode = BeanValidationMode.AUTO;
-        beanValidator = JAXBBeanValidator.getUnmarshallingBeanValidator(this.jaxbContext);
+        if (BeanValidationChecker.isBeanValidationPresent()) {
+            beanValidator = JAXBBeanValidator.getUnmarshallingBeanValidator(this.jaxbContext);
+        }
         xmlUnmarshaller = newXMLUnmarshaller;
         xmlUnmarshaller.setValidationMode(XMLUnmarshaller.NONVALIDATING);
         xmlUnmarshaller.setUnmarshalListener(new JAXBUnmarshalListener(this));
@@ -236,7 +239,7 @@
     }
 
     private JAXBElement validateAndBuildJAXBElement(Object obj, Class declaredClass) throws BeanValidationException {
-        if (beanValidator.shouldValidate(obj, beanValidationMode, prefValidatorFactory, bvNoOptimisation)) {
+        if (beanValidator != null && beanValidator.shouldValidate(obj, beanValidationMode, prefValidatorFactory, bvNoOptimisation)) {
             beanValidator.validate(obj, beanValidationGroups);
         }
         return buildJAXBElementFromObject(obj, declaredClass);
@@ -884,10 +887,8 @@
             }
             this.beanValidationMode = ((BeanValidationMode) value);
         } else if (UnmarshallerProperties.BEAN_VALIDATION_FACTORY.equals(key)) {
-            if(value == null){
-                // Allow null value for preferred validation factory.
-            }
-            this.prefValidatorFactory = ((ValidatorFactory)value);
+            // Null value is allowed
+            this.prefValidatorFactory = value;
         } else if (UnmarshallerProperties.BEAN_VALIDATION_GROUPS.equals(key)) {
             if (value == null) {
                 throw new PropertyException(key, Constants.EMPTY_STRING);
@@ -1054,7 +1055,7 @@
     }
 
     private Object validateAndTransformIfRequired(Object obj) throws BeanValidationException {
-        if (beanValidator.shouldValidate(obj, beanValidationMode, prefValidatorFactory, bvNoOptimisation)) {
+        if (beanValidator != null && beanValidator.shouldValidate(obj, beanValidationMode, prefValidatorFactory, bvNoOptimisation)) {
             beanValidator.validate(obj, beanValidationGroups);
         }
         return createJAXBElementOrUnwrapIfRequired(obj);
@@ -1138,8 +1139,11 @@
      *
      * @return set of constraint violations from last unmarshal
      */
-    public Set<? extends ConstraintViolation<?>> getConstraintViolations() {
-        return beanValidator.getConstraintViolations();
+    public Set<ConstraintViolationWrapper<Object>> getConstraintViolations() {
+        if (beanValidator != null) {
+            return beanValidator.getConstraintViolations();
+        }
+        return Collections.emptySet();
     }
 
     private static class PrimitiveContentHandler<T> extends DefaultHandler {
diff --git a/plugins/javax.validation_1.1.0.v201304101302.jar b/plugins/javax.validation_1.1.0.v201304101302.jar
index 8414119..aca36fa 100644
--- a/plugins/javax.validation_1.1.0.v201304101302.jar
+++ b/plugins/javax.validation_1.1.0.v201304101302.jar
Binary files differ