Weld injects a proxy instead of real instance - why?
dermoritz Feb 5, 2016 10:19 AMIn my application i have "@RequestScoped" converter classes that convert jpa entities to jaxb classes (dto serialized to json) and vice versa. All of those classes inject Provider<JaxbClass>. I need to use the provider because those Jaxb-classes extend a class that itself injects some stuff. This all works fine: the provider produces real instances. The class hierarchy looks like that:
interface Identifiable (getId) -> abstract class Linkable (injects some stuff) -> jaxb-class (annotated with xmlroot)
Some classes also extend an additional abstract class (createBy) that provides an additional field, also here no problem.
The problem begins if i create an Jaxb-classes from an generic abstract class (don't know if this is related to problem). The hierarchy is:
[hierarchy as before]->abstract class<T>->jaxb-class
if i try to get an instance via a provider of those classes the instance is a weld proxy. This proxy has additional fields and the json (un)marshaller moans about unknown field (handler), it can't handle it. My question is why in the latter case i get an proxy?
Here is a working example:
Converter
@RequestScoped
public class VendorRepresentationConverter extends RepresentationConverter.Base<VendorRepresentation,Vendor> {
@Inject
@CurrentUser
private User user;
@Inject
private Provider<VendorRepresentation> vrProv;
@Inject
private UserRepresentationConverter userReprsentationConverter;
@Override
protected Vendor createNew(VendorRepresentation representation) {
return new Vendor(representation.getName(), representation.getHomePage(), user);
}
@Override
public VendorRepresentation from(Vendor vendor) {
VendorRepresentation vendorRepresentation = vrProv.get(); //returns real instance
vendorRepresentation.setName(vendor.getName());
vendorRepresentation.setHomePage(vendor.getHomePage());
vendorRepresentation.setCreatedBy(userReprsentationConverter.from(vendor.getCreatedBy()));
vendorRepresentation.setId(vendor.getId());
return vendorRepresentation;
}
@Override
public Vendor update(VendorRepresentation representation, Vendor target) {
target.setName(representation.getName());
target.setHomePage(representation.getHomePage());
return target;
}
}
jaxb class:
@XmlRootElement(name = "vendor", namespace = "urn:problems:vendor")
public class VendorRepresentation extends CreatedByUserRepresentation{
@NotNull
private String name;
@NotNull
private String homePage;
@Override
protected Class<?> getResourceClass() {
return VendorResource.class;
}
public String getName() {
return name;
}
public void setName(String name) {
if(Strings.isNullOrEmpty(name)){
throw new IllegalArgumentException("Name must neither null nor empty.");
}
this.name = name;
}
public String getHomePage() {
return homePage;
}
public void setHomePage(String homePage) {
if(Strings.isNullOrEmpty(homePage)){
throw new IllegalArgumentException("Home page must neither null nor empty.");
}
this.homePage = homePage;
}
now the non working example
converter
@RequestScoped
public class ProblemVoteRepresentationConverter extends VoteRepresentationConverter<ProblemVoteRepresentation, ProblemVote> {
@Inject
private ProblemRepresentationConverter problemConverter;
@Inject
private Provider<ProblemVoteRepresentation> problemVoteRepresentationProvider;
@Override
protected ProblemVote createNew( ProblemVoteRepresentation representation ) {
return new ProblemVote( problemConverter.to( representation.getVoteOf() ), representation.getValue()==1, user );
}
@Override
public ProblemVoteRepresentation from( ProblemVote problemVote ) {
ProblemVoteRepresentation problemVoteRepresentation = problemVoteRepresentationProvider.get(); //proxy is provided!!!!!!!!!!!!!!!
problemVoteRepresentation.setVoteOf(problemConverter.from(problemVote.getEntity()));
problemVoteRepresentation.setValue(problemVote.getValue());
problemVoteRepresentation.setCreatedBy(userConverter.from( problemVote.getCreatedBy()));
problemVoteRepresentation.setId( problemVote.getId());
return problemVoteRepresentation;
}
}
based on
@RequestScoped
public abstract class VoteRepresentationConverter<REST extends Identifiable, SOURCE> extends RepresentationConverter.Base<REST, SOURCE>{
@Inject
@CurrentUser
protected User user;
@Inject
protected UserRepresentationConverter userConverter;
@Override
public SOURCE update(REST representation, SOURCE target) {
throw new UnsupportedOperationException("Votes can't be updated.");
}
}
jaxb:
@XmlRootElement(name = "problemvote", namespace = "urn:problems:problemvote")
public class ProblemVoteRepresentation extends VoteRepresentation<ProblemRepresentation> {
@Override
protected Class<?> getResourceClass() {
return ProblemVoteResource.class;
}
}
based on:
public abstract class VoteRepresentation<T extends CreatedByUserRepresentation> extends CreatedByUserRepresentation{
@NotNull
private T voteOf;
@Min(-1) // down vote
@Max(1) // up vote
private int value;
@AssertTrue
public boolean valueIsNotZero() {
return value != 0;
}
public T getVoteOf() {
return voteOf;
}
public int getValue() {
return value;
}
public void setVoteOf(T voteOf) {
this.voteOf = voteOf;
}
public void setValue(int value) {
this.value = value;
}
}
now the hierarchy continues like in the working example. So what could possibly cause weld to provide a proxy instead of real instance of "ProblemVoteRepresentation" ?