Implementing Snapshot in AXON 3.0 : Aggregate Type is unknown in this snapShotter - spring

I'm still new to the axon frame work.
I'm trying to implement snapshotting using mongodb in my application and I keep on getting an error saying
"AbstractSnapshotter : An attempt to create and store a snapshot resulted in an exception. Exception summary: Aggregate Type is unknown in this snapshotter: com.myworklife.contacts.domain.contact.Contact"
This is a part of my java config file.
#Bean
public AggregateSnapshotter snapShotter(EventStore eventStore, AggregateFactory<Contact> contactAggregateFactory) {
return new AggregateSnapshotter(eventStore);
}
#Bean
public SnapshotTriggerDefinition snapshotTriggerDefinition(Snapshotter snapShotter) throws Exception {
return new EventCountSnapshotTriggerDefinition(snapShotter, 1);
}
#Bean
public EventStore eventStore(EventStorageEngine eventStorageEngine) {
return new EmbeddedEventStore(eventStorageEngine);
}
#Bean
public Repository<Contact> contactAggregateRepository(EventStore eventStore, SnapshotTriggerDefinition snapshotTriggerDefinition) {
return new ContactRepository(eventStore, snapshotTriggerDefinition);
}
And my repository.
#Repository("ContactRepository")
public class ContactRepository extends EventSourcingRepository<Contact> {
#Autowired
public ContactRepository(EventStore eventStore, SnapshotTriggerDefinition snapshotTriggerDefinition) {
super(Contact.class, eventStore, snapshotTriggerDefinition);
}
public Contact findContact(ContactId contactId) {
return load(contactId.toString()).getWrappedAggregate().getAggregateRoot();
}
}
My aggregate.
#Aggregate(repository="contactAggregateRepository")
public class Contact {
#AggregateIdentifier
private ContactId id;
private String name;
private String mobileNumber;
public Contact() {
// do nothing, Axon requires default constructor
}
#CommandHandler
public Contact(CreateContactCommand createContactCommand) {
apply(new ContactHasBeenCreatedEvent(createContactCommand.getContactId(), createContactCommand.getName(),
createContactCommand.getMobileNumber()));
}
}
Is there something I'm doing wrong?
since I'm getting an error saying "An attempt to create and store a snapshot resulted in an exception. Exception summary: Aggregate Type is unknown in this snapshotter: com.myworklife.contacts.domain.contact.Contact"
Any help will be highly appreciated.
Thanks,
Pat

You need to add the contactAggregateFactory to the constructor of the AggregateSnapshotter in the snapShotter bean:
#Bean
public AggregateSnapshotter snapShotter(EventStore eventStore, AggregateFactory<Contact> contactAggregateFactory) {
return new AggregateSnapshotter(eventStore, contactAggregateFactory);
}

