Wicket, Spring 4 und Hibernate 5
Wie man Spring 4 und Hibernate 5 einfach in Wicket integriert. Minimaler Setup und Konfiguration.
Nachdem es im Netz mehrere Resourcen zum Thema Spring und Hibernate Integration in Apache Wicket gibt, und diese Anleitungen sich auf teils veraltete Spring und Hibernate Versionen beziehen, gebe ich für eine aktuelle Kombination mit Spring 4, Hibernate 6 und Wicket 6 eine Anleitung zum einfachen Setup. Nur mit Bibliotheken, die in jedem Fall gebraucht werden. Konfigurationen über Annotations und eine Properties Datei für die Datenbank-Verbindung.
Bibliotheken
Die folgenden Bibliotheken braucht man zwingend, um den Technologie-Stack Wicket, Spring, Hibernate mit aktuellen Bibliotheken zu realisieren.
Beispielhaft wird MySQL als Datenbank und Maven als Build-System verwendet.
Wicket 6
- wicket-spring
Spring 4
- spring-core
- spring-context
- spring-orm
- spring-tx
Hibernate 5
- hibernate-core
- hibernate-entitymanager
3rd Party
- commons-dbcp
- javax.transaction / jta
- mysql-connector
Maven POM
<properties>
<!-- Wicket -->
<wicket.version>6.21.0</wicket.version>
<!-- Spring framework -->
<springframework.version>4.2.3.RELEASE</springframework.version>
<!-- Persistence -->
<mysql.connector.version>5.1.37</mysql.connector.version>
<!-- Hibernate -->
<hibernate.version>5.0.4.Final</hibernate.version>
</properties>
<dependencies>
<!-- Wicket -->
<dependency>
<groupId>org.apache.wicket</groupId>
<artifactId>wicket-core</artifactId>
<version>${wicket.version}</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.apache.wicket</groupId>
<artifactId>wicket-spring</artifactId>
<version>${wicket.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- Spring ORM -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${springframework.version}</version>
</dependency>
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<!-- DB connection pool -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!-- JTA -->
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.version}</version>
</dependency>
</dependencies>
Wicket Integration
Die Wicket Integration besteht aus Anpassung der WebApplication und dem Schreiben einer Spring Konfiguration.
WicketApplication
Jede Applikation überschreibt die Klasse WebApplication, dabei fügt man Folgendes ein:
public class WicketSpringHibernateApplication extends WebApplication {
/**
* @see org.apache.wicket.Application#getHomePage()
*/
@Override
public Class<? extends WebPage> getHomePage() {
return HomePage.class;
}
@Override
public void init() {
super.init();
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(WicketSpringHibernateApplicationConfiguration.class);
ctx.refresh();
getComponentInstantiationListeners().add(new SpringComponentInjector(this, ctx));
}
}
WicketApplicationConfiguration
Die oben referenzierte Instanz von WicketApplicationConfiguration ersetzt frühere XML-Konfigurationen von Spring und Hibernate sowie Eingriffe in die web.xml. Einzig und allein die Attribute der JDBC-Verbindung werden aus Properties ausgelesen.
@Configuration
@ComponentScan(basePackages = { "de.it72.repository", "de.it72.service" })
@EnableTransactionManagement
@PropertySource(value = { "classpath:application.properties" })
public class WicketSpringHibernateApplicationConfiguration {
@Autowired
private Environment environment;
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "de.it72.domain" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
return properties;
}
@Bean
@Autowired
public HibernateTransactionManager transactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s); return txManager;
}
}
JDBC Properties-Datei
application.properties packt man in src/main/resources:
jdbc.driverClassName = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://${server_name}:${port}/${db_name}
jdbc.username = <user_name>
jdbc.password = <password>
jdbc.showSql=true
jdbc.generateDDL=fals
# Hibernate
hibernate.dialect = org.hibernate.dialect.MySQLDialect
hibernate.show_sql = true
hibernate.format_sql = false
jdbc.driverClassName = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://${server_name}:${port}/${db_name}
jdbc.username = <user_name>
jdbc.password = <password>
jdbc.showSql=true
jdbc.generateDDL=false
# Hibernate
hibernate.dialect = org.hibernate.dialect.MySQLDialect
hibernate.show_sql = true
hibernate.format_sql = false
Die Platzhalter ersetzt man durch die definierten Werte der Datenbankverbindung. Wenn der Datenbankserver gleich dem Applikationsserver ist. wird ${server_name}=localhost gelten.
Hibernate Repository – Spring Service Bean
An einem Beispiel soll nun gezeigt werden wie man Hibernate und Spring anwendet. Über die Annotationen @Repository und @Service findet Spring mit der obigen Konfiguration in @ComponentScan die bereitgestellten Klassen
Hibernate Repository
So könnte ein Hibernate Repository aussehen, im Beispiel Package de.it72.repository:
Schnittstelle
/**
* Repository Interface zu {@link User}
*
*/
public interface UserRepository extends HibernateRepository<User, Long> {
User loadByUserName(String userName);
}
Repository Bean
Die Repository Bean mit der @Repository Annotation.
/**
* Repository-Implementierung
*/
@Repository
public class UserRepositoryImpl extends HibernateDao<User, Long> implements UserRepository {
/** * JPQL Query oder Criteria API */
@Override
public User loadByUserName(String userName) {
List<User> list = getSession()...
return list;
}
Spring Bean
Die Spring Bean wird in der Schnittstelle deklariert und in der Bean implementiert.
Service Schnittstelle
Im Beispiel Package de.it72.service definiert man folgende Schnittstelle:
/**
* Service zu {@link User}
*/
public interface UserService extends UserRepository {
User loadByUserName(String userName);
}
Service Bean
Schließlich die Service Bean, im Beispiel Package de.it72.service, mit der @Service Annotation.
@Transactional für Transaktionsunterstützung.
/**
* Service Implementierung
*
*/
@Service
@Transactional
public class UserServiceImpl implements UserService {
@Autowired private UserRepository repository;
@Override public User loadByUserName(String userName) {
return repository.loadByUserName(userName);
}
}
Einbindung in Wicket WebPage
Der UserService kann nun über die Annotation @SpringBean in Wicket Komponenten injiziert werden, voilá!
/**
* Webseite - Home Page
*/
public class HomePage extends WebPage {
@SpringBean private UserService userService;
public HomePage(final PageParameters parameters) {
super(parameters);
add(new Label("user", userService.loadByUserName("it72")));
}
}