Issue: 10030 Part 1: make @Resource work for Validator and ValidatorFactory Part 2: Make java:comp/Validator and java:comp/ValidatorFactory work in JNDI Author: Ken Saks and Ed Burns SECTION: Changes for Part 1 M deployment/dol/src/main/java/com/sun/enterprise/deployment/JmsDestinationReferenceDescriptor.java - Make this class aware of Validator and ValidatorFactory as valid JmsDestinations. M common/container-common/src/main/java/com/sun/enterprise/container/common/impl/ComponentEnvManagerImpl.java - Factory boilerplate code for obtaining a reference to an instance of Validator or ValidatorFactory. Ken, how do I store it in the ctx so subsequent lookups can find it there? When I try to bind() it says I can't store into the comp: namespace. M tests/quicklook/bean-validator/integration-test-servlet/metadata/web.xml A tests/quicklook/bean-validator/integration-test-servlet/src/java/integration_test_servlet/ValidatorFactoryInjectionTestServlet.java - Automated test code SECTION: Diffs for Part 1 Index: tests/quicklook/bean-validator/integration-test-servlet/metadata/web.xml =================================================================== --- tests/quicklook/bean-validator/integration-test-servlet/metadata/web.xml (revision 32299) +++ tests/quicklook/bean-validator/integration-test-servlet/metadata/web.xml (working copy) @@ -1,7 +1,7 @@ - + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> BVIntegrationTestServlet integration_test_servlet.BVIntegrationTestServlet @@ -10,5 +10,28 @@ BVIntegrationTestServlet /test/* + + + ValidatorFactoryInjectionTestServlet + integration_test_servlet.ValidatorFactoryInjectionTestServlet + + + ValidatorFactoryInjectionTestServlet + /testInject/* + + + + Index: tests/quicklook/bean-validator/integration-test-servlet/src/java/integration_test_servlet/ValidatorFactoryInjectionTestServlet.java =================================================================== --- tests/quicklook/bean-validator/integration-test-servlet/src/java/integration_test_servlet/ValidatorFactoryInjectionTestServlet.java (revision 0) +++ tests/quicklook/bean-validator/integration-test-servlet/src/java/integration_test_servlet/ValidatorFactoryInjectionTestServlet.java (revision 0) @@ -0,0 +1,142 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can obtain + * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html + * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt. + * Sun designates this particular file as subject to the "Classpath" exception + * as provided by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the License + * Header, with the fields enclosed by brackets [] replaced by your own + * identifying information: "Portions Copyrighted [year] + * [name of copyright owner]" + * + * Contributor(s): + * + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ + +package integration_test_servlet; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import javax.annotation.Resource; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.validation.ConstraintViolation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; + +public class ValidatorFactoryInjectionTestServlet extends HttpServlet { + + @Resource + Validator beanValidator; + + @Resource + ValidatorFactory validatorFactory; + + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + PrintWriter out = resp.getWriter(); + resp.setContentType("text/html"); + out.print("SimpleBVServlet"); + + out.print("

"); + out.print("Obtained ValidatorFactory: " + validatorFactory + "."); + out.print("

"); + + out.print("

"); + out.print("Validating person class using validateValue with valid property"); + out.print("

"); + + List listOfString = new ArrayList(); + listOfString.add("one"); + listOfString.add("two"); + listOfString.add("three"); + + Set> violations = + beanValidator.validateValue(Person.class, "listOfString", listOfString); + + printConstraintViolations(out, violations, "case1"); + + out.print("

"); + out.print("Validating person class using validateValue with invalid property"); + out.print("

"); + + try { + violations = + beanValidator.validateValue(Person.class, "nonExistentProperty", listOfString); + } catch (IllegalArgumentException iae) { + out.print("

"); + out.print("case2: caught IllegalArgumentException. Message: " + + iae.getMessage()); + out.print("

"); + } + Person person = new Person(); + + out.print("

"); + out.print("Validating invalid person instance using validate."); + out.print("

"); + + violations = beanValidator.validate(person); + + printConstraintViolations(out, violations, "case3"); + + out.print("

"); + out.print("Validating valid person."); + out.print("

"); + + person.setFirstName("John"); + person.setLastName("Yaya"); + person.setListOfString(listOfString); + + violations = beanValidator.validate(person); + printConstraintViolations(out, violations, "case4"); + + out.print(""); + + } + + private void printConstraintViolations(PrintWriter out, + Set> violations, String caseId) { + if (violations.isEmpty()) { + out.print("

"); + out.print(caseId + ": No ConstraintViolations found."); + out.print("

"); + } else { + for (ConstraintViolation curViolation : violations) { + out.print("

"); + out.print(caseId + ": ConstraintViolation: message: " + curViolation.getMessage() + + " propertyPath: " + curViolation.getPropertyPath()); + out.print("