1.depencity jar
<dependency>
<groupId>org.axonframework</groupId>
<artifactId>axon-spring-boot-autoconfigure</artifactId>
<version>${axon.version}</version>
</dependency>
2.At first,you should config your application.ymp or bootstrap.yml,like this:spring:
data:
mongodb:
host: localhost
port: 27017
database: axonframework
events: domainevents
snapshots: snapshotevents
3.config your mongoDB:
#Bean(name = "axonMongoTemplate")
public MongoTemplate axonMongoTemplate() {
MongoTemplate template = new DefaultMongoTemplate(mongoClient(), mongoDbName, eventsCollectionName, snapshotCollectionName);
return template;
}
#Bean
public MongoClient mongoClient(){
MongoFactory mongoFactory = new MongoFactory();
mongoFactory.setMongoAddresses(Arrays.asList(new ServerAddress(mongoHost)));
return mongoFactory.createMongo();
}
#Bean
public EventStorageEngine eventStorageEngine(Serializer serializer){
return new MongoEventStorageEngine(
serializer,null, axonMongoTemplate(), new DocumentPerEventStorageStrategy());
4.config repository for your aggregate,for example,i config a Element Aggreaget's repository
#Configuration
public class ElementConfiguration {
#Autowired
private EventStore eventStore;
#Bean
#Scope("prototype")
public Element elementAggregate() {
return new Element();
}
#Bean
public AggregateFactory<Element> elementAggregateAggregateFactory() {
SpringPrototypeAggregateFactory<Element> aggregateFactory = new SpringPrototypeAggregateFactory<>();
aggregateFactory.setPrototypeBeanName("elementAggregate");
return aggregateFactory;
}
#Bean
public SpringAggregateSnapshotterFactoryBean springAggregateSnapshotterFactoryBean(){
SpringAggregateSnapshotterFactoryBean factory = new SpringAggregateSnapshotterFactoryBean();
return factory;
}
#Bean
public Repository<Element> elementAggregateRepository(Snapshotter snapshotter) {
EventCountSnapshotTriggerDefinition eventCountSnapshotTriggerDefinition = new EventCountSnapshotTriggerDefinition(snapshotter, 3);
EventSourcingRepository<Element> repository = new EventSourcingRepository<Element>(
elementAggregateAggregateFactory(),
eventStore,
eventCountSnapshotTriggerDefinition
);
return repository;
}
5.enjoy

If you're using Axon 3.3 and SpringBoot 2, this is how we did it in this project:
#Configuration
public class SnapshotConfiguration {
#Bean
public SpringAggregateSnapshotter snapshotter(ParameterResolverFactory parameterResolverFactory,
EventStore eventStore,
TransactionManager transactionManager) {
// https://docs.axoniq.io/reference-guide/v/3.3/part-iii-infrastructure-components/repository-and-event-store#snapshotting
// (...) By default, snapshots are created in the thread that calls the scheduleSnapshot() method, which is generally not recommended for production (...)
Executor executor = Executors.newSingleThreadExecutor();
return new SpringAggregateSnapshotter(eventStore, parameterResolverFactory, executor, transactionManager);
}
#Bean
public EventCountSnapshotTriggerDefinition snapshotTrigger(SpringAggregateSnapshotter snapshotter) {
int snapshotThreshold = 42;
return new EventCountSnapshotTriggerDefinition(snapshotter, snapshotThreshold);
}
}
And if you need the EventStore configuration:
#Configuration
public class AxonMongoEventStoreConfiguration {
#Bean
public MongoClient axonMongoClient(MongoClientURI axonMongoClientUri) {
return new MongoClient(axonMongoClientUri);
}
#Bean
public MongoClientURI axonMongoClientUri() {
return new MongoClientURI("mongodb://host:port/database");
}
#Bean
#Primary
public EventStorageEngine eventStore(MongoClient axonMongoClient, MongoClientURI axonMongoClientUri) {
DefaultMongoTemplate mongoTemplate = new DefaultMongoTemplate(axonMongoClient, axonMongoClientUri.getDatabase());
return new MongoEventStorageEngine(mongoTemplate);
}
}

Related

How to use error-channel for catching exception in Spring Integration?

What I am trying to do? : I am new to Spring Integration and already have read many similar questions regarding error handling but I don't understand how to catch exceptions using error-channel?
What I have done so far:
#EnableIntegration
#IntegrationComponentScan
#Configuration
public class TcpClientConfig implements ApplicationEventPublisherAware {
private ApplicationEventPublisher applicationEventPublisher;
private final ConnectionProperty connectionProperty;
#Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
TcpClientConfig(ConnectionProperty connectionProperty) {
this.connectionProperty = connectionProperty;
}
#Bean
public AbstractClientConnectionFactory clientConnectionFactory() {
TcpNioClientConnectionFactory tcpNioClientConnectionFactory =
getTcpNioClientConnectionFactoryOf(
connectionProperty.getPrimaryHSMServerIpAddress(),
connectionProperty.getPrimaryHSMServerPort());
final List<AbstractClientConnectionFactory> fallBackConnections = getFallBackConnections();
fallBackConnections.add(tcpNioClientConnectionFactory);
final FailoverClientConnectionFactory failoverClientConnectionFactory =
new FailoverClientConnectionFactory(fallBackConnections);
return new CachingClientConnectionFactory(
failoverClientConnectionFactory, connectionProperty.getConnectionPoolSize());
}
#Bean
DefaultTcpNioSSLConnectionSupport connectionSupport() {
final DefaultTcpSSLContextSupport defaultTcpSSLContextSupport =
new DefaultTcpSSLContextSupport(
connectionProperty.getKeystorePath(),
connectionProperty.getTrustStorePath(),
connectionProperty.getKeystorePassword(),
connectionProperty.getTruststorePassword());
final String protocol = "TLSv1.2";
defaultTcpSSLContextSupport.setProtocol(protocol);
return new DefaultTcpNioSSLConnectionSupport(defaultTcpSSLContextSupport, false);
}
#Bean
public MessageChannel outboundChannel() {
return new DirectChannel();
}
#Bean
#ServiceActivator(inputChannel = "outboundChannel")
public MessageHandler outboundGateway(AbstractClientConnectionFactory clientConnectionFactory) {
TcpOutboundGateway tcpOutboundGateway = new TcpOutboundGateway();
tcpOutboundGateway.setConnectionFactory(clientConnectionFactory);
return tcpOutboundGateway;
}
#Bean
#ServiceActivator(inputChannel = "error-channel")
public void handleError(ErrorMessage em) {
throw new RuntimeException(String.valueOf(em));
}
private List<AbstractClientConnectionFactory> getFallBackConnections() {
final int size = connectionProperty.getAdditionalHSMServersConfig().size();
List<AbstractClientConnectionFactory> collector = new ArrayList<>(size);
for (final Map.Entry<String, Integer> server :
connectionProperty.getAdditionalHSMServersConfig().entrySet()) {
collector.add(getTcpNioClientConnectionFactoryOf(server.getKey(), server.getValue()));
}
return collector;
}
private TcpNioClientConnectionFactory getTcpNioClientConnectionFactoryOf(
final String ipAddress, final int port) {
TcpNioClientConnectionFactory tcpNioClientConnectionFactory =
new TcpNioClientConnectionFactory(ipAddress, port);
tcpNioClientConnectionFactory.setUsingDirectBuffers(true);
tcpNioClientConnectionFactory.setDeserializer(new CustomDeserializer());
tcpNioClientConnectionFactory.setApplicationEventPublisher(applicationEventPublisher);
tcpNioClientConnectionFactory.setSoKeepAlive(true);
tcpNioClientConnectionFactory.setConnectTimeout(connectionProperty.getConnectionTimeout());
tcpNioClientConnectionFactory.setSoTcpNoDelay(true);
tcpNioClientConnectionFactory.setTcpNioConnectionSupport(connectionSupport());
return tcpNioClientConnectionFactory;
}
}
Gateway
#Component
#MessagingGateway(defaultRequestChannel = "outboundChannel",errorChannel ="error-channel" )
public interface TcpClientGateway {
String send(String message);
}
Also currently, I am facing
required a bean of type org.springframework.messaging.support.ErrorMessage that could not be found
I need some assistance!
Thanking you in advance,
EDIT
#AllArgsConstructor
#Service
public class AsyncNonBlockingClient implements Connector {
TcpClientGateway tcpClientGateway;
#Override
public String send(final String payload) {
return tcpClientGateway.send(payload);
}
}
See documentation about messaging annotation:
Your problem is here: https://docs.spring.io/spring-integration/docs/current/reference/html/configuration.html#annotations_on_beans
#Bean
#ServiceActivator(inputChannel = "error-channel")
public void handleError(ErrorMessage em) {
This is a plain POJO method, therefore it cannot be marked with a #Bean. You use a #Bean really for beans to expose. Then you decide if that has to be a #ServiceActivator or not. So, just remove #Bean from this method and your error-channel consumer should be OK.

Integration RedHat DataGrid with Spring Boot (throw SocketTimeoutException)

I create an application with spring boot that use the data grid redHat (Infinispan 'Estrella Galicia' 9.3.6.Final in standalone) to management of java bean in memory chache.
When i get the cache configured on datagrid, i show the following error:
*java.net.SocketTimeoutException: FaultTolerantPingOperation{default, flags=0} timed out after 60000 ms
at org.infinispan.client.hotrod.impl.operations.HotRodOperation.run(HotRodOperation.java:172) ~[infinispan-client-hotrod-9.4.0.Final.jar:9.4.0.Final]"
The configuration of my application is the following:
Console RedHat Datagrid:
Maven dependencies:
Configuration Spring:
#Primary
#Bean(name = "cacheManager")
public CacheManager cacheManager() throws Exception {
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.addServer().host("127.0.0.1").port(11222);
RemoteCacheManager remoteCacheManager = new RemoteCacheManager(builder.build());
return new SpringRemoteCacheManager(remoteCacheManager);
}
#Bean
public CacheResolver cacheResolver() throws Exception {
NamedCacheResolver resolver = new NamedCacheResolver();
resolver.setCacheManager(cacheManager());
resolver.setCacheNames(Collections.singleton("default"));
return resolver;
}
This is the Java Bean
public class UdmOutput {
private String entityCode;
private Udm unitaPrimaria;
private List<Udm> udmList;
public UdmOutput() {
}
public String getEntityCode() {
return entityCode;
}
public void setEntityCode(String entityCode) {
this.entityCode = entityCode;
}
public List<Udm> getUdmList() {
return udmList;
}
public void setUdmList(List<Udm> udmList) {
this.udmList = udmList;
}
public Udm getUnitaPrimaria() {
return unitaPrimaria;
}
public void setUnitaPrimaria(Udm unitaPrimaria) {
this.unitaPrimaria = unitaPrimaria;
}
}
This is the code used to insert java bean in cache:
#CachePut(cacheResolver="cacheResolver", key="#keyLogic")
public UdmOutput saveObjectInCache(UdmOutput msg, String keyLogic) {
return msg;
}
When run of the method ends i get the exception SocketTimeoutException
Can you help me ?
Thanks a lot,
Giuseppe.

Multiple LDAP repositories with Spring LDAP Repository

I would like to set more than one LDAP repositories with Spring LDAP. My aim is to create or update objects in all repositories at the same time.
I use LdapRepository Spring interface and I think that isn't possible for now.
I wonder if I can create my own LdapRepository extending the Spring one but I have no idea how to start.
This my configuration :
#Configuration
#EnableLdapRepositories("com.xxx.repository.ldap")
#PropertySource("classpath:ldap.properties")
public class LdapConfiguration {
#Autowired
Environment ldapProperties;
#Bean
public LdapContextSourceCustom contextSourceTarget() {
LdapContextSourceCustom ldapContextSource = new LdapContextSourceCustom();
ldapContextSource.setUrl(ldapProperties.getProperty("ldap.url"));
ldapContextSource.setBase(ldapProperties.getProperty("ldap.base"));
ldapContextSource.setUserDn(ldapProperties.getProperty("ldap.userDn"));
ldapContextSource.setPassword(ldapProperties.getProperty("ldap.password"));
ldapContextSource.setKeyStoreFile(ldapProperties.getProperty("ldap.truststore"));
return ldapContextSource;
}
#Bean
public LdapTemplate ldapTemplate(){
return new LdapTemplate(contextSourceTarget());
}
}
And to be complete, one repository:
public interface LdapUserRepository extends LdapRepository<LdapUser> {
}
Any idea how to do it ?
Thanks in advance for any help.
1) It is possible specify more than one LDAP Repository configuration. Please see the following example. [Notice: This depends on spring-boot libraries]
#Configuration
#EnableLdapRepositories("com.xxx.repository.ldap")
#EnableConfigurationProperties(LdapProperties.class)
public class LdapConfiguration {
#Autowired
private Environment environment;
#Bean(name="contextSource1")
public LdapContextSource contextSourceTarget(LdapProperties ldapProperties) {
LdapContextSource source = new LdapContextSource();
source.setUserDn(this.properties.getUsername());
source.setPassword(this.properties.getPassword());
source.setBase(this.properties.getBase());
source.setUrls(this.properties.determineUrls(this.environment));
source.setBaseEnvironmentProperties(Collections.<String,Object>unmodifiableMap(this.properties.getBaseEnvironment()));
return source;
}
#Bean
public LdapTemplate ldapTemplate(#Qualifier("contextSource1") LdapContextSource contextSource){
return new LdapTemplate(contextSource);
}
}
You can use the spring.ldap prefix in application.properties to configure the above LdapConfiguration. You can see the available properties by checking out https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ldap/LdapProperties.java.
#Configuration
#EnableLdapRepositories(basePackages="com.yyy.repository.ldap", ldapTemplateRef="ldapTemplate2")
public class LdapConfiguration2 {
#Autowired
private Environment environment;
#Bean(name="ldapProperties2")
#ConfigurationProperties(prefix="spring.ldap2")
public LdapProperties ldapProperties() {
return new LdapProperties();
}
#Bean(name="contextSource2")
public LdapContextSource contextSourceTarget(#Qualifier("ldapProperties2") LdapProperties ldapProperties) {
LdapContextSource source = new LdapContextSource();
source.setUserDn(this.properties.getUsername());
source.setPassword(this.properties.getPassword());
source.setBase(this.properties.getBase());
source.setUrls(this.properties.determineUrls(this.environment));
source.setBaseEnvironmentProperties(Collections.<String,Object>unmodifiableMap(this.properties.getBaseEnvironment()));
return source;
}
#Bean(name="ldapTemplate2")
public LdapTemplate ldapTemplate(#Qualifier("contextSource2") LdapContextSource contextSource){
return new LdapTemplate(contextSource);
}
}
LdapConfiguration2 will be configured by the spring.ldap2 prefix in application.properties.
2) I don't think extending the Repository is the solution. I would recommend creating a #Service method that iterated through your repositories and applied the updates. I will provide two approaches below.
Example 1)
#Service
public class UpdateRepositories {
public void updateAllRepositories(LdapUserRepository userRepository1, LdapUserRepository userRepository2) {
// apply updates to userRepository1 and userRepository2
}
}
Example 2)
#Service
public class UpdateRepositories {
public void updateAllRepositories(ApplicationContext appContext) {
Map<String, LdapRepository> ldapRepositories = appContext.getBeansofType(LdapRepository.class)
// iterate through map and apply updates
}
}
I haven't compiled this code, so let me know if something is off or if you need additional guidance.
I don't known if I understood correctly but here is what we did:
Global configuration class
#Bean("odm")
public ObjectDirectoryMapper odm() {
return new DefaultObjectDirectoryMapper();
};
First LDAP configuration class
#Configuration
#PropertySource("classpath:ldap-one.properties")
public class LdapOneConfiguration {
#Autowired
Environment ldapProperties;
#Bean(name = "contextSourceOne")
public LdapContextSourceCustom contextSourceLdapOneTarget() {
LdapContextSourceCustom ldapContextSource = new LdapContextSourceCustom();
ldapContextSource.setUrl(ldapProperties.getProperty("ldap-one.url"));
ldapContextSource.setBase(ldapProperties.getProperty("ldap-one.base"));
ldapContextSource.setUserDn(ldapProperties.getProperty("ldap-one.userDn"));
ldapContextSource.setPassword(ldapProperties.getProperty("ldap-one.password"));
ldapContextSource.setKeyStoreFile(ldapProperties.getProperty("ldap-one.truststore"));
return ldapContextSource;
}
#Bean(name = "ldapTemplateOne")
public LdapTemplate ldapOneTemplate(#Qualifier("contextSourceOne") LdapContextSourceCustom contextSource) {
return new LdapTemplate(contextSource);
}
#Bean(name = "ldapUserRepoOne")
public LdapUserRepository ldapUserRepositoryOne(#Qualifier("ldapTemplateOne") LdapTemplate ldapTemplate,
#Qualifier("odm") ObjectDirectoryMapper odm) {
return new LdapUserRepository(ldapTemplate, odm);
}
#Bean(name = "ldapFamilyRepoOne")
public LdapFamilyRepository ldapFamilyRepositoryOne(#Qualifier("ldapTemplateOne") LdapTemplate ldapTemplate,
#Qualifier("odm") ObjectDirectoryMapper odm) {
return new LdapFamilyRepository(ldapTemplate, odm);
}
}
Second LDAP configuration class
#Configuration
#PropertySource("classpath:ldap-two.properties")
public class LdapTwoConfiguration {
#Autowired
Environment ldapProperties;
#Bean(name = "contextSourceTwo")
public LdapContextSourceCustom contextSourceLdapTwoTarget() {
LdapContextSourceCustom ldapContextSource = new LdapContextSourceCustom();
ldapContextSource.setUrl(ldapProperties.getProperty("ldap-two.url"));
ldapContextSource.setBase(ldapProperties.getProperty("ldap-two.base"));
ldapContextSource.setUserDn(ldapProperties.getProperty("ldap-two.userDn"));
ldapContextSource.setPassword(ldapProperties.getProperty("ldap-two.password"));
ldapContextSource.setKeyStoreFile(ldapProperties.getProperty("ldap-two.truststore"));
return ldapContextSource;
}
#Bean(name = "ldapTemplateTwo")
public LdapTemplate ldapTwoTemplate(#Qualifier("contextSourceTwo") LdapContextSourceCustom contextSource) {
return new LdapTemplate(contextSource);
}
#Bean(name = "ldapUserRepoTwo")
public LdapUserRepository ldapUserRepositoryTwo(#Qualifier("ldapTemplateTwo") LdapTemplate ldapTemplate,
#Qualifier("odm") ObjectDirectoryMapper odm) {
return new LdapUserRepository(ldapTemplate, odm);
}
#Bean(name = "ldapFamilyRepoTwo")
public LdapFamilyRepository ldapFamilyRepositoryTwo(#Qualifier("ldapTemplateTwo") LdapTemplate ldapTemplate,
#Qualifier("odm") ObjectDirectoryMapper odm) {
return new LdapFamilyRepository(ldapTemplate, odm);
}
}
LdapUser repository
public class LdapUserRepository extends SimpleLdapRepository<LdapUser> {
public LdapUserRepository(LdapOperations ldapOperations, ObjectDirectoryMapper odm) {
super(ldapOperations, odm, LdapUser.class);
}
}
LdapFamily repository
public class LdapFamilyRepository extends SimpleLdapRepository<LdapFamily> {
public LdapFamilyRepository(LdapOperations ldapOperations, ObjectDirectoryMapper odm) {
super(ldapOperations, odm, LdapFamily.class);
}
}
LdapUser service (same for LdapFamily service)
#Service
public class LdapUserServiceImpl implements LdapUserService {
#Autowired
private ApplicationContext appContext;
private LdapUserRepository uniqueLdapUserRepo;
private List<LdapUserRepository> ldapUserRepoList;
#PostConstruct
private void setUniqueRepo() {
uniqueLdapUserRepo = appContext.getBeansOfType(LdapUserRepository.class).values().iterator().next();
ldapUserRepoList = new ArrayList<>(appContext.getBeansOfType(LdapUserRepository.class).values());
}
#Override
public LdapUser getUser(String uid) {
return uniqueLdapUserRepo.findOne(query().where("uid").is(uid));
}
#Override
public void saveUser(LdapUser user) {
for(LdapUserRepository repo: ldapUserRepoList){
repo.save(user);
}
}
}
We deleted the auto configuration of LDAP repo:
#EnableLdapRepositories(basePackages = "com.afklm.paul.repository.ldap", ldapTemplateRef = "ldapTwoTemplate")
Thanks ryan2049 for your help.
there is actually an easier way now:
create multiple configuration that is anotated with #EnableLdapRepositories with corresponding attributes
Create first configuration
#Configuration
#EnableLdapRepositories(basePackages = "first.ldap.package.repository.**", ldapTemplateRef = "firstLdapTemplate")
public class FirstLDAPConfig {
....detail
#Bean("firstLdapTemplate")
public LdapTemplate firstLdapTemplate() {
...template creation
}
}
Create second configuration
#Configuration
#EnableLdapRepositories(basePackages = "second.ldap.package.repository.**", ldapTemplateRef = "secondLdapTemplate")
public class SecondLDAPConfig {
....detail
#Bean("secondLdapTemplate")
public LdapTemplate secondLdapTemplate() {
...template creation
}
}
each configuration should handle it's own contextSource
then only the specified repository within the EnableLdapRepositories annotation will use that specific ContextSource and LdapTemplate

Integrate my app with Activiti

I have one issue. I integrate my app with Activiti (in the same DB). When I insert, update or delete my entities (not entities's Activiti) by Dao class have use #Transactional but nothing about is being saved to database with no exception.
Here is my config to integrating:
#Configuration
public class ActivitiEngineConfiguration {
private final Logger log = LoggerFactory.getLogger(ActivitiEngineConfiguration.class);
#Autowired
protected Environment environment;
#Bean
public DataSource dataSource() {
SimpleDriverDataSource ds = new SimpleDriverDataSource();
try {
#SuppressWarnings("unchecked")
Class<? extends Driver> driverClass = (Class<? extends Driver>) Class.forName(environment.getProperty("jdbc.driver", "org.postgresql.Driver"));
ds.setDriverClass(driverClass);
} catch (Exception e) {
log.error("Error loading driver class", e);
}
ds.setUrl(environment.getProperty("spring.datasource.url"));
ds.setUsername(environment.getProperty("spring.datasource.username"));
ds.setPassword(environment.getProperty("spring.datasource.password"));
return ds;
}
#Bean(name = "transactionManager")
public PlatformTransactionManager annotationDrivenTransactionManager() {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource());
System.out.println("transactionManager: "+transactionManager);
return transactionManager;
}
#Bean(name="processEngineFactoryBean")
public ProcessEngineFactoryBean processEngineFactoryBean() {
ProcessEngineFactoryBean factoryBean = new ProcessEngineFactoryBean();
factoryBean.setProcessEngineConfiguration(processEngineConfiguration());
return factoryBean;
}
#Bean(name="processEngine")
public ProcessEngine processEngine() {
// Safe to call the getObject() on the #Bean annotated processEngineFactoryBean(), will be
// the fully initialized object instanced from the factory and will NOT be created more than once
try {
return processEngineFactoryBean().getObject();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
#Bean(name="processEngineConfiguration")
public ProcessEngineConfigurationImpl processEngineConfiguration() {
SpringProcessEngineConfiguration processEngineConfiguration = new SpringProcessEngineConfiguration();
processEngineConfiguration.setDataSource(dataSource());
processEngineConfiguration.setDatabaseSchemaUpdate(environment.getProperty("engine.schema.update", "true"));
processEngineConfiguration.setTransactionManager(annotationDrivenTransactionManager());
processEngineConfiguration.setJobExecutorActivate(Boolean.valueOf(
environment.getProperty("engine.activate.jobexecutor", "false")));
processEngineConfiguration.setAsyncExecutorEnabled(Boolean.valueOf(
environment.getProperty("engine.asyncexecutor.enabled", "true")));
processEngineConfiguration.setAsyncExecutorActivate(Boolean.valueOf(
environment.getProperty("engine.asyncexecutor.activate", "true")));
processEngineConfiguration.setHistory(environment.getProperty("engine.history.level", "full"));
String mailEnabled = environment.getProperty("engine.email.enabled");
if ("true".equals(mailEnabled)) {
processEngineConfiguration.setMailServerHost(environment.getProperty("engine.email.host"));
int emailPort = 1025;
String emailPortProperty = environment.getProperty("engine.email.port");
if (StringUtils.isNotEmpty(emailPortProperty)) {
emailPort = Integer.valueOf(emailPortProperty);
}
processEngineConfiguration.setMailServerPort(emailPort);
String emailUsernameProperty = environment.getProperty("engine.email.username");
if (StringUtils.isNotEmpty(emailUsernameProperty)) {
processEngineConfiguration.setMailServerUsername(emailUsernameProperty);
}
String emailPasswordProperty = environment.getProperty("engine.email.password");
if (StringUtils.isNotEmpty(emailPasswordProperty)) {
processEngineConfiguration.setMailServerPassword(emailPasswordProperty);
}
}
// List<AbstractFormType> formTypes = new ArrayList<AbstractFormType>();
// formTypes.add(new UserFormType());
// formTypes.add(new ProcessDefinitionFormType());
// formTypes.add(new MonthFormType());
// processEngineConfiguration.setCustomFormTypes(formTypes);
return processEngineConfiguration;
}
#Bean
public RepositoryService repositoryService() {
return processEngine().getRepositoryService();
}
#Bean
public RuntimeService runtimeService() {
return processEngine().getRuntimeService();
}
#Bean
public TaskService taskService() {
return processEngine().getTaskService();
}
#Bean
public HistoryService historyService() {
return processEngine().getHistoryService();
}
#Bean
public FormService formService() {
return processEngine().getFormService();
}
#Bean
public IdentityService identityService() {
return processEngine().getIdentityService();
}
#Bean
public ManagementService managementService() {
return processEngine().getManagementService();
}
}
DAO Layer:
#Autowired
private SessionFactory sessionFactory;
#Override
#Transactional
public void save(MyEntity obj) {
sessionFactory.getCurrentSession().saveOrUpdate(loaiDanhMuc);
}
Thank all!
I guess #Transactional is not working in this case
Please check following things below:
Check if <tx:annotation-driven /> is defined in your spring xml file.

Use camel component in route specified in spring configuration

I have the following sftp camel component configuration:
#Configuration
public class FtpCamelComponent {
#Value("${SFTP_HOST}")
private String sftpHost;
#Value("${SFTP_KNOWNHOST}")
private String sftpKnownHost;
#Value("${SFTP_KEY}")
private String sftpKey;
#Value("${SFTP_USER}")
private String sftpUser;
#Value("{SFTP_DIRECTORY}")
private String sftpFileDirectory;
#Bean
public SftpConfiguration sftpConfiguration(){
SftpConfiguration sftpConfiguration = new SftpConfiguration();
sftpConfiguration.setUsername(sftpUser);
sftpConfiguration.setHost(sftpHost);
sftpConfiguration.setKnownHostsFile(sftpKnownHost);
sftpConfiguration.setPrivateKeyFile(sftpKey);
sftpConfiguration.setDirectory(sftpFileDirectory);
return sftpConfiguration;
}
#Bean
public SftpEndpoint sftpEndpoint(SftpConfiguration sftpConfiguration){
SftpEndpoint sftpEndpoint = new SftpEndpoint();
sftpEndpoint.setConfiguration(sftpConfiguration);
sftpEndpoint.setEndpointUriIfNotSpecified("sftp");
return sftpEndpoint;
}
#Bean
public SftpComponent sftpComponent(SftpEndpoint sftpEndpoint){
SftpComponent sftpComponent = new SftpComponent();
sftpComponent.setEndpointClass(sftpEndpoint.getClass());
return sftpComponent;
}
}
I added the component to my camel context:
#Configuration
#Import({FtpCamelComponent.class,
SftpCamelRoute.class})
public class SftpCamelContext extends CamelConfiguration {
#Autowired
SftpComponent sftpComponent;
#Bean(name = "sftpCamelContext")
protected CamelContext createCamelContext() throws Exception {
SpringCamelContext camelContext = new SpringCamelContext();
camelContext.setApplicationContext(getApplicationContext());
camelContext.addComponent("sftp", sftpComponent);
return camelContext;
}
}
Why can't I just use sftp: in my camel route as I have already configured it and added it to my camel context?
#Bean(name = "FileToSftp")
public RouteBuilder fileToSFTP(){
return new RouteBuilder() {
public void configure() {
from("direct:fileToSftp")
.to("file:export/b1?fileName=export.csv")
.setHeader("CamelFileName", constant("export.csv"))
.to("sftp://dev#localhost:/export/in/?knownHostsFile=key/knownhost&privateKeyFile=key/id_rsa.pub&localWorkDirectory=export/b1&download=false");
}
};
}

Resources