VRaptor 3 - NoSuchBeanDefinitionException: No unique bean of type

Tenho um projeto java com epenas dois arquivos, uma interface e uma classe.
Essa interface extende a interface br.com.caelum.vraptor.View para tratar alguns casos específicos na serialização de objetos JSON.

ExtJSJson.java

import br.com.caelum.vraptor.View;

public interface ExtJSJson extends View {
	
	public ExtJSJsonImpl from(Object object);
	
	public ExtJSJsonImpl success();
	
	public ExtJSJsonImpl success(boolean success);
	
	public ExtJSJsonImpl selected(Object value);
	
	public ExtJSJsonImpl exclude(String... names);
	
	public ExtJSJsonImpl include(String... fields);
	
	public ExtJSJsonImpl upload(String fileName);
	
	public ExtJSJsonImpl serialize();
	
}

E a implantação dela na classe ExtJSJsonImpl.java

@Component
public class ExtJSJsonImpl implements ExtJSJson {
private final Multimap<Class<?>, String> excludes = LinkedListMultimap.create();
	private final XStream xstream;
	private final HttpServletResponse response;
	private final String SUCCESS  = "{\"success\": ";
	private final String SELECTED = ",\n \"selected\": @value }";
	
	private Set<Class<?>> elementTypes;
	private Class<?> rootClass;
	
	private Object object;
	private String json;
	private boolean convertToJson = true;
	
	private boolean includeSuccess = false;
	private boolean successValue   = true;
	
	private boolean includeSelected = false;
	private Object  selectedValue;
	
	
	public ExtJSJsonImpl(HttpServletResponse response) {
		this.xstream  = new XStream(new JsonHierarchicalStreamDriver());
		this.response = response;
	}
	
	public ExtJSJsonImpl from(Object object) {
		response.setContentType("application/json; charset=ISO-8859-1");
		this.rootClass = object.getClass();
		this.object    = object;
		return this;
	}
	
	public ExtJSJsonImpl success() {
		return success(true);
	}
	
	public ExtJSJsonImpl success(boolean success) {
		includeSuccess = true;
		successValue   = success;
		return this;
	}
	
	public ExtJSJsonImpl selected(Object value) {
		if(value != null) {
			includeSelected = true;
			selectedValue = value;
		}
		return this;
	}
	
	public ExtJSJsonImpl exclude(String... names) {
		for (String name : names) {
			Set<Class<?>> parentTypes = getParentTypesFor(name);
			for (Class<?> type : parentTypes) {
				xstream.omitField(type, getNameFor(name));
			}
		}
		return this;
	}
	
	public ExtJSJsonImpl include(String... fields) {
		for (String field : fields) {
			try {
				Set<Class<?>> parentTypes = getParentTypesFor(field);
				String fieldName = getNameFor(field);
				for (Class<?> parentType : parentTypes) {
					Type genericType = new Mirror().on(parentType).reflect().field(fieldName).getGenericType();
					Class<?> fieldType = getActualType(genericType);

					if (!excludes.containsKey(fieldType)) {
						excludeNonPrimitiveFields(fieldType);
					}
					excludes.remove(parentType, fieldName);
				}
			} catch (NullPointerException e) {
				throw new IllegalArgumentException("Field path " + field + " doesn't exist");
			}
		}
		return this;
	}
	
	public ExtJSJsonImpl upload(String fileName) {
		response.setContentType("text/html");
		convertToJson = false;
		fileName = fileName != null ? fileName : "undefined";
		json = "{success:" + successValue + ", file:\"" + fileName + "\"}";
		return this;
	}
	