"); + } + } + + } + + +} Index: common/container-common/src/main/java/com/sun/enterprise/container/common/impl/ComponentEnvManagerImpl.java =================================================================== --- common/container-common/src/main/java/com/sun/enterprise/container/common/impl/ComponentEnvManagerImpl.java (revision 32299) +++ common/container-common/src/main/java/com/sun/enterprise/container/common/impl/ComponentEnvManagerImpl.java (working copy) @@ -66,6 +66,11 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; +import javax.validation.Validation; +import javax.validation.ValidationException; +import javax.validation.Validator; +import javax.validation.ValidatorContext; +import javax.validation.ValidatorFactory; @Service public class ComponentEnvManagerImpl @@ -552,6 +557,10 @@ Object value = null; if (next.isEJBContext()) { value = new EjbContextProxy(next.getRefType()); + } else if( next.isValidator() ) { + value = new ValidatorProxy(); + } else if( next.isValidatorFactory() ) { + value = new ValidatorFactoryProxy(); } else if( next.isCDIBeanManager() ) { value = namingUtils.createLazyNamingObjectFactory(name, "java:comp/BeanManager", false); } else { @@ -839,6 +848,100 @@ } + private class ValidatorProxy + implements NamingObjectProxy { + + private volatile ValidatorFactory validatorFactory; + private volatile Validator validator; + + ValidatorProxy() { + } + + @Override + public Object create(Context ctx) + throws NamingException { + final String nameForValidator = "java:comp/Validator"; + String exceptionMessage = "Can not obtain reference to Validator instance "; + + // Phase 1, obtain a reference to the Validator + + // case 1, try to look in the ctx + if (null == validator) { + try { + validator = (Validator) ctx.lookup(nameForValidator); + } catch (NamingException ne) { + exceptionMessage = "Unable to lookup " + + nameForValidator + ":" + ne.toString(); + } + } + + // case 2, Create a new Validator instance + if (null == validator) { + + // case 2a no validatorFactory + if (null == validatorFactory) { + ValidatorFactoryProxy factoryProxy = new ValidatorFactoryProxy(); + validatorFactory = (ValidatorFactory) factoryProxy.create(ctx); + } + + // Use the ValidatorFactory to create a Validator + if (null != validatorFactory) { + ValidatorContext validatorContext = validatorFactory.usingContext(); + validator = validatorContext.getValidator(); + } + } + + if( validator == null ) { + throw new NameNotFoundException(exceptionMessage); + } + + return validator; + } + + } + + private class ValidatorFactoryProxy + implements NamingObjectProxy { + + private volatile ValidatorFactory validatorFactory; + + ValidatorFactoryProxy() { + } + + @Override + public Object create(Context ctx) + throws NamingException { + final String nameForValidatorFactory = "java:comp/ValidatorFactory"; + String exceptionMessage = "Can not obtain reference to ValidatorFactory instance "; + + // Phase 1, obtain a reference to the ValidatorFactory + + // case 1, try to look in the ctx + if (null == validatorFactory) { + try { + validatorFactory = (ValidatorFactory) + ctx.lookup(nameForValidatorFactory); + } catch (NamingException ne) { + exceptionMessage = "Unable to lookup " + + nameForValidatorFactory + ":" + ne.toString(); + } + } + + // case 2, create the ValidatorFactory using the spec. + if (null == validatorFactory) { + try { + validatorFactory = Validation.buildDefaultValidatorFactory(); + } catch (ValidationException e) { + exceptionMessage = "Could not build a default Bean Validator factory: " + + e.toString(); + } + } + + return validatorFactory; + } + + } + private class WebServiceRefProxy implements NamingObjectProxy { Index: deployment/dol/src/main/java/com/sun/enterprise/deployment/JmsDestinationReferenceDescriptor.java =================================================================== --- deployment/dol/src/main/java/com/sun/enterprise/deployment/JmsDestinationReferenceDescriptor.java (revision 32299) +++ deployment/dol/src/main/java/com/sun/enterprise/deployment/JmsDestinationReferenceDescriptor.java (working copy) @@ -50,6 +50,8 @@ private static final String EJB_CTX_TYPE ="javax.ejb.EJBContext"; private static final String EJB_TIMER_SERVICE_TYPE = "javax.ejb.TimerService"; + private static final String VALIDATION_VALIDATOR ="javax.validation.Validator"; + private static final String VALIDATION_VALIDATOR_FACTORY ="javax.validation.ValidatorFactory"; private static final String CDI_BEAN_MANAGER_TYPE = "javax.enterprise.inject.spi.BeanManager"; @@ -106,6 +108,14 @@ getRefType().equals(EJB_TIMER_SERVICE_TYPE)); } + public boolean isValidator() { + return (getRefType().equals(VALIDATION_VALIDATOR)); + } + + public boolean isValidatorFactory() { + return (getRefType().equals(VALIDATION_VALIDATOR_FACTORY)); + } + public boolean isCDIBeanManager() { return (getRefType().equals(CDI_BEAN_MANAGER_TYPE)); } SECTION: Changes for Part 2, in https://svn.dev.java.net/svn/glassfish-svn/trunk/external/modules/bean-validator/bean-validator-source-build A bundle/osgi/src/main/java/org/glassfish/enterprise/bean_validator/BeanValidatorNamingProxy.java - Per Ken Saks's advice, make an HK2 @Service that allows JNDI lookup for java:comp/Validator and java:comp/ValidatorFactory to succeed. A bundle/osgi/src/main/resources/META-INF/inhabitants/default - Per Mahesh Kannan's advice, this is the extra special sauce to declare the @Service annotated class to the system. M bundle/osgi/pom.xml - dependencies to enable compiling the java source part of this jar project. SECTION: Diffs for Part 2, Index: bundle/osgi/src/main/java/org/glassfish/enterprise/bean_validator/BeanValidatorNamingProxy.java =================================================================== --- bundle/osgi/src/main/java/org/glassfish/enterprise/bean_validator/BeanValidatorNamingProxy.java (revision 0) +++ bundle/osgi/src/main/java/org/glassfish/enterprise/bean_validator/BeanValidatorNamingProxy.java (revision 0) @@ -0,0 +1,100 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can obtain + * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html + * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt. + * Sun designates this particular file as subject to the "Classpath" exception + * as provided by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the License + * Header, with the fields enclosed by brackets [] replaced by your own + * identifying information: "Portions Copyrighted [year] + * [name of copyright owner]" + * + * Contributor(s): + * + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ + +package org.glassfish.enterprise.bean_validator; + +import javax.naming.NamingException; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorContext; +import javax.validation.ValidatorFactory; +import org.glassfish.api.naming.NamedNamingObjectProxy; +import org.jvnet.hk2.annotations.Service; + +@Service +public class BeanValidatorNamingProxy implements NamedNamingObjectProxy { + + static final String nameForValidator = "java:comp/Validator"; + static final String nameForValidatorFactory = "java:comp/ValidatorFactory"; + + private ValidatorFactory validatorFactory; + private Validator validator; + + + public Object handle(String name) throws NamingException { + Object result = null; + + if (nameForValidator.equals(name)) { + result = getValidator(); + } else if (nameForValidatorFactory.equals(name)) { + result = getValidatorFactory(); + } + return result; + } + + private Validator getValidator() throws NamingException { + if (null == validator) { + try { + ValidatorFactory factory = getValidatorFactory(); + ValidatorContext validatorContext = factory.usingContext(); + validator = validatorContext.getValidator(); + } catch (Throwable t) { + NamingException ne = new NamingException("Error retrieving Validator for " + nameForValidator + " lookup"); + ne.initCause(t); + throw ne; + } + } + return validator; + } + + private ValidatorFactory getValidatorFactory() throws NamingException { + + if (null == validatorFactory) { + try { + validatorFactory = Validation.buildDefaultValidatorFactory(); + } catch (Throwable t) { + NamingException ne = new NamingException("Error retrieving ValidatorFactory for " + nameForValidatorFactory + " lookup"); + ne.initCause(t); + throw ne; + } + } + + return validatorFactory; + } + + + +} Index: bundle/osgi/src/main/resources/META-INF/inhabitants/default =================================================================== --- bundle/osgi/src/main/resources/META-INF/inhabitants/default (revision 0) +++ bundle/osgi/src/main/resources/META-INF/inhabitants/default (revision 0) @@ -0,0 +1 @@ +class=org.glassfish.enterprise.bean_validator.BeanValidatorNamingProxy,index=org.glassfish.api.naming.NamedNamingObjectProxy Index: bundle/osgi/pom.xml =================================================================== --- bundle/osgi/pom.xml (revision 32705) +++ bundle/osgi/pom.xml (working copy) @@ -6,6 +6,27 @@ 3.0-JBoss-4.0.0.GA Module repackaging of the Hibernate validator library and Validation API (JSR 303) + + + org.glassfish.common + glassfish-api + 3.0-SNAPSHOT + provided + + + com.sun.enterprise + hk2 + 0.3.96 + provided + + + javax.validation + validation-api + 1.0.0.GA + provided + + + install @@ -208,9 +229,9 @@ *;scope=compile;inline=true - javax.validation.* + javax.validation.*,org.glassfish.enterprise.bean_validator.* org.hibernate.*,org.slf4j.*,com.googlecode.* - javax.persistence.*,javax.xml.*,org.xml.* + javax.persistence.*,javax.xml.*,org.xml.*,org.glassfish.api.naming.*,org.jvnet.hk2.annotations.*,javax.naming.*