2017-09-08 1 views
3

Utilisation de Spring boot 1.5.6.RELEASE.MappingException: mappage de champ ambigu détecté

je la classe de base de documents mongo suivant:

@Document(collection="validation_commercial") 
public abstract class Tier { 
    @Id 
    private String id; 
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) 
    private Date created; 
    @Field("tran") 
    private Tran tran; 

    public Tier() { 
    } 

    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 

    public Date getCreated() { 
     return created; 
    } 

    public void setCreated(Date created) { 
     this.created = created; 
    } 

    public Tran getTran() { 
     return tran; 
    } 

    public void setTran(Tran tran) { 
     this.tran = tran; 
    } 
} 

qui est ensuite étendu:

public class Tier1 extends Tier { 

    @Field("tier1") 
    private Tier1Programs tier1; 

    public Tier1() { 
     this.tier1 = new Tier1Programs(); 
    } 

    public Tier1Programs getTier1() { 
     return tier1; 
    } 

    public void setTier1(Tier1Programs tier1) { 
     this.tier1 = tier1; 
    } 
} 

qui à son tour est prolongée:

public class Tier2 extends Tier1 { 

    @Field("tier2") 
    private Tier2Programs tier2; 

    public Tier2() { 
     this.tier2 = new Tier2Programs(); 
    } 

    public Tier2Programs getTier2() { 
     return tier2; 
    } 

    public void setTier2(Tier2Programs tier2) { 
     this.tier2 = tier2; 
    } 
} 

Il y a un superviseur Tier1 (Spring Boot Application) qui utilise la classe Tier1 dans l'interface MongoRepository:

public interface Tier1Repository extends MongoRepository<Tier1,String>{} 

pour la récupération et l'enregistrement - aucun problème.

J'ai alors un superviseur Tier2 (application Boot Spring) qui utilise un référentiel Tier1 (pour récupérer le document Tier1 et un dépôt Tier2 pour l'enregistrement du document Tier2:

@Repository("tier1Repository") 
public interface Tier1Repository extends MongoRepository<Tier1,String>{} 

@Repository("tier2Repository") 
public interface Tier2Repository extends MongoRepository<Tier2,String>{} 

Mon service est:

@Service 
public class TierService { 
    @Qualifier("tier1Repository") 
    @Autowired 
    private final Tier1Repository tier1Repository; 
    @Qualifier("tier2Repository") 
    @Autowired 
    private final Tier2Repository tier2Repository; 

    public TierService(@Qualifier("tier1Repository") Tier1Repository tier1Repository, @Qualifier("tier2Repository") Tier2Repository tier2Repository) { 
     this.tier1Repository = tier1Repository; 
     this.tier2Repository = tier2Repository; 
    } 

    public Tier1 findOne(String id) { 
     return tier1Repository.findOne(id); 
    } 

    public void SaveTier(Tier2 tier) { 
     tier2Repository.save(tier); 
    } 

    public Tier1Repository getTier1Repository() { 
     return tier1Repository; 
    } 

    public Tier2Repository getTier2Repository() { 
     return tier2Repository; 
    } 
} 

et enfin l'application:

@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, 
    DataSourceTransactionManagerAutoConfiguration.class, JdbcTemplateAutoConfiguration.class}) 
@Configuration 
@ComponentScan(basePackages = {"com.k12commercial.tier2supervisor"}) 
@ImportResource("classpath:application-context.xml") 
public class Application implements CommandLineRunner { 

    @Autowired 
    private IReceiver raBidNetPriceReceiver; 

    @Autowired 
    private UdyDataSourceFactory udyDSRegistry; 