	public ExtJSJsonImpl serialize() {
		if(convertToJson) 
			this.json = objectToJSON();
		
		if(includeSelected) 
			includeSelected();
			
		if(includeSuccess)
			includeSuccess();
		
		try {
			response.getWriter().write(json);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return this;
	}
	
	private void excludeNonPrimitiveFields(Class<?> type) {
		for (Field field : new Mirror().on(type).reflectAll().fields()) {
			if (!isPrimitive(field.getType())) {
				excludes.put(type, field.getName());
			}
		}
	}

	private String objectToJSON() {
		xstream.setMode(XStream.NO_REFERENCES);
        xstream.alias("data", object.getClass());

        for(Class clazz : object.getClass().getInterfaces()) {
        	xstream.alias("data", clazz);
        }
        
        String json = xstream.toXML(object).trim();
        if(json.endsWith("}}")) {
        	json = json.substring(0, json.length() - 2) + " }\n}";
        }
        return json;
	}
	
	private String getNameFor(String name) {
		String[] path = name.split("\\.");
		return path[path.length-1];
	}
	
	private Set<Class<?>> getParentTypesFor(String name) {
		if (elementTypes == null) {
			Class<?> type = rootClass;
			return Collections.<Class<?>>singleton(getParentType(name, type));
		} else {
			Set<Class<?>> result = new HashSet<Class<?>>();
			for (Class<?> type : elementTypes) {
				result.add(getParentType(name, type));
			}
			return result;
		}
	}
	
	private Class<?> getParentType(String name, Class<?> type) {
		String[] path = name.split("\\.");
		for (int i = 0; i < path.length - 1; i++) {
			type = getActualType(new Mirror().on(type).reflect().field(path[i]).getGenericType());
		}
		return type;
	}
	
	private Class<?> getActualType(Type genericType) {
		if (genericType instanceof ParameterizedType) {
			ParameterizedType type = (ParameterizedType) genericType;
			if (isCollection(type)) {
				return (Class<?>) type.getActualTypeArguments()[0];
			}
		}
		return (Class<?>) genericType;
	}
	
	private boolean isCollection(Type type) {
		if (type instanceof ParameterizedType) {
			ParameterizedType ptype = (ParameterizedType) type;
			return Collection.class.isAssignableFrom((Class<?>) ptype.getRawType())
			  || Map.class.isAssignableFrom((Class<?>) ptype.getRawType());
		}
		return Collection.class.isAssignableFrom((Class<?>) type);
	}
	
	private void includeSuccess() {
		if(json != null && json.length() > 0 && json.startsWith("{") && json.endsWith("}")) {
			this.json = SUCCESS + successValue + ", \n " + this.json.substring(1); 
		}
	}
	
	private void includeSelected() {
		if(json != null && json.length() > 0 && json.startsWith("{") && json.endsWith("}")) {
			String v = null;
			if(isNumeric(selectedValue.getClass())) {
				v = selectedValue.toString();
			} else {
				v = "\"" + selectedValue.toString() + "\"";
			}
			this.json = this.json.substring(0, json.length() - 1) + SELECTED.replace("@value", v); 
		}
	}
	
	private boolean isPrimitive(Class<?> type) {
		return type.isPrimitive()
			|| type.isEnum()
			|| Number.class.isAssignableFrom(type)
			|| type.equals(String.class)
			|| Date.class.isAssignableFrom(type)
			|| Calendar.class.isAssignableFrom(type)
			|| Boolean.class.equals(type)
			|| Character.class.equals(type);
	}
	
	private boolean isNumeric(Class clazz) {
		return Integer.class.equals(clazz) 
			|| Double.class.equals(clazz) 
			|| Long.class.equals(clazz)
			|| Number.class.equals(clazz);
	}
}

Quando eu deixo as classes diretamente no projeto WEB, o sistema roda tranquilamente.
Contudo, se eu compilo um JAR com as duas classes e adiciono o mesmo na lib do projeto, quando aciono esse classe recebo o seguinte erro:

24/06/2010 16:25:41 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet default threw exception
br.com.caelum.vraptor.InterceptionException: an exception was raised while executing resource method
	at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:86)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:77)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:42)
	at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:47)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.k2studio.vraptor.interceptor.LoginInterceptor.intercept(LoginInterceptor.java:37)
	at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:47)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:46)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:81)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:70)
	at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:92)
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:56)
	at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:89)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
	at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [br.com.k2studio.vraptor.extjs.ExtJSJson] is defined: no bean for this type registered
	at br.com.caelum.vraptor.ioc.spring.VRaptorApplicationContext.getBean(VRaptorApplicationContext.java:255)
	at br.com.caelum.vraptor.ioc.spring.SpringBasedContainer.instanceFor(SpringBasedContainer.java:59)
	at br.com.caelum.vraptor.core.DefaultResult.use(DefaultResult.java:48)
	at br.com.k2studio.vraptor.controller.ExtjsController.combobox(ExtjsController.java:74)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:57)
	... 40 more
24/06/2010 16:25:41 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet default threw exception
br.com.caelum.vraptor.InterceptionException: an exception was raised while executing resource method
	at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:86)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:77)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:42)
	at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:47)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.k2studio.vraptor.interceptor.LoginInterceptor.intercept(LoginInterceptor.java:37)
	at br.com.caelum.vraptor.core.InstantiatedInterceptorHandler.execute(InstantiatedInterceptorHandler.java:47)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:46)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:81)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56)
	at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:65)
	at br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:70)
	at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:92)
	at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:56)
	at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:89)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
	at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [br.com.k2studio.vraptor.extjs.ExtJSJson] is defined: no bean for this type registered
	at br.com.caelum.vraptor.ioc.spring.VRaptorApplicationContext.getBean(VRaptorApplicationContext.java:255)
	at br.com.caelum.vraptor.ioc.spring.SpringBasedContainer.instanceFor(SpringBasedContainer.java:59)
	at br.com.caelum.vraptor.core.DefaultResult.use(DefaultResult.java:48)
	at br.com.k2studio.vraptor.controller.ExtjsController.grid(ExtjsController.java:36)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:57)
	... 40 more

Alguém sabe como posso resolver isso?

[]´s
Daniel

se você usar componentes do vraptor dentro de um jar você precisa especificar no seu web.xml o endereço desses pacotes.

<context-param> <param-name>br.com.caelum.vraptor.packages</param-name> <param-value>com.acme.blahhhh</param-value> </context-param>

Opa, fiz isso mas não deu certo.

Mais alguma dica?

[]´s

Daniel

Você especificou o package br.com.k2studio.vraptor.extjs?

Sim, e até mudei o pacote no outro projeto para tirar qualquer semelhança com o projeto web.

vc gerou o jar com entradas de diretório?

no eclipse, vc tem que marcar um checkbox chamado “include directory entries” ou algo do tipo…