Forked from codyaray/ValidatingJacksonJsonProvider.java
Last active
February 14, 2023 18:09
Star
You must be signed in to star a gist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.mydomain.myapp.resources; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.io.OutputStream; | |
import java.lang.annotation.Annotation; | |
import java.lang.reflect.Type; | |
import java.util.List; | |
import java.util.Set; | |
import javax.validation.ConstraintViolation; | |
import javax.validation.Valid; | |
import javax.validation.Validator; | |
import javax.ws.rs.Consumes; | |
import javax.ws.rs.Produces; | |
import javax.ws.rs.WebApplicationException; | |
import javax.ws.rs.core.MediaType; | |
import javax.ws.rs.core.MultivaluedMap; | |
import javax.ws.rs.core.Response; | |
import javax.ws.rs.core.Response.StatusType; | |
import javax.ws.rs.ext.MessageBodyReader; | |
import javax.ws.rs.ext.MessageBodyWriter; | |
import javax.ws.rs.ext.Provider; | |
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; | |
import com.google.common.annotations.VisibleForTesting; | |
import com.google.common.collect.ImmutableList; | |
import com.google.common.collect.Ordering; | |
import com.google.common.collect.Sets; | |
import com.google.inject.Inject; | |
/** | |
* A Jersey provider which adds validation to the basic Jackson Json provider. Any request | |
* entity method parameters annotated with {@code @Valid} are validated, and an informative | |
* {@code 422 Unprocessable Entity} response is returned should the entity be invalid. | |
* <br/> | |
* Thanks to Yammer's Dropwizard for the original idea. | |
* | |
* @author codyaray | |
* @since 5/23/12 | |
*/ | |
@Provider | |
@Consumes({ MediaType.APPLICATION_JSON, "text/json" }) | |
@Produces({ MediaType.APPLICATION_JSON, "text/json" }) | |
public class ValidatingJacksonJsonProvider | |
implements MessageBodyReader<Object>, MessageBodyWriter<Object> { | |
// Unfortunate that this isn't defined in Response.Status | |
@VisibleForTesting static final StatusType UNPROCESSABLE_ENTITY = new StatusType() { | |
@Override | |
public int getStatusCode() { | |
return 422; | |
} | |
@Override | |
public Response.Status.Family getFamily() { | |
return Response.Status.Family.CLIENT_ERROR; | |
} | |
@Override | |
public String getReasonPhrase() { | |
return "Unprocessable Entity"; | |
} | |
}; | |
private final JacksonJsonProvider delegate; | |
private final Validator validator; | |
@Inject | |
public ValidatingJacksonJsonProvider(JacksonJsonProvider delegate, Validator validator) { | |
this.delegate = delegate; | |
this.validator = validator; | |
} | |
@Override | |
public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, | |
MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) | |
throws IOException { | |
Object value = null; | |
try { | |
value = parseEntity(type, genericType, annotations, mediaType, httpHeaders, entityStream); | |
} catch (JsonProcessingException ex) { | |
throw new WebApplicationException(unprocessableEntity(ex.getMessage())); | |
} | |
if (hasValidAnnotation(annotations)) { | |
List<String> errors = validate(value); | |
if (!errors.isEmpty()) { | |
StringBuilder msg = new StringBuilder("The request entity had the following errors:\n"); | |
for (String error : errors) { | |
msg.append(" * ").append(error).append('\n'); | |
} | |
throw new WebApplicationException(unprocessableEntity(msg.toString())); | |
} | |
} | |
return value; | |
} | |
private Object parseEntity(Class<Object> type, Type genericType, Annotation[] annotations, | |
MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) | |
throws IOException { | |
return delegate.readFrom(type, genericType, annotations, mediaType, httpHeaders, entityStream); | |
} | |
@Override | |
public void writeTo(Object t, Class<?> type, Type genericType, Annotation[] annotations, | |
MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) | |
throws IOException { | |
delegate.writeTo(t, type, genericType, annotations, mediaType, httpHeaders, entityStream); | |
} | |
@Override | |
public boolean isWriteable(Class<?> type, Type genericType, | |
Annotation[] annotations, MediaType mediaType) { | |
return delegate.isWriteable(type, genericType, annotations, mediaType); | |
} | |
@Override | |
public long getSize(Object t, Class<?> type, Type genericType, | |
Annotation[] annotations, MediaType mediaType) { | |
return delegate.getSize(t, type, genericType, annotations, mediaType); | |
} | |
@Override | |
public boolean isReadable(Class<?> type, Type genericType, | |
Annotation[] annotations, MediaType mediaType) { | |
return delegate.isReadable(type, genericType, annotations, mediaType); | |
} | |
private List<String> validate(Object o) { | |
if (o == null) | |
throw new WebApplicationException(unprocessableEntity("No entity received")); | |
Set<String> errors = Sets.newHashSet(); | |
Set<ConstraintViolation<Object>> violations = validator.validate(o); | |
for (ConstraintViolation<Object> v : violations) { | |
errors.add(String.format("%s %s (was %s)", | |
v.getPropertyPath(), v.getMessage(), v.getInvalidValue())); | |
} | |
return ImmutableList.copyOf(Ordering.natural().sortedCopy(errors)); | |
} | |
@VisibleForTesting static boolean hasValidAnnotation(Annotation[] annotations) { | |
for (Annotation annotation : annotations) { | |
if (Valid.class.equals(annotation.annotationType())) { | |
return true; | |
} | |
} | |
return false; | |
} | |
private static Response unprocessableEntity(String msg) { | |
return Response | |
.status(UNPROCESSABLE_ENTITY) | |
.entity(msg) | |
.type(MediaType.TEXT_PLAIN_TYPE) | |
.build(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi am getting following error after adding this class
please check the stack trace and help me
A MultiException has 4 exceptions. They are:|1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=JacksonJsonProvider,parent=ValidatingJacksonJsonProvider,qualifiers={},position=0,optional=false,self=false,unqualified=null,13503984)|2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of com.koderzlab.lawman.validation.ValidatingJacksonJsonProvider errors were found|3. java.lang.IllegalStateException: Unable to perform operation: resolve on com.koderzlab.lawman.validation.ValidatingJacksonJsonProvider|4. java.lang.IllegalStateException: Unable to perform operation: create on org.glassfish.jersey.message.internal.MessageBodyFactory|
at org.jvnet.hk2.internal.Collector.throwIfErrors(Collector.java:88)
at org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:252)
at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:360)
at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:471)
at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:82)
at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:70)
at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture$1.call(Cache.java:97)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture.run(Cache.java:154)
at org.glassfish.hk2.utilities.cache.Cache.compute(Cache.java:199)
at org.jvnet.hk2.internal.SingletonContext.findOrCreate(SingletonContext.java:121)
at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2064)
at org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:105)
at org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:87)
at org.glassfish.jersey.internal.inject.ProviderToService.apply(ProviderToService.java:58)
at org.glassfish.jersey.internal.inject.ProviderToService.apply(ProviderToService.java:54)
at jersey.repackaged.com.google.common.collect.Iterators$8.transform(Iterators.java:860)
at jersey.repackaged.com.google.common.collect.TransformedIterator.next(TransformedIterator.java:48)
at java.util.AbstractCollection.addAll(AbstractCollection.java:333)
at java.util.LinkedHashSet.(LinkedHashSet.java:169)
at jersey.repackaged.com.google.common.collect.Sets.newLinkedHashSet(Sets.java:292)
at org.glassfish.jersey.internal.inject.Providers.getClasses(Providers.java:388)
at org.glassfish.jersey.internal.inject.Providers.getCustomProviders(Providers.java:201)
at org.glassfish.jersey.message.internal.MessageBodyFactory.(MessageBodyFactory.java:221)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at org.glassfish.hk2.utilities.reflection.ReflectionHelper.makeMe(ReflectionHelper.java:1129)
at org.jvnet.hk2.internal.ClazzCreator.createMe(ClazzCreator.java:274)
at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:368)
at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:471)
at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:82)
at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:70)
at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture$1.call(Cache.java:97)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture.run(Cache.java:154)
at org.glassfish.hk2.utilities.cache.Cache.compute(Cache.java:199)
at org.jvnet.hk2.internal.SingletonContext.findOrCreate(SingletonContext.java:121)
at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2064)
at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:711)
at org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:653)
at org.glassfish.jersey.server.model.ComponentModelValidator.(ComponentModelValidator.java:97)
at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:496)
at org.glassfish.jersey.server.ApplicationHandler.access$500(ApplicationHandler.java:166)
at org.glassfish.jersey.server.ApplicationHandler$3.run(ApplicationHandler.java:327)
at org.glassfish.jersey.internal.Errors$2.call(Errors.java:289)
at org.glassfish.jersey.internal.Errors$2.call(Errors.java:286)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.processWithException(Errors.java:286)
at org.glassfish.jersey.server.ApplicationHandler.(ApplicationHandler.java:324)
at org.glassfish.jersey.servlet.WebComponent.(WebComponent.java:336)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:170)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:358)
at javax.servlet.GenericServlet.init(GenericServlet.java:241)
at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:475)
at org.eclipse.jetty.servlet.ServletHolder.doStart(ServletHolder.java:291)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:730)
at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:254)
at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1240)
at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:689)
at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:482)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
at org.eclipse.jetty.deploy.ContextDeployer.deploy(ContextDeployer.java:359)
at org.eclipse.jetty.deploy.ContextDeployer.access$000(ContextDeployer.java:82)
at org.eclipse.jetty.deploy.ContextDeployer$ScannerListener.fileAdded(ContextDeployer.java:107)
at org.eclipse.jetty.util.Scanner.reportAddition(Scanner.java:615)
at org.eclipse.jetty.util.Scanner.reportDifferences(Scanner.java:540)
at org.eclipse.jetty.util.Scanner.scan(Scanner.java:403)
at org.eclipse.jetty.util.Scanner$1.run(Scanner.java:353)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
Caused by:
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=JacksonJsonProvider,parent=ValidatingJacksonJsonProvider,qualifiers={},position=0,optional=false,self=false,unqualified=null,13503984)
at org.jvnet.hk2.internal.ThreeThirtyResolver.resolve(ThreeThirtyResolver.java:74)
at org.jvnet.hk2.internal.ClazzCreator.resolve(ClazzCreator.java:214)
at org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:231)
at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:360)
at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:471)
at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:82)
at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:70)
at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture$1.call(Cache.java:97)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture.run(Cache.java:154)
at org.glassfish.hk2.utilities.cache.Cache.compute(Cache.java:199)
at org.jvnet.hk2.internal.SingletonContext.findOrCreate(SingletonContext.java:121)
at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2064)
at org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:105)
at org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:87)
at org.glassfish.jersey.internal.inject.ProviderToService.apply(ProviderToService.java:58)
at org.glassfish.jersey.internal.inject.ProviderToService.apply(ProviderToService.java:54)
at jersey.repackaged.com.google.common.collect.Iterators$8.transform(Iterators.java:860)
at jersey.repackaged.com.google.common.collect.TransformedIterator.next(TransformedIterator.java:48)
at java.util.AbstractCollection.addAll(AbstractCollection.java:333)
at java.util.LinkedHashSet.(LinkedHashSet.java:169)
at jersey.repackaged.com.google.common.collect.Sets.newLinkedHashSet(Sets.java:292)
at org.glassfish.jersey.internal.inject.Providers.getClasses(Providers.java:388)
at org.glassfish.jersey.internal.inject.Providers.getCustomProviders(Providers.java:201)
at org.glassfish.jersey.message.internal.MessageBodyFactory.(MessageBodyFactory.java:221)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at org.glassfish.hk2.utilities.reflection.ReflectionHelper.makeMe(ReflectionHelper.java:1129)
at org.jvnet.hk2.internal.ClazzCreator.createMe(ClazzCreator.java:274)
at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:368)
at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:471)
at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:82)
at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:70)
at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture$1.call(Cache.java:97)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture.run(Cache.java:154)
at org.glassfish.hk2.utilities.cache.Cache.compute(Cache.java:199)
at org.jvnet.hk2.internal.SingletonContext.findOrCreate(SingletonContext.java:121)
at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2064)
at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:711)
at org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:653)
at org.glassfish.jersey.server.model.ComponentModelValidator.(ComponentModelValidator.java:97)
at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:496)
at org.glassfish.jersey.server.ApplicationHandler.access$500(ApplicationHandler.java:166)
at org.glassfish.jersey.server.ApplicationHandler$3.run(ApplicationHandler.java:327)
at org.glassfish.jersey.internal.Errors$2.call(Errors.java:289)
at org.glassfish.jersey.internal.Errors$2.call(Errors.java:286)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.processWithException(Errors.java:286)
at org.glassfish.jersey.server.ApplicationHandler.(ApplicationHandler.java:324)
at org.glassfish.jersey.servlet.WebComponent.(WebComponent.java:336)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:170)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:358)
at javax.servlet.GenericServlet.init(GenericServlet.java:241)
at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:475)
at org.eclipse.jetty.servlet.ServletHolder.doStart(ServletHolder.java:291)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:730)
at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:254)
at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1240)
at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:689)
at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:482)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64)
at org.eclipse.jetty.deploy.ContextDeployer.deploy(ContextDeployer.java:359)
at org.eclipse.jetty.deploy.ContextDeployer.access$000(ContextDeployer.java:82)
at org.eclipse.jetty.deploy.ContextDeployer$ScannerListener.fileAdded(ContextDeployer.java:107)
at org.eclipse.jetty.util.Scanner.reportAddition(Scanner.java:615)
at org.eclipse.jetty.util.Scanner.reportDifferences(Scanner.java:540)
at org.eclipse.jetty.util.Scanner.scan(Scanner.java:403)
at org.eclipse.jetty.util.Scanner$1.run(Scanner.java:353)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)