Jhipster Multi-tenancy with Hibernate Second Level Caching - java

I've been attempting to turn my JHipster generated application into a multi-tenancy app using this - http://jannatconsulting.com/blog/?p=41 blog post as a base.
I've run into a problem with second level caching. Spring boot appears to correctly detect and set up:
DatabaseConfiguration.java
#Configuration
#EnableConfigurationProperties(JpaProperties.class)
#EnableJpaRepositories(
entityManagerFactoryRef = "masterEntityManager",
transactionManagerRef = "masterTransactionManager",
basePackages = {"com.quadrimular.nts.helium.repository.master"})
#EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
#EnableTransactionManagement
#EnableElasticsearchRepositories("com.quadrimular.nts.helium.repository.search")
public class DatabaseConfiguration {
#Inject
private Environment env;
#Autowired(required = false)
private MetricRegistry metricRegistry;
#Inject
private DataSourceProperties datasourceProperties;
#Inject
private JHipsterProperties jhipsterProperties;
#Inject
private JpaProperties jpaProperties;
#Inject
private DataSource dataSource;
#Bean(destroyMethod = "close")
#ConditionalOnExpression("#{!environment.acceptsProfiles('cloud') && !environment.acceptsProfiles('heroku')}")
public DataSource dataSource(DataSourceProperties dataSourceProperties, JHipsterProperties jHipsterProperties) {
log.debug("Configuring Master Datasource");
if (dataSourceProperties.getUrl() == null) {
log.error("Your database connection pool configuration is incorrect! The application" +
" cannot start. Please check your Spring profile, current profiles are: {}",
Arrays.toString(env.getActiveProfiles()));
throw new ApplicationContextException("Database connection pool is not configured correctly");
}
HikariConfig config = new HikariConfig();
config.setDataSourceClassName(dataSourceProperties.getDriverClassName());
config.addDataSourceProperty("url", dataSourceProperties.getUrl());
if (dataSourceProperties.getUsername() != null) {
config.addDataSourceProperty("user", dataSourceProperties.getUsername());
} else {
config.addDataSourceProperty("user", ""); // HikariCP doesn't allow null user
}
if (dataSourceProperties.getPassword() != null) {
config.addDataSourceProperty("password", dataSourceProperties.getPassword());
} else {
config.addDataSourceProperty("password", ""); // HikariCP doesn't allow null password
}
//MySQL optimizations, see https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration
if ("com.mysql.jdbc.jdbc2.optional.MysqlDataSource".equals(dataSourceProperties.getDriverClassName())) {
config.addDataSourceProperty("cachePrepStmts", jHipsterProperties.getDatasource().isCachePrepStmts());
config.addDataSourceProperty("prepStmtCacheSize", jHipsterProperties.getDatasource().getPrepStmtCacheSize());
config.addDataSourceProperty("prepStmtCacheSqlLimit", jHipsterProperties.getDatasource().getPrepStmtCacheSqlLimit());
}
if (metricRegistry != null) {
config.setMetricRegistry(metricRegistry);
}
return new HikariDataSource(config);
}
#Bean(name = "masterEntityManager")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(){
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource(datasourceProperties, jhipsterProperties));
em.setPackagesToScan(new String[]{"com.quadrimular.nts.helium.domain.master"});
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalJpaProperties());
em.setPersistenceUnitName("master");
return em;
}
private Properties additionalJpaProperties() {
Properties properties = new Properties();
for (Map.Entry<String, String> entry : jpaProperties.getHibernateProperties(dataSource).entrySet()) {
properties.setProperty(entry.getKey(), entry.getValue());
}
return properties;
}
#Bean(name = "masterTransactionManager")
public JpaTransactionManager transactionManager(EntityManagerFactory masterEntityManager){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(masterEntityManager);
return transactionManager;
}
}
When spring tries to configure:
MultiTenancyJPAConfiguration.java
#Configuration
#EnableConfigurationProperties(JpaProperties.class)
#EnableJpaRepositories(
entityManagerFactoryRef = "tenantEntityManager",
transactionManagerRef = "tenantTransactionManager",
basePackages = {"com.quadrimular.nts.helium.repository.tenant"})
#EnableTransactionManagement
public class MultiTenancyJpaConfiguration {
#Bean(name = "tenantEntityManager")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
MultiTenantConnectionProvider connectionProvider,
CurrentTenantIdentifierResolver tenantResolver) {
LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean();
emfBean.setDataSource(dataSource);
emfBean.setPackagesToScan("com.quadrimular.nts.helium.domain.tenant");
emfBean.setJpaVendorAdapter(jpaVendorAdapter());
Map<String, Object> properties = new HashMap<>();
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT, MultiTenancyStrategy.DATABASE);
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_CONNECTION_PROVIDER, connectionProvider);
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, tenantResolver);
properties.put("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy");
emfBean.setJpaPropertyMap(properties);
return emfBean;
}
#Bean(name = "tenantTransactionManager")
public JpaTransactionManager transactionManager(EntityManagerFactory tenantEntityManager){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(tenantEntityManager);
return transactionManager;
}
}
I'm getting this in my trace:
Caused by: org.hibernate.cache.NoCacheRegionFactoryAvailableException: Second-level cache is used in the application, but property hibernate.cache.region.factory_class is not given; please either disable second level cache or set correct region factory using the hibernate.cache.region.factory_class setting and make sure the second level cache provider (hibernate-infinispan, e.g.) is available on the classpath.
I have all the required properties defined in my application-dev.yml
hibernate.cache.use_second_level_cache: true
hibernate.cache.use_query_cache: false
hibernate.generate_statistics: true
hibernate.cache.region.factory_class: org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
It appears that it's being read and used correctly by spring boot for my DatabaseConfiguration.java. I can't work out why it's not detecting the property file. If I try to disable the cache by setting:
hibernate.cache.use_second_level_cache: false
DatabaseConfiguration.java detects and behaves accordingly however MultiTenancyJPAConfiguration.java still throws the same exception.
Am I missing something obvious?

