Ich versuche, eine Spring-Data-Rest-App mit Spring Boot 1.5.9.RELEASE einrichten. Ich habe ein ConstraintValidator
wie diese ein:@Autowired Repository in ConstraintValidator null, wenn von CommandLineRunner verwendet
UniqueEmail.java
:
import javax.validation.Constraint;
import javax.validation.Payload;
import javax.validation.ReportAsSingleViolation;
import javax.validation.constraints.NotNull;
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {UniqueEmailValidator.class})
@NotNull
@ReportAsSingleViolation
public @interface UniqueEmail {
Class<?>[] groups() default {};
String message() default "{eu.icarus.momca.backend.domain.validation.UniqueEmail.message}";
Class<? extends Payload>[] payload() default {};
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
static @interface List {
UniqueEmail[] value();
}
}
UniqueEmailValidator.java
:
import eu.icarus.momca.backend.domain.repository.AccountRepository;
import org.springframework.beans.factory.annotation.Autowired;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class UniqueEmailValidator implements ConstraintValidator<UniqueEmail, String> {
@Autowired
private AccountRepository accountRepository;
@Override
public void initialize(UniqueEmail annotation) {
}
@Override
public boolean isValid(String email, ConstraintValidatorContext context) {
return accountRepository.findByEmail(email) == null;
}
}
Ich habe auch Listener für die beforeCreate
und beforeSave
Repository Methoden ein:
RestConfiguration.java
:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.rest.core.event.ValidatingRepositoryEventListener;
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
@Configuration
public class RestConfiguration extends RepositoryRestConfigurerAdapter {
@Override
public void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
validatingListener.addValidator("beforeCreate", localValidatorFactoryBean());
validatingListener.addValidator("beforeSave", localValidatorFactoryBean());
}
@Bean
@Primary
LocalValidatorFactoryBean localValidatorFactoryBean() {
return new LocalValidatorFactoryBean();
}
}
Mein Problem:
Der Validator scheint zu funktionieren, wenn die Repository-Methoden durch REST-Endpunkte genannt werden, jedoch über ein CommandLineRunner
ein paar Sachen in der angeschlossenen Datenbank einzurichten Ich versuche auch, die gleich verwendet Repository. Wenn die Aufrufe an das Repository validiert werden, ist der Autowired AccountRepository
im ConstraintValidator
null
, auch wenn es nicht gleichzeitig im CommandLineRunner null ist, das auch dasselbe Repository autowired hat. Ich verstehe das nicht.
Hat jemand eine Idee, warum das Repository null ist, wenn die Validierung vom CommandLineRunner ausgelöst wird?
Jede Hilfe wird sehr geschätzt. Daniel
Edit: hat die CommandLineRunner-Code
InitAdminData.java
:
import eu.icarus.momca.backend.domain.entity.Account;
import eu.icarus.momca.backend.domain.entity.AccountDetails;
import eu.icarus.momca.backend.domain.entity.AccountProfile;
import eu.icarus.momca.backend.domain.entity.Client;
import eu.icarus.momca.backend.domain.enumeration.AccountRoles;
import eu.icarus.momca.backend.domain.enumeration.ClientRoles;
import eu.icarus.momca.backend.domain.enumeration.GrantTypes;
import eu.icarus.momca.backend.domain.repository.AccountRepository;
import eu.icarus.momca.backend.domain.repository.ClientRepository;
import eu.icarus.momca.backend.domain.service.AccountService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
@Component
public class InitAdminData implements CommandLineRunner {
private static final Collection<AccountRoles> DEFAULT_ACCOUNT_ROLES = Arrays.asList(AccountRoles.ROLE_ACCOUNT, AccountRoles.ROLE_ADMINISTRATOR, AccountRoles.ROLE_CLIENT_OWNER);
private static final Logger logger = LoggerFactory.getLogger(InitAdminData.class);
private AccountRepository accountRepository;
private AccountService accountService;
@Value("${app.admin-email}")
private String adminEmail;
@Value("${app.admin-name}")
private String adminName;
@Value("${app.admin-password}")
private String adminPassword;
private ClientRepository clientRepository;
@Value("${app.default-client-description}")
private String defaultClientDescription;
@Autowired
public InitAdminData(AccountRepository accountRepository, AccountService accountService, ClientRepository clientRepository) {
this.accountRepository = accountRepository;
this.clientRepository = clientRepository;
this.accountService = accountService;
}
private Account initAdminAccount() {
Account adminAccount = accountRepository.findByAccountProfile_Name(adminName);
if (adminAccount == null) {
adminAccount = new Account();
logger.info("Initialized new admin account");
} else {
logger.info("Refreshed admin account");
}
setAdminAccountData(adminAccount);
return accountService.save(adminAccount, adminPassword);
}
private void initDefaultClient(Account adminAccount) {
long adminAccountId = adminAccount.getId();
Collection<Client> adminClients = clientRepository.findAllByOwnerId(adminAccountId);
if (adminClients.isEmpty()) {
Client defaultClient = new Client();
defaultClient.setOwnerId(adminAccountId);
defaultClient.setDescription(defaultClientDescription);
Collection<ClientRoles> clientRoles = new HashSet<>(2);
clientRoles.add(ClientRoles.ROLE_CLIENT);
clientRoles.add(ClientRoles.ROLE_DEFAULT_CLIENT);
defaultClient.setRoles(clientRoles);
Collection<GrantTypes> grantTypes = new HashSet<>();
grantTypes.add(GrantTypes.authorization_code);
grantTypes.add(GrantTypes.client_credentials);
grantTypes.add(GrantTypes.password);
grantTypes.add(GrantTypes.refresh_token);
defaultClient.setGrantTypes(grantTypes);
defaultClient = clientRepository.save(defaultClient);
logger.info(String.format("Added new default client with id '%s'", defaultClient.getId()));
}
}
@Override
public void run(String... args) {
Account adminAccount = initAdminAccount();
initDefaultClient(adminAccount);
}
private void setAdminAccountData(Account adminAccount) {
adminAccount.setEmail(adminEmail);
adminAccount.setRoles(DEFAULT_ACCOUNT_ROLES);
adminAccount.setAccountDetails(new AccountDetails());
adminAccount.setAccountProfile(new AccountProfile(adminName));
}
}
wie die Komponenten Sieht aus, wo beim Start nicht initialisiert, wenn die CommandLineRunner verwenden. Bitte versuchen Sie, die Klasse, die mit dem CommandLineRunner gestartet wurde, mit '@ ComponentScan' zu kommentieren. – alltej
Bitte teilen Sie Ihren Code/Klasse, die mit dem CommandLineRunner gestartet wurde – alltej
Danke für Ihre Antwort @alltej! Ich habe die Frage bearbeitet, um den CommandLineRunner hinzuzufügen. – yngwi