CrudRepository Unsatisfied dependency expressed through field folioRepository - spring

I am getting error Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'getFolioService': Unsatisfied dependency expressed through field 'folioRepository': No qualifying bean of type [a.b.c.repository.FolioRepository]
I am running Junit test case for my service, which save document in couchbase.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = AppConfig.class, loader = AnnotationConfigContextLoader.class)
public class FolioServiceTest {
#Autowired
private FolioService folioService;
#Test
public void testAddFolioTransaction() {
Folios folios = new Folios();
folios.setUiid("user123");
List<Order> orders = new ArrayList<Order>();
Order order = new Order();
order.set__type("type1");
order.set__version("version1");
order.setCreatedDate("09/02/2016");
order.setCreatedUser("test user");
OrderPayload orderPayload = new OrderPayload();
orderPayload.set__type("type payload type");
orderPayload.set__version("version payload type");
order.setOrderPayload(orderPayload);
orders.add(order);
folios.getOrder().addAll(orders);
boolean flag= folioService.addFolioTransaction(folios);
assertTrue(flag == true);
}
#Configuration
public class AppConfig {
#Bean
public FolioService getFolioService() {
return new FolioService();
}
}
}
#Service
public class FolioService {
private final static Logger LOGGER = LoggerFactory.getLogger(FolioService.class);
#Autowired
FolioRepository folioRepository;
/**
* Method will save the folio to the couchbase
*
* #param folios
*/
public boolean addFolioTransaction(Folios folios){
LOGGER.debug("Adding transaction details to folio.");
Folios newFolio = folioRepository.save(folios);
if (newFolio != null) {
return true;
}
return false;
}
public Folios getFolioDetailsByUiid(String uiid){
LOGGER.debug("Get folio details by uiid.");
Folios folios = folioRepository.findOne(uiid);
return folios;
}
}
#Repository
public interface FolioRepository extends CrudRepository{
}

Related

Error while autowiring String in springboot

I'm getting the below during the server startup. I'm trying to apply constructor injection here but it doesn't see to work? I do not want to assign any default value to gameId. The purpose of the class is to act as a model How can I fix this?
Error
Parameter 0 of constructor in Score required a bean of type 'java.lang.String' that could not be found.
no qualifying bean of type 'java.lang.String'
Code
#Repository
public class Score {
private final Map<String, List<BatsmanScore>> scoreRepository = new HashMap<>();
private final List<BatsmanScore> batsmanScores;
private final String gameId;
public Score(String gameId, List<BatsmanScore> batsmanScores) {
this.gameId = gameId;
this.batsmanScores = batsmanScores;
}
public List<BatsmanScore> getBatsmanScores() {
return batsmanScores;
}
public List<BatsmanScore> getBatsmanScoresByGameId(String gameId) {
return scoreRepository.get(gameId);
}
public String getGameId() {
return gameId;
}
public void storeScores(String gameId, List<BatsmanScore> batsmanScores) {
if (!scoreRepository.containsKey(gameId)) {
scoreRepository.put(gameId, new ArrayList<>());
}
scoreRepository.get(gameId).addAll(batsmanScores);
}
}

Sending #Value annotated fields to a DTO layer returns null