    public static void main(String[] args) throws InterruptedException { 
     try { 
      SpringApplication.run(Application.class, args); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    }  

    @Override 
    public void run(String... args) throws Exception { 
     raBidNetPriceReceiver.processTierMessages(); 
     exit(0); 
    } 
} 

Quand je lance la cravate Superviseur de la r2 ligne de commande, je reçois l'erreur suivante:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'tierService' defined in URL [jar:file:/opt/java-commandline/tier2supervisor-1.0.jar!/BOOT-INF/classes!/com/k12commercial/tier2supervisor/service/TierService.class]: Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tier2Repository': Invocation of init method failed; nested exception is org.springframework.data.mapping.model.MappingException: Ambiguous field mapping detected! Both private final java.lang.reflect.Type org.springframework.data.util.TypeDiscoverer.type and private final java.lang.Class org.springframework.data.util.ClassTypeInformation.type map to the same field name type! Disambiguate using @Field annotation!

Je ne suis pas sûr si la question est Tier2 extension Tier1 (n'essayez de mettre tag @Document ci-dessus Tier1 et Tier2 sans changement). Je pense avoir marqué les champs pertinents, donc je ne comprends pas le besoin de désambiguïser. Je pensais que le problème était d'avoir 2 dépôts (Spring Boot ne sachant pas lequel à DI) ainsi enlevé le Tier1Repository - n'a pas fonctionné. Essayé de mieux qualifier les dépôts, mais toujours eu la même erreur. J'ai fait Tier1 et Tier2 @ Transient et cela s'est débarrassé du message mais a également enlevé la section tier1 dans le document de mongo - correction tellement fausse.

Pensant qu'il est une solution d'annotation, mais ne pas le voir ...

S'il vous plaît conseiller - merci.

+0

Cant reproduire le problème avec le code affiché.Pouvez-vous s'il vous plaît créer un [mvce] (https://stackoverflow.com/help/mcve) et aussi inclure la trace complète de la pile? – Veeram

+0

Dans TierService, vous initialisez deux fois Tier1Repository et Tier2Repository. 1) Instanciation via autowiring d'une variable membre. 2) Instanciation via les déclarer dans le constructeur. Peut-être que vous devriez supprimer cela aussi si vous utilisez SpringBoot puis exécutez-le en activant le mode --debug et s'il vous plaît imprimer le stacktrace –

Répondre

0

Désolé pour le retard (je me suis attelé pour travailler sur autre chose) et merci à ceux qui ont répondu. Le problème était que j'avais un MongoTemplate dans mes programmes de niveau Tier, par exemple Tier2Programs (sous-bibliothèque) que Spring Boot essayait d'autowire. En déplaçant les exigences Mongo (CRUD) au niveau superviseur (j'ai également remplacé les référentiels par un MongoTemplate pour simplifier), j'ai levé l'ambiguïté. (J'ai également supprimé la classe Service).

Le code est contenu avec la classe RaBidNetReciever

@Component 
public class RaBidNetPriceReceiver extends BaseReceiver implements IReceiver, ApplicationEventPublisherAware { 
    private static final Logger LOGGER = LoggerFactory.getLogger(RaBidNetPriceReceiver.class); 
    private final RabbitTemplate raBidNetPriceRabbitTemplate; 

    public RaBidNetPriceReceiver(MongoTemplate mongoTemplate, RabbitTemplate raBidNetPriceRabbitTemplate) { 
    super(mongoTemplate); 
    this.raBidNetPriceRabbitTemplate = raBidNetPriceRabbitTemplate; 
    } 

    @Transactional 
    public void processTierMessages() { 
    try { 
     while (true) { 
      gson = getGsonBuilder().create(); 
      byte[] body = (byte[]) raBidNetPriceRabbitTemplate.receiveAndConvert(); 
      if (body == null) { 
       setFinished(true); 
       break; 
      } 
      tier1Message = gson.fromJson(new String(body), Tier1Message.class); 
      // document a 'Tier1' type so retrieve Tier1 first... 
      Tier1 tier1 = mongoTemplate.findById(tier1Message.getId(), Tier1.class); 

      Tier2Message tier2Message = new Tier2Message(tier1Message.getTran(), tier1Message.getId()); 
      Tier2Process tierProcess = getTierProcess(tier2Message.getTran().getK12ArchitectureId()); 

      Tier2 tier2 = new Tier2(); 
      tier2.setId(tier1.getId()); 
      tier2.setTier1Programs(tier1.getTier1Programs()); 
      tier2.setCreated(tier1.getCreated()); 
      tier2.setTran(tier1.getTran()); 

      tierProcess.setTier(tier2); 
      tier2 = tier2.getTier2Programs().getRaBidNetPriceProgram().process(tierProcess); 
      mongoTemplate.save(tier2); 

      if (tier2.getTier2Programs().getRaBidNetPriceProgram().isFinished()) { 
       // publish event 
       publisher.publishEvent(new ProgramEvent(this, "FINISHED", tier2Message)); 
      } 
     } 

    } catch (Exception e) { 
     LOGGER.error("id: " + tier1Message.getId() + " " + e.getMessage()); 
    } 
    } 

    @Override 
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { 
    this.publisher = applicationEventPublisher; 
    } 
} 

Merci,