The answer is to actually set the jpa property values on the entity manager. I'm not sure how I overlooked this; I thought that somehow they were already set.
Firstly I injected the main datasource and the jpa properties object provided by spring boot if I'm not mistaken.
MultiTenancyJPAConfiguration.java
#Inject
private JpaProperties jpaProperties;
#Inject
private DataSource dataSource;
I then set the values using the same method used in DatabaseConfiguration.java
MultiTenancyJPAConfiguration.java
#Bean(name = "tenantEntityManager")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
MultiTenantConnectionProvider connectionProvider,
CurrentTenantIdentifierResolver tenantResolver) {
LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean();
emfBean.setDataSource(dataSource);
emfBean.setPackagesToScan("com.quadrimular.nts.helium.domain.tenant");
emfBean.setJpaVendorAdapter(jpaVendorAdapter());
Map<String, Object> properties = new HashMap<>();
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT, MultiTenancyStrategy.DATABASE);
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_CONNECTION_PROVIDER, connectionProvider);
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, tenantResolver);
properties.put("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy");
emfBean.setJpaPropertyMap(properties);
emfBean.setJpaProperties(additionalJpaProperties());
return emfBean;
}
private Properties additionalJpaProperties() {
Properties properties = new Properties();
for (Map.Entry<String, String> entry : jpaProperties.getHibernateProperties(dataSource).entrySet()) {
properties.setProperty(entry.getKey(), entry.getValue());
}
return properties;
}
Using the method additionalJpaProperties() to get all the hibernate jpa properties for my main datasource. I then set the hibernate property map properties after the hard coded ones. Clearly not the cleanest solution I plan to set all jpa values from the .yml file.

Related

Multiple database connection reusing entity mapping

We have a case where we connect to different databases environments, but the tables in each of the environment are the same.
Is there any way I can reuse the entity class for each of the environment?
I am using separate config class for each of the environment. Below is the config for one of the environment, similarly I have 4 others. The "packages" deduce which environment to connect to.
codejava
#Configuration
#EnableJpaRepositories(basePackages = {"packages"},
entityManagerFactoryRef = "OneEntityManager",
transactionManagerRef = "OneTransactionManager")
public class DevDataSourceConfig {
#Bean
#Primary
public LocalContainerEntityManagerFactoryBean OneEntityManager() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(OneDataSource());
em.setPackagesToScan(String[]{"packages"});
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
properties.put("hibernate.dialect", env.getProperty("hibernate.dialect"));
em.setJpaPropertyMap(properties);
return em;
}
#Primary
#Bean
public DataSource OneDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(driverclass);
dataSource.setUrl(url);
dataSource.setUsername(uName);
dataSource.setPassword(dbPass);
return dataSource;
}
#Primary
#Bean
public PlatformTransactionManager OneTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(OneEntityManager().getObject());
return transactionManager;
}
}

setting more than one transaction manager in spring jpa 2.1 error

I get this error:
***************************
APPLICATION FAILED TO START
***************************
Description:
Method DbEntityManagerFactoryS2 in xxx.xxx.entities.DbAutoConfigurationS2 required a single bean, but 2 were found:
- dataSourceS2: defined by method 'dataSourceS2' in class path resource [xx/xx/entities/DbAutoConfigurationS2.class]
- dataSourcevb: defined by method 'dataSourcevb' in class path resource [xx/xx/entities/DbAutoConfigurationVB.class]
Action:
Consider marking one of the beans as #Primary, updating the consumer to accept multiple beans, or using #Qualifier to identify the bean that should be consumed
This is the java spring classes:
#Configuration
#ComponentScan
#EnableJpaRepositories(entityManagerFactoryRef = "DbEntityManagerFactoryS2",
transactionManagerRef = "DbTransactionManagerS2")
#PropertySource("classpath:db-config.properties")
public class DbAutoConfigurationS2 {
static final Logger logger = LoggerFactory.getLogger(DbAutoConfigurationS2.class);
#Value("${spring.jpa.hibernate.ddl-auto}")
String ddlauto;
#Value("${spring.jpa.show-sql}")
Boolean showsql;
#Value("${spring.jpa.hibernate.naming_strategy}")
String dbstrategy;
public DbAutoConfigurationS2() {
}
/**
* CMP ( content management persist. - wrappare il metodo sotto transazione con # Transactional )
* #return
*/
#Bean
PlatformTransactionManager DbTransactionManagerS2() {
return new JpaTransactionManager(DbEntityManagerFactoryS2().getObject());
}
#Bean
LocalContainerEntityManagerFactoryBean DbEntityManagerFactoryS2() {
logger.info("DbEntityManagerFactoryS2 enter ");
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
//jpaVendorAdapter.setGenerateDdl(true);
jpaVendorAdapter.setShowSql(showsql);
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSourceS2());
factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
factoryBean.setPackagesToScan(DbAutoConfigurationVB.class.getPackage().getName());
//override di alcune proprietà specificate nel db-config.properties
Properties props = new Properties();
Map<String, Object> map = factoryBean.getJpaPropertyMap();
map.put("hibernate.hbm2ddl.auto", ddlauto.trim().toString());
map.put("org.hibernate.cfg.ImprovedNamingStrategy", dbstrategy.trim().toString());
props.putAll(map);
factoryBean.setJpaProperties(props);
return factoryBean;
}
#Bean
#ConfigurationProperties(prefix = "spring.datasourceS2")
public DataSource dataSourceS2(){
logger.info("datasource S2 enter ");
//DataSource ds =new EmbeddedDatabaseBuilder().addScript("classpath:sql/schema.sql").addScript("classpath:testdb/data.sql").build();
DataSourceBuilder ds = DataSourceBuilder.create();
logger.info("dataSource S2 = " + ds);
return ds.build();
}
I have another TRansaction manager because i must deal with More than one database..
#Configuration
#ComponentScan
#EnableJpaRepositories(entityManagerFactoryRef = "DbEntityManagerFactoryVB",
transactionManagerRef = "DbTransactionManagerVB")
#PropertySource("classpath:db-config.properties")
public class DbAutoConfigurationVB {
static final Logger logger = LoggerFactory.getLogger(DbAutoConfigurationVB.class);
#Value("${spring.jpa.hibernate.ddl-auto}")
String ddlauto;
#Value("${spring.jpa.show-sql}")
Boolean showsql;
#Value("${spring.jpa.hibernate.naming_strategy}")
String dbstrategy;
public DbAutoConfigurationVB() {
}
/**
* CMP ( content management persist. - wrappare il metodo sotto transazione con # Transactional )
* #return
*/
#Bean
#Primary
PlatformTransactionManager DbTransactionManagerVB() {
return new JpaTransactionManager(DbEntityManagerFactoryVB().getObject());
}
#Bean
#Primary
LocalContainerEntityManagerFactoryBean DbEntityManagerFactoryVB() {
logger.info("DbEntityManagerFactoryVB enter ");
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
//jpaVendorAdapter.setGenerateDdl(true);
jpaVendorAdapter.setShowSql(showsql);
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSourcevb());
factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
factoryBean.setPackagesToScan(DbAutoConfigurationVB.class.getPackage().getName());
//override di alcune proprietà specificate nel db-config.properties
Properties props = new Properties();
Map<String, Object> map = factoryBean.getJpaPropertyMap();
map.put("hibernate.hbm2ddl.auto", ddlauto.trim().toString());
map.put("org.hibernate.cfg.ImprovedNamingStrategy", dbstrategy.trim().toString());
props.putAll(map);
factoryBean.setJpaProperties(props);
return factoryBean;
}
#Bean
#ConfigurationProperties(prefix = "spring.datasourceVB")
public DataSource dataSourcevb(){
logger.info("datasource enter ");
//DataSource ds =new EmbeddedDatabaseBuilder().addScript("classpath:sql/schema.sql").addScript("classpath:testdb/data.sql").build();
DataSourceBuilder ds = DataSourceBuilder.create();
logger.info("dataSource = " + ds);
return ds.build();
}
}
So i have to wrap method with
#Transactional(propagation = Propagation.REQUIRED , transactionManager="DbTransactionManagerS2")
or
#Transactional(propagation = Propagation.REQUIRED , transactionManager="DbTransactionManagerVB")
Why doesn't it work?
I set factoryBean.setDataSource(dataSource_bean_name()) but still the same...
If i marked all methods in bAutoConfigurationVB class with #Primary, the error disappear but transactionManagerVb only works and db target still the same, not the exactly one selected by the right datasource method..
Isn't the right way?
thanks
Roberto

How to connect to multiple databases Spring Boot JPA?

I am trying to model it off of this example https://github.com/spring-projects/spring-data-examples/tree/master/jpa/multiple-datasources but they dont seem to be using a properties file, which is confusing me. How do they input the database name, log in info, and url? The way I currently have it is like this:
This is my config file for one of my databases: LM_Config.java
#Configuration
#EnableJpaRepositories(entityManagerFactoryRef = "lmEntityManagerFactory",
transactionManagerRef = "lmTransactionManager")
class LM_Config {
#Bean
PlatformTransactionManager lmTransactionManager() {
return new JpaTransactionManager(lmEntityManagerFactory().getObject());
}
#Bean
LocalContainerEntityManagerFactoryBean lmEntityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(lmDataSource());
factoryBean.setJpaVendorAdapter(vendorAdapter);
factoryBean.setPackagesToScan(LM_Config.class.getPackage().getName());
return factoryBean;
}
#Bean
#Primary
#ConfigurationProperties(prefix="spring.datasource")
public DataSource lmDataSource() {
return DataSourceBuilder.create().build();
}
}
This is my config file for one of my databases: MTS_Config.java
#Configuration
#EnableJpaRepositories(entityManagerFactoryRef = "mtsEntityManagerFactory",
transactionManagerRef = "mtsTransactionManager")
class MTS_Config {
#Bean
PlatformTransactionManager mtsTransactionManager() {
return new JpaTransactionManager(mtsEntityManagerFactory().getObject());
}
#Bean
LocalContainerEntityManagerFactoryBean mtsEntityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(mtsDataSource());
factoryBean.setJpaVendorAdapter(vendorAdapter);
factoryBean.setPackagesToScan(MTS_Config.class.getPackage().getName());
return factoryBean;
}
#Bean
#Primary
#ConfigurationProperties(prefix="spring.mtsDatasource")
public DataSource mtsDataSource() {
return DataSourceBuilder.create().build();
}
}
This is my application.properties file. The main points of interest should be the ones starting in spring.datasource... and spring.mtsDatasource...
hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.default_schema=dbo
hibernate.packagesToScan=src.repositories.LMClientRepository.java
spring.jpa.generate-ddl=true
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.DefaultNamingStrategy
spring.datasource.username=LOADdev
spring.datasource.password=lmtdev01
spring.datasource.url=jdbc:sqlserver://schqvsqlaod:1433;database=dbMOBClientTemp;integratedSecurity=false;
spring.datasource.testOnBorrow=true
spring.datasource.validationQuery=SELECT 1
spring.jpa.database=dbMOBClientTemp
spring.jpa.show-sql=true
spring.jpa.hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect
spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
#spring.jpa.hibernate.ddl-auto=none
#spring.jpa.hibernate.ddl-auto=none
#spring.jpa.properties.hibernate.hbm2ddl.auto=none
spring.mtsDatasource.username=mtsj
spring.mtsDatasource.password=mtsjapps
spring.mtsDatasource.url=jdbc:sqlserver://SCHQVSQLCON2\VSPD:1433;database=dbMTS;integratedSecurity=false;
spring.mtsDatasource.testOnBorrow=true
spring.mtsDatasource.validationQuery=SELECT 1
they dont seem to be using a properties file, which is confusing me. How do they input the database name, log in info, and url?
The answer to this is that the example is using an embedded database, so there is no DB name, username, etc..
For your main question, review the similar questions in the sidebar, look at the documentation for #Qualifier, and come back with a more specific question.

Set hibernate.ddl-auto in springboot programmatically

I use springboot in a non web application and data jpa. I use the default configuration except for datasource:
private static final String dataSourceUrl = "jdbc:h2:./Database;DB_CLOSE_ON_EXIT=FALSE";
#Bean
public DataSource dataSource() {
return DataSourceBuilder.create().url(dataSourceUrl).username("user").password("pwd").build();
}
How can I set the spring.jpa.hibernate.ddl-auto property also programmatically?
Adding the following bean seems to do the job (thanks to Jens' comment):
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan(new String[] { "packages.to.scan" });
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
properties.setProperty("hibernate.hbm2ddl.auto", "update");
em.setJpaProperties(properties);
return em;
}

Play Framework evolutions not working with Spring/Hibernate

I am using java-play-spring template (obtainable here: https://github.com/jamesward/play-java-spring#master )and currently I am trying to write some evolutions for it.
I am putting my script:
# --- !Ups
CREATE TABLE accounts
(
accountid INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
clientid INT NOT NULL,
credit DECIMAL(13,2)
);
# --- !Downs
drop table accounts;
into conf/evolutions/default/1.sql. Unfortunatelly, after application starts, nothing happens. I suppose that it may be Spring/Hibernate fault, so i disabled Hibernate validation:
#Configuration
#EnableTransactionManagement
public class DataConfig {
#Bean
public EntityManagerFactory entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setShowSql(true);
vendorAdapter.setGenerateDdl(false);
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setPackagesToScan("models");
entityManagerFactory.setJpaVendorAdapter(vendorAdapter);
entityManagerFactory.setDataSource(dataSource());
entityManagerFactory.setValidationMode(ValidationMode.NONE);
entityManagerFactory.afterPropertiesSet();
return entityManagerFactory.getObject();
}
#Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager(entityManagerFactory());
return transactionManager;
}
#Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(Play.application().configuration().getString("db.default.driver"));
dataSource.setUrl(Play.application().configuration().getString("db.default.url"));
dataSource.setUsername(Play.application().configuration().getString("db.default.user"));
dataSource.setPassword(Play.application().configuration().getString("db.default.password"));
return dataSource;
}
}
But this didn't help. I have also added
play.modules.evolutions.enabled=true
To my application.conf. This does not help too.
Does anyone has any ideas what may be wrong?

Categories

Resources