I have a class which is composed of 2 different objects :
public class MyClass{
private OptionClass optionClass;
private ConstantClass constantClass;
public DocumentToSignRestRequest(OptionClass optionClass, ConstantClass constantClass) {
this.optionClass= optionClass;
this.constantClass= constantClass;
}
}
My first class is a classic POJO. My second class retrieve values from the application.properties file.
public class ConstantClass {
#Value("${api.url}")
private String hostName;
#Value("${sign.path}")
private String pathStart;
public ConstantClass () {
this.hostName= getHostName();
this.path = getPath();
}
I map MyClass with MyClassDto in order to call a service.
#PostMapping(
value="/sign",
consumes = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE },
produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE }
)
public MyClassRest prepareDocument(#RequestBody DocumentToPrepare documentToPrepare) throws Exception {
MyClassRest returnValue = new MyClassRest ();
ModelMapper modelMapper = new ModelMapper();
MyClassDto myClassDto = modelMapper.map(documentToPrepare, MyClassDto .class);
DocumentDto signedDocument = documentService.signDocument(documentDto);
returnValue = modelMapper.map(signedDocument, DocumentRest.class);
return returnValue;
}
My DTO class work fine and retrieve the OptionClass datas, but concerning the second Class, i obtain null as value, while i try to print it out in the service layer.
Your ConstantClass should be a Bean or a Component (as #cassiomolin says in comments)
#Component
public class ConstantClass {
private String hostName;
private String pathStart;
public ConstantClass (#Value("${api.url}") String url, #Value("${sign.path}") String path ) {
this.hostName = url;
this.pathStart = path;
}
// getters...
Then you can easily inject this component in your Controller and use it.
#Controller
public class YourController(){
private ConstantClass constantClass;
public YourController(ConstantClass constantClass){
this.constantClass = constantClass;
}
#PostMapping("...")
public MyClass post(.....){
.....
MyClass myclass = new MyClass(this.constantClass,...)
.....
}
}
note that Spring can autowire #Value and #Component, ... via the constructor; that can be very useful when you do unit-testing

camelContext attribute discriminator for tenant resolver , using jpa multitenant and camel routeId

i ask you how can use camelContext to get the name of route fired by an event, more in details, how can I use any kind of discriminator attribute x in camelContext for predicate decision (if x =1 then .. else ..)
For example:
I have this kind of route:
//this route use the forst database
from("direct:csvprocessor1")
.routeId("tenant1")
.from("file:src/main/resources/data/1?move=OUT&moveFailed=REFUSED")
.unmarshal(csv)
.to("bean:myCsvHandler?method=doHandleCsvData")
.setBody(constant("OK VB"))
.setHeader(Exchange.HTTP_RESPONSE_CODE, constant(200))
.setHeader(Exchange.CONTENT_TYPE, constant("text/html"));
and this other route:
//this route use tenant2, the second database
from("direct:csvprocessor1")
.routeId("tenant2")
.from("file:src/main/resources/data/2?move=OUT&moveFailed=REFUSED")
.unmarshal(csv)
.to("bean:myCsvHandler?method=doHandleCsvData")
.setBody(constant("OK 2"))
.setHeader(Exchange.HTTP_RESPONSE_CODE, constant(200))
.setHeader(Exchange.CONTENT_TYPE, constant("text/html"));
when i pick up file in 1 folder the first route named "tenant1" starts, the same happen when pick up file in 2, the second route tenant2 starts.It reads csv content and the content must be write using jpa on the right tenantX (database)
I have to retrieve routeid name in another class but this class instanced before the camel Context start so i can't inject context (because this class "BatchCurrentTenantIdentifierResolverImpl " belong to Spring database initializator). I try to add method "of" to set camelContext but i get tenant1 only, also when route 2 starts, so can't switch from tenant to another tenant (tenant is database, i have two database):
#Component
public class BatchTenantContext {
private static final Logger log = LoggerFactory.getLogger(BatchTenantContext.class);
// don't Inject, use method Of because injecton was null
CamelContext cctx;
public BatchTenantContext(){getInstance();}
private final static BatchTenantContext instance = new BatchTenantContext();
public static BatchTenantContext getInstance(){
return instance;
}
public synchronized String get() {
if (cctx != null){
Route val = cctx.getRoute("tenant1");
if (val == null){
val = cctx.getRoute("tenant2");
if (val == null){
return "";
}
else {
return "tenant_2";
}
}
else return "tenant_1";
}
return "";
}
public synchronized void of(CamelContext ctx){
cctx = ctx;
}
public CamelContext getCamelContext()
{
return cctx;
}
}
//multitenant approach, switch from one database to another
//based on BatchTenantContext resolution..
public class BatchCurrentTenantIdentifierResolverImpl implements CurrentTenantIdentifierResolver {
static final Logger log = LoggerFactory.getLogger(BatchCurrentTenantIdentifierResolverImpl.class);
#Override
public String resolveCurrentTenantIdentifier() {
String val = BatchTenantContext.getInstance().get();
log.info("*** get tenant " + val);
return val;
}
#Override
public boolean validateExistingCurrentSessions() {
return true;
}
}
So, how to know how route fire? Note thaht the class above is singleton..I'm in a right way?
I use jpa whitin hibernate provider, configured using rhe multitenant configuration like this post: http://tech.asimio.net/2017/01/17/Multitenant-applications-using-Spring-Boot-JPA-Hibernate-and-Postgres.html
The application work in spring-boot Runtime environment or with Tomcat app server.
Any ideas about all?
Thanks so much!
roby
I add this code:
#Configuration
#EnableConfigurationProperties({ MultiTenantAfSissProperties.class, JpaProperties.class })
#ImportResource(locations = { "classpath:applicationContent.xml" })
#EnableTransactionManagement
public class MultiTenantJpaConfiguration {
static final Logger logger = LoggerFactory.getLogger(MultiTenantJpaConfiguration.class);
#Inject
private JpaProperties jpaProperties;
#Inject
MultiTenantAFSISSProperties multiTenantAFSISSProperties; //lista dei datasources collegati ai tenant
#Bean
public Map<String, DataSource> dataSourceRetrieval(){
Map<String, DataSource> result = new HashMap<>();
for (DataSourceProperties dsProperties : this.multiTenantAFSISSProperties.getDataSources()) {
DataSourceBuilder factory = DataSourceBuilder
.create()
.url(dsProperties.getUrl())
.username(dsProperties.getUsername())
.password(dsProperties.getPassword())
.driverClassName(dsProperties.getDriverClassName());
result.put(dsProperties.getTenantId(), factory.build());
}
return result;
}
/**
*
* #return
*/
#Bean
public MultiTenantConnectionProvider multiTenantConnectionProvider(){
return new AfsissMultiTenantConnectionProviderImpl();
}
/**
*
* #return
*/
#Bean
public CurrentTenantIdentifierResolver currentTenantIdentifierResolver(){
return new BatchCurrentTenantIdentifierResolverImpl();
}
/**
*
* #param multiTenantConnectionProvider
* #param currentTenantIdentifierResolver
* #return
*/
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(MultiTenantConnectionProvider multiTenantConnectionProvider,
CurrentTenantIdentifierResolver currentTenantIdentifierResolver) {
Map<String, Object> hibernateProps = new LinkedHashMap<>();
hibernateProps.putAll(this.jpaProperties.getProperties());
Map<String,String> all = this.jpaProperties.getProperties();
for ( Map.Entry<String, String> prop : all.entrySet()){
System.out.println(" " + prop.getKey() + " = " + prop.getValue());
}
hibernateProps.put(Environment.MULTI_TENANT, MultiTenancyStrategy.DATABASE);
hibernateProps.put(Environment.MULTI_TENANT_CONNECTION_PROVIDER, multiTenantConnectionProvider);
hibernateProps.put(Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, currentTenantIdentifierResolver);
// No dataSource is set to resulting entityManagerFactoryBean
LocalContainerEntityManagerFactoryBean result = new LocalContainerEntityManagerFactoryBean();
result.setPackagesToScan(new String[] { AfFileEntity.class.getPackage().getName() });
result.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
result.setJpaPropertyMap(hibernateProps);
return result;
}
/**
* crea la factory per ricavare l'entity manager
* #param entityManagerFactoryBean
* #return
*/
#Bean
public EntityManagerFactory entityManagerFactory(LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
return entityManagerFactoryBean.getObject();
}
/**
* get transaction manager
* #param entityManagerFactory
* #return
*/
#Bean
public PlatformTransactionManager txManager(EntityManagerFactory entityManagerFactory) {
SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
HibernateTransactionManager result = new HibernateTransactionManager();
result.setAutodetectDataSource(false);
result.setSessionFactory(sessionFactory);
return result;
}
}
In applicationContent.xml:
<jpa:repositories base-package="com.xxx.dao" transaction-manager-ref="txManager" />
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" />
The class BatchCurrentTenantIdentifierResolverImpl is called in currentTenantIdentifierResolver() method above by spring transaction manager every time i use entity manager and transaction manager in csvHanlder :
#Component
#Transactional(propagation = Propagation.REQUIRED)
public class MyCsvHandler {
#Inject
AFMOVCrudRepository _entitymanagerMov; //it extends JpaRepository
#Inject
AFVINCCrudRepository _entityManagerVINC;//it extends JpaRepository
#Inject
AFFileCrudRepository _entityManagerAfFile;//it extends JpaRepository
static final Logger logger = LoggerFactory.getLogger(MyCsvHandler.class);
//save csv data on the right table on the right tenant
public void doHandleCsvData(List<List<String>> csvData) throws FileNotEvaluableException
{
//System.out.println("stampo..");
boolean status = true;
if (csvData.size() > 0){
AfFileEntity afbean = new AfFileEntity();
afbean.setNomeFile("test");
afbean.setDataImport(new java.sql.Timestamp(System.currentTimeMillis()));
afbean.setTipoFile("M");
afbean.setAfStatoFlusso("I");
_entityManagerAfFile.save(afbean);
long pkfile = afbean.getId();
logger.info("pkfile: " + pkfile);
int i = 1;
logger.info("file size:" + csvData.size());
for (List<String> rows : csvData){
//for (int j = 0; i < rows.size(); j++){
if (rows.get(2).trim().equalsIgnoreCase(...)){
MovEntity mbean = new MovEntity();
setMovFields(mbean, rows);
mbean.setAfFileId(afbean);
logger.info(String.valueOf((i++)) + " " + mbean);
_entitymanagerMov.save(mbean);
}
else if (rows.get(2).trim().equalsIgnoreCase(..) || rows.get(2).trim().equalsIgnoreCase(..) ) {
VincEntity vincBean = new VincEntity();
setVincFields(vincBean, rows);
vincBean.setAfFileId(afbean);
logger.info(String.valueOf((i++)) + " " + vincBean);
_entityManagerVINC.save(vincBean);
}
else {
status = false;
break;
}
}
if (!status) throw new FileNotEvaluableException("error file format");
}
}
private void setVincFields(VincEntity vincBean, List<String> rows) {
vincBean.setXXX().. and others methods
}
private void setMovFields(MovEntity mbean, List<String> rows) {
mbean.setStxxx() and other .. methods
}
return new
Something like this in your routes
from("direct:csvprocessor1").routeId("tenant2").process((Exchange e)-> {
BatchCurrentTenantIdentifierResolverImpl.tenant.set("tenant_1");
})
.from("file:src/main/resources/data/2?move=OUT&moveFailed=REFUSED")
.unmarshal().csv()
.to("bean:myCsvHandler?method=doHandleCsvData")
.setBody(constant("OK 2"))
.setHeader(Exchange.HTTP_RESPONSE_CODE, constant(200))
.setHeader(Exchange.CONTENT_TYPE, constant("text/html"));
And in your BatchCurrentTenantIdentifierResolverImpl implement it aspublic
class BatchCurrentTenantIdentifierResolverImpl {
public static ThreadLocal<String> tenant = new ThreadLocal<String>();
static final Logger log = LoggerFactory.getLogger(BatchCurrentTenantIdentifierResolverImpl.class);
#Override
public String resolveCurrentTenantIdentifier() {
String val = tenant.get();
log.info("*** get tenant " + val);
return val;
}
#Override
public boolean validateExistingCurrentSessions() {
return true;
}
}

Spring validator fails looking up value of class level constraint

I'm getting an error with JSR 303 class level validation and spring and I'd like to know if I am setting things up in the correct way.
I'm using validation in spring (4.2.6.RELEASE) using hibernate-validator (5.2.4.Final) with a typical setup inside a spring controller like:
#RequestMapping(value = "/{id}", method = RequestMethod.PUT)
public SomeDto update(#PathVariable Integer id, #Valid #RequestBody SomeDto someDto) {
...
return someDto;
}
This works fine with most setups, but when the target of the validation includes a set of objects that are annotated with a Class level validation the SpringValidatorAdaptor fails when trying to lookup the original value
The following code illustrates the problem:
Target class to validate:
public class Base {
#Valid
Set<MyClass> myClassSet = new HashSet<>();
public Set<MyClass> getMyClassSet() {
return myClassSet;
}
Class with class level validation annotation:
#CheckMyClass
public class MyClass {
String a;
String b;
public MyClass(final String a, final String b) {
this.a = a;
this.b = b;
}
}
Constraint:
#Target({ TYPE, ANNOTATION_TYPE })
#Retention(RUNTIME)
#Constraint(validatedBy = CheckMyClassValidator.class)
#Documented
public #interface CheckMyClass {
String message() default "Invalid class";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
Validator:
public class CheckMyClassValidator implements ConstraintValidator<CheckMyClass, MyClass> {
#Override
public void initialize(final CheckMyClass constraintAnnotation) {
}
#Override
public boolean isValid(final MyClass value, final ConstraintValidatorContext context) {
return false; // want it to fail for testing purposes
}
}
Test class:
#SpringBootApplication
public class SpringValidationTest {
#Bean
public org.springframework.validation.Validator validator() {
return new org.springframework.validation.beanvalidation.LocalValidatorFactoryBean();
}
private void doStandardValidation() {
Base base = createBase();
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<Base>> violations = validator.validate(base);
for (ConstraintViolation<?> violation : violations) {
System.out.println(violation.getMessage());
}
}
private Base createBase() {
Base base = new Base();
base.getMyClassSet().add(new MyClass("a1", "b1"));
// base.getMyClassSet().add(new MyClass("a2", "b2"));
return base;
}
#PostConstruct
private void doSpringValidation() {
Base base = createBase();
org.springframework.validation.Validator validator = validator();
DataBinder binder = new DataBinder(base);
binder.setValidator(validator);
binder.validate();
BindingResult results = binder.getBindingResult();
for (ObjectError error : results.getAllErrors()) {
System.out.println(error.getDefaultMessage());
}
}
public static void main(String[] args) {
(new SpringValidationTest()).doStandardValidation();
System.out.println();
ApplicationContext applicationContext = SpringApplication.run(SpringValidationTest.class);
}
}
The standard validation works fine, but when it is wrapped by the spring validator (as in the typical controller setup) it ends up with an exception (as below) trying to lookup the value of the property:
Caused by: java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) ~[na:1.8.0_45]
at java.lang.Integer.parseInt(Integer.java:592) ~[na:1.8.0_45]
at java.lang.Integer.parseInt(Integer.java:615) ~[na:1.8.0_45]
at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:657) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
... 37 common frames omitted

Use #Autowired in #Webservice (other solutions found did not work)

We are trying to use autowiring in our webservice, but this doens't seem to work (generates nullPointer). We have been searching for a solution for quite a long time, but did not succeed.
Our webservice:
#WebService(wsdlLocation = "/WEB-INF/wsdl/contract.wsdl", serviceName = "BookingService", targetNamespace = "http://realdolmen.com/", portName = "BookingServicePortType")
public class BookingService extends SpringBeanAutowiringSupport implements BookingServicePortType {
#Autowired
BookingServiceBean bookingServiceBean;
#Autowired
TariffService tariffService;
#Override
public BookingResponse createBooking(#WebParam(name = "bookingInput", targetNamespace = "http://realdolmen.com/", partName = "tariffId") BookingInput input) {
Tariff tariff = tariffService.getTariffById(input.getTariffId());
Booking booking = new Booking.BookingBuilder().withBaggageAllowance(tariff.getFlight().getBaggageAllowance())
.withDayOfDeparture(input.getDayOfDeparture()).withHourOfDeparture(input.getHourOfDeparture()).withTariff(tariff).withDuration(input.getDuration()).createBooking();
bookingServiceBean.createBooking(booking);
BookingResponse bookingResponse = new BookingResponse();
bookingResponse.setBookingId(booking.getId());
bookingResponse.setBaggageAllowance(booking.getBaggageAllowance());
bookingResponse.setDayOfDeparture(createWeirdDateClass(booking.getDayOfDeparture()));
bookingResponse.setDuration(booking.getDuration());
bookingResponse.setHourOfDeparture(booking.getHourOfDeparture());
return bookingResponse;
}
private XMLGregorianCalendar createWeirdDateClass(String lexicalRepresentation) {
try {
return DatatypeFactory.newInstance().newXMLGregorianCalendar(lexicalRepresentation);
} catch (DatatypeConfigurationException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
return null;
}
}
}
our spring service:
#Service
#Transactional
public class BookingServiceBeanImpl implements BookingServiceBean {
#Autowired
BookingDAO bookingDAO;
#Override public void createBooking(Booking booking) {
bookingDAO.createBooking(booking);
}
}
The spring bean can be used in the spring controllers so I don't think there's a problem there..

Resources