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" ?