Skip to content

Instantly share code, notes, and snippets.

@wpivotto
Created January 31, 2012 11:53
Show Gist options
  • Save wpivotto/1710097 to your computer and use it in GitHub Desktop.
Save wpivotto/1710097 to your computer and use it in GitHub Desktop.
Vraptor - Loader dinamico
package app.infra;
import java.io.Serializable;
import org.hibernate.Session;
import br.com.caelum.vraptor.ioc.Component;
@Component
public class DefaultLoader implements Loader<Object> {
private final Session session;
public DefaultLoader(Session session) {
this.session = session;
}
public Object load(Class<?> type, Serializable id) {
return session.get(type, id);
}
}
package app.infra;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface LoadedBy {
Class<? extends Loader<?>> value();
}
package app.infra;
import java.io.Serializable;
public interface Loader<T> {
T load(Class<?> type, Serializable id);
}
package app.infra;
import java.io.Serializable;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import br.com.caelum.vraptor.ioc.Component;
@Component
@SuppressWarnings({ "rawtypes", "unchecked" })
public class Loaders {
private final List<Loader> loaders;
private final Logger log = LoggerFactory.getLogger(getClass());
public Loaders(List<Loader> loaders) {
this.loaders = loaders;
}
public Object load(Class type, Serializable id) {
return loaderFor(type).load(type, id);
}
private Loader loaderFor(Class type) {
Class<?> expected = expectedLoader(type);
for (Loader loader : loaders) {
if (match(loader, expected)) {
log.debug("Loading entity " + type.getSimpleName() + " using " + loader.getClass().getSimpleName());
return loader;
}
}
throw new IllegalStateException("Entity " + type.getSimpleName() + " must have a loader");
}
private Class expectedLoader(Class type) {
if (type.isAnnotationPresent(LoadedBy.class))
return ((LoadedBy) type.getAnnotation(LoadedBy.class)).value();
else
return DefaultLoader.class;
}
private boolean match(Loader candidate, Class<?> expected) {
return candidate.getClass().equals(expected);
}
}
/***
* Copyright (c) 2009 Caelum - www.caelum.com.br/opensource All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package app.infra;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Predicates.instanceOf;
import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Iterables.isEmpty;
import static java.util.Arrays.asList;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import javax.servlet.http.HttpServletRequest;
import net.vidageek.mirror.dsl.Mirror;
import br.com.caelum.vraptor.Converter;
import br.com.caelum.vraptor.InterceptionException;
import br.com.caelum.vraptor.Intercepts;
import br.com.caelum.vraptor.Lazy;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.core.Converters;
import br.com.caelum.vraptor.core.InterceptorStack;
import br.com.caelum.vraptor.core.Localization;
import br.com.caelum.vraptor.http.ParameterNameProvider;
import br.com.caelum.vraptor.interceptor.Interceptor;
import br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor;
import br.com.caelum.vraptor.resource.ResourceMethod;
import br.com.caelum.vraptor.util.hibernate.extra.Load;
import br.com.caelum.vraptor.view.FlashScope;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
/**
* Interceptor that loads given entity from the database.
*
* @author Lucas Cavalcanti
* @author Cecilia Fernandes
* @since 3.3.2
*
*/
@Intercepts(before = ParametersInstantiatorInterceptor.class)
@Lazy
public class ParameterLoaderInterceptor implements Interceptor {
private final HttpServletRequest request;
private final ParameterNameProvider provider;
private final Result result;
private final Converters converters;
private final Localization localization;
private final FlashScope flash;
private final Loaders loaders;
public ParameterLoaderInterceptor(HttpServletRequest request,
ParameterNameProvider provider, Result result,
Converters converters, Localization localization, FlashScope flash,
Loaders loaders) {
this.request = request;
this.provider = provider;
this.result = result;
this.converters = converters;
this.localization = localization;
this.flash = flash;
this.loaders = loaders;
}
public boolean accepts(ResourceMethod method) {
return any(asList(method.getMethod().getParameterAnnotations()),
hasLoadAnnotation());
}
public void intercept(InterceptorStack stack, ResourceMethod method,
Object resourceInstance) throws InterceptionException {
Annotation[][] annotations = method.getMethod()
.getParameterAnnotations();
String[] names = provider.parameterNamesFor(method.getMethod());
Class<?>[] types = method.getMethod().getParameterTypes();
Object[] args = flash.consumeParameters(method);
for (int i = 0; i < names.length; i++) {
Iterable<Load> loads = Iterables.filter(asList(annotations[i]),
Load.class);
if (!isEmpty(loads)) {
Object loaded = load(names[i], types[i]);
if (loaded == null) {
result.notFound();
return;
}
if (args != null)
args[i] = loaded;
else
request.setAttribute(names[i], loaded);
}
}
flash.includeParameters(method, args);
stack.next(method, resourceInstance);
}
private Object load(String name, Class type) {
String parameter = request.getParameter(name + ".id");
if (parameter == null) {
return null;
}
Field field = new Mirror().on(type).reflect().field("id");
checkArgument(field != null, "Entity " + type.getSimpleName()
+ " must have an id property for @Load.");
Class<?> idType = field.getType();
Converter<?> converter = converters.to(idType);
checkArgument(converter != null, "Entity " + type.getSimpleName()
+ " id type " + idType + " must have a converter");
Serializable id = (Serializable) converter.convert(parameter, type,
localization.getBundle());
return loaders.load(type, id);
}
private Predicate<Annotation[]> hasLoadAnnotation() {
return new Predicate<Annotation[]>() {
public boolean apply(Annotation[] param) {
return any(asList(param), instanceOf(Load.class));
}
};
}
}
package app.models;
import app.infra.LoadedBy;
import app.repositories.ProductLoader;
@javax.persistence.Entity
@LoadedBy(ProductLoader.class)
public class Product extends Entity {
private String name;
private Double price;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setPrice(Double price) {
this.price = price;
}
public Double getPrice() {
return price;
}
}
package app.controllers;
import java.util.List;
import app.models.Product;
import app.repositories.ProductRepository;
import br.com.caelum.vraptor.Delete;
import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Post;
import br.com.caelum.vraptor.Put;
import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.Validator;
import br.com.caelum.vraptor.util.hibernate.extra.Load;
@Resource
public class ProductController {
private final Result result;
private final ProductRepository repository;
private final Validator validator;
ProductController(Result result, ProductRepository repository, Validator validator) {
this.result = result;
this.repository = repository;
this.validator = validator;
}
@Get("/products")
public List<Product> index() {
return repository.findAll();
}
@Post("/products")
public void create(Product product) {
validator.validate(product);
validator.onErrorUsePageOf(this).newProduct();
repository.create(product);
result.redirectTo(this).index();
}
@Get("/products/new")
public Product newProduct() {
return new Product();
}
@Put("/products")
public void update(Product product) {
validator.validate(product);
validator.onErrorUsePageOf(this).edit(product);
repository.update(product);
result.redirectTo(this).index();
}
@Get("/products/{product.id}/edit")
public Product edit(@Load Product product) {
return product;
}
@Get("/products/{product.id}")
public Product show(@Load Product product) {
return product;
}
@Delete("/products/{product.id}")
public void destroy(@Load Product product) {
repository.destroy(product);
result.redirectTo(this).index();
}
}
package app.repositories;
import java.io.Serializable;
import org.hibernate.Session;
import app.infra.Loader;
import app.models.Product;
import br.com.caelum.vraptor.ioc.Component;
@Component
public class ProductLoader implements Loader<Product> {
private final Session session;
ProductLoader(Session session) {
this.session = session;
}
public Product load(Class<?> type, Serializable id) {
return (Product) session.get(type, id);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment