JPA Inheritance entitymanager.find produces ClassCastException - java

I have a class hierarchy like this:
#Entity
#Table (name="call_distribution_policies")
#Inheritance (strategy=InheritanceType.JOINED)
public class CallDistributionPolicy implements Serializable, Cloneable{
----------------
}
#Entity
#Table(name="skill_based_call_distribution_policies")
public class SkillBasedCallDistributionPolicy extends CallDistributionPolicy {
--------------
}
public class CallDistributionPolicyDAOJPAImpl extends
AbstractJPADAOImpl<CallDistributionPolicy> implements
CallDistributionPolicyDAO {
}
public CallDistributionPolicy get(long id) {
try {
Query query = entityManager
.createQuery("from CallDistributionPolicy where id = :id");
query.setParameter("id", id);
List<CallDistributionPolicy> resultList = query.getResultList();
if (!CollectionUtils.isEmpty(resultList)) {
return resultList.get(0);
}
return null;
} catch (EntityNotFoundException e) {
return null;
}
}
}
When I do this:
log.debug(" loaded: " + callDistributionPolicyDao.get(10).toString())
It prints the toString() of the SkillsBasedCallDistributionPolicy
But when I try to cast it like this:
SkillsBasedCallDistributionPolicy scdp = (SkillsBasedCallDistributionPolicy) callDistributionPolicyDao.get(10)
I get class cast exception.
com.vantage.callcenter.core.entity.acd.CallDistributionPolicy$$EnhancerByCGLIB$$334f3d1b cannot be cast to com.vantage.callcenter.core.entity.acd.SkillBasedCallDistributionPolicy
The instanceof check fails too!
When I inspect the object in eclipse, I see the CGLIB Proxy, but as far as I understand, the CGLIB proxy should extend the SkillsBasedCallDistributionPolicy class? In the CGLIB$CALLBACK_0 property, I can see the entity class is "CallDistributionPolicy" but the target is "SkillsBasedCallDistributionPolicy".
What should be the proper process of loading the Subclass? I can see hibernate is generating all the right SQL and loading the proper subclass, but how can I check the instanceof and cast it into a subclass?
I am using hibernate 3.2.1 , Spring 2.5.5 , cglib2.1_3. Any suggestions?

I know that this has been a problem in Hibernate during a long time, see for example:
ClassCastException cglib lazy loading
JPA: instanceof vs. hibernate proxy: when is it safe?
How to Avoid ClassCastExceptions when using Hibernate Proxied Objects)
And by problem, I mean bug, instanceof and casting should just work.
But I couldn't reproduce your issue with Hibernate 3.3.0.SP1. Both instanceof and casting to subclasses of a hierarchy using a joined strategy just worked. Tested with:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-cglib-repack</artifactId>
<version>2.1_3</version>
</dependency>
and
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.8.0.GA</version>
</dependency>
I'm pretty sure there was a Jira issue for this, but couldn't find it.
The problem(bug) is consistent across my application. Can you post your working pom.xml here so I can see exactly what hibernate dependencies are you using?
Below the dependencies I used:
<project>
...
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.5.10</version>
</dependency>
</dependencies>
</dependencyManagement>
...
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.4.0.GA</version>
<exclusions>
<exclusion>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-cglib-repack</artifactId>
<version>2.1_3</version>
</dependency>
...
</dependencies>
</project>
Here is the dependency tree:
[INFO] +- org.hibernate:hibernate-entitymanager:jar:3.4.0.GA:compile
[INFO] | +- org.hibernate:ejb3-persistence:jar:1.0.2.GA:compile
[INFO] | +- org.hibernate:hibernate-commons-annotations:jar:3.1.0.GA:compile
[INFO] | +- org.hibernate:hibernate-annotations:jar:3.4.0.GA:compile
[INFO] | +- org.hibernate:hibernate-core:jar:3.3.0.SP1:compile
[INFO] | | +- antlr:antlr:jar:2.7.6:compile
[INFO] | | \- commons-collections:commons-collections:jar:3.1:compile
[INFO] | +- org.slf4j:slf4j-api:jar:1.5.10:compile
[INFO] | +- dom4j:dom4j:jar:1.6.1:compile
[INFO] | | \- xml-apis:xml-apis:jar:1.0.b2:compile
[INFO] | \- javax.transaction:jta:jar:1.1:compile
...
[INFO] \- org.hibernate:hibernate-cglib-repack:jar:2.1_3:compile

Related

java.lang.AbstractMethodError when calling Jersey Client.target

I am getting this error
java.lang.AbstractMethodError: Receiver class com.sun.jersey.api.uri.UriBuilderImpl does not define or inherit an implementation of the resolved method abstract uri(Ljava/lang/String;)Ljavax/ws/rs/core/UriBuilder; of abstract class javax.ws.rs.core.UriBuilder.
at javax.ws.rs.core.UriBuilder.fromUri(UriBuilder.java:96)
at org.glassfish.jersey.client.JerseyWebTarget.<init>(JerseyWebTarget.java:50)
at org.glassfish.jersey.client.JerseyClient.target(JerseyClient.java:274)
at org.glassfish.jersey.client.JerseyClient.target(JerseyClient.java:56)
...
when calling
client = ClientBuilder.newClient();
WebTarget url = client.target(someURL).path(somePath); // the error happens here !!!
Response response = url.request().get();
We use the jersey library.
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId>
<version>2.35</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.35</version>
</dependency>
Any ideas what could be causing this and how to fix?
We use JDK 11 to run this code.
I can see that from another dependency in the same project we're also pulling these:
[INFO] | | +- com.sun.jersey:jersey-core:jar:1.9:compile
[INFO] | | +- com.sun.jersey:jersey-json:jar:1.9:compile
[INFO] | | +- com.sun.jersey:jersey-server:jar:1.9:compile
I wonder if this could be some sort of clash between versions, or even something more subtle?! I currently have no idea. I don't find much info on the web too about this particular error.

Spring Retryable annotation ClassNotFoundException

I would like to use #Retryable annotation for restTemplate. I've added:
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.2.1.RELEASE</version>
</dependency>
as well as #EnableRetry to config class. I've marked method:
restTemplate.exchange(url, HttpMethod.POST, request, String.class);
with (in a new thread)
#Retryable(maxAttempts=4,value=Exception.class,backoff=#Backoff(delay = 2000))
But I'm getting error from catalina:
27-Oct-2017 18:11:41.023 SEVERE [http-nio-8080-exec-1] org.apache.catalina.core.StandardContext.listenerStart Exception sending context initialized event to listener instance of class [org.springframework.web.context.ContextLoaderListener]
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.aop.config.internalAutoProxyCreator': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/aspectj/lang/annotation/Around
at
<ommitted>
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: org/aspectj/lang/annotation/Around
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:154)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:89)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1103)
... 61 more
Caused by: java.lang.NoClassDefFoundError: org/aspectj/lang/annotation/Around
at org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.<clinit>(ReflectiveAspectJAdvisorFactory.java:76)
at org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator.<init>(AnnotationAwareAspectJAutoProxyCreator.java:53)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:142)
... 63 more
Caused by: java.lang.ClassNotFoundException: org.aspectj.lang.annotation.Around
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1285)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1119)
... 70 more
27-Oct-2017 18:11:41.038 INFO [http-nio-8080-exec-1] org.apache.catalina.core.ApplicationContext.log Closing Spring root WebApplicationContext
What I'm doing wrong ?
EDITED:
I moved a little bit forward. Found that Spring Retry makes use of AOP so I added:
<dependency>
<groupid>org.springframework</groupid>
<artifactid>spring-aop</artifactid>
<version>4.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.8</version>
</dependency>
Now I'm getting different error:
27-Oct-2017 21:11:12.071 SEVERE [http-nio-8088-exec-5] org.springframework.web.servlet.DispatcherServlet.initServletBean Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'homeController' defined in file [(...)\HomeController.class]: Initialization of bean failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class org.springframework.aop.framework.ObjenesisCglibAopProxy
<ommitted>
Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.springframework.aop.framework.ObjenesisCglibAopProxy
at org.springframework.aop.framework.DefaultAopProxyFactory.createAopProxy(DefaultAopProxyFactory.java:60)
at org.springframework.aop.framework.ProxyCreatorSupport.createAopProxy(ProxyCreatorSupport.java:105)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:109)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:468)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:349)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:298)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:421)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1558)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
... 35 more
To isolate the problem I created small springMVC project and it's the same. To keep everything simple used only few dependencies. This is output from mvn dependency:tree:
[INFO] com.example:store:war:0.0.1-SNAPSHOT
[INFO] +- org.springframework:spring-webmvc:jar:4.0.3.RELEASE:compile
[INFO] | +- org.springframework:spring-beans:jar:4.0.3.RELEASE:compile
[INFO] | +- org.springframework:spring-context:jar:4.0.3.RELEASE:compile
[INFO] | +- org.springframework:spring-core:jar:4.0.3.RELEASE:compile
[INFO] | | \- commons-logging:commons-logging:jar:1.1.3:compile
[INFO] | +- org.springframework:spring-expression:jar:4.0.3.RELEASE:compile
[INFO] | \- org.springframework:spring-web:jar:4.0.3.RELEASE:compile
[INFO] +- javax.servlet:jstl:jar:1.2:compile
[INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:provided
[INFO] +- org.springframework.retry:spring-retry:jar:1.2.1.RELEASE:compile
[INFO] +- com.mashape.unirest:unirest-java:jar:1.4.9:compile
[INFO] | +- org.apache.httpcomponents:httpasyncclient:jar:4.1.1:compile
[INFO] | | +- org.apache.httpcomponents:httpcore:jar:4.4.4:compile
[INFO] | | \- org.apache.httpcomponents:httpcore-nio:jar:4.4.4:compile
[INFO] | +- org.apache.httpcomponents:httpmime:jar:4.5.2:compile
[INFO] | \- org.json:json:jar:20160212:compile
[INFO] +- org.springframework:spring-aop:jar:4.2.5.RELEASE:compile
[INFO] | \- aopalliance:aopalliance:jar:1.0:compile
[INFO] \- org.aspectj:aspectjweaver:jar:1.8.8:compile
It worked for me after adding the spring-boot-starter-aop dependency like below:
compile ("org.springframework.boot:spring-boot-starter-aop:1.5.10.RELEASE")
I will answer my own question 'cause it seems to be working now. All dependencies that are necessary:
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</version>
</dependency>
check if there is no duplicate dependencies (f.e. by mvn dependency:tree, use <exclusions> where necessary). Be sure you decorated your config class with #EnableRetry. For some reason you need to separate the caller from the method itself. F.e.this:
#Retryable(maxAttempts = 4, value = {ResourceAccessException.class}, backoff = #Backoff(delay = 5000))
public ResponseEntity<String> tryToSendAndReturnResponseByRestTemplate(final RestTemplate restTemplate,
final HttpEntity<MyObjDTO>
request) {
return restTemplate.exchange(resolveUrl(ENDPOINT_ADDRESS), HttpMethod.POST, request, String.class);
}
goes to SenderManager class marked as f.e. #Service and in a different class f.e. PhoneDirector class you call:
senderManager.tryToSendAndReturnResponseByRestTemplate(restTemplate, request);
It should work. (If you need to specify what supposed to be returned if after 4 (only here) attempts you're still getting an exception, you can create another method (in SenderManager class) marked with #Recover, like this:
#Recover
public ResponseEntity<String> recoverWhenSendingMessageFailed(final ResourceAccessException e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.REQUEST_TIMEOUT);
}
But If you needed args from #Retryable (in #Recover method) remeber that arguments are populated from the argument list of the failed method in the same order as the failed method, and with the same return type
spring-retry uses spring aop, make sure you have aop added in your pom and try clean building the application.
for spring app :
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
for spring boot :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>

Maven JdbcTemplate exclusion

I would like to use JdbcTemplate to query some very simple values:
String sql = "SELECT NAME FROM CUSTOMER WHERE CUST_ID = ?";
String name = (String)getJdbcTemplate().queryForObject(
sql, new Object[] { custId }, String.class);
So I added the flowing entry to my pom:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
I see other Jars added
spring-tx-4.3.7.RELEASE.jar
spring-beans-4.3.7.RELEASE.jar
spring-core-4.3.7.RELEASE.jar
I would like to minimize the jar clash with the host application, and reduce my code footprint,
Out of this list what can I exclude and still letting JdbcTemplate work?
I won't disappoint you but ... none of them is excludable. All of the mentioned jars are needed.
You can check that out by visiting the dependency respository site itself. There you can find all of them (and even more) in the "Compile Dependencies" list.
Or execute mvn dependency:tree -Dverbose -Dincludes=org.springframework:spring-core,org.springframework:spring-tx,org.springframework:spring-beans inside the root of your project to verify it on your own.
The command should give you something like:
[INFO] \- org.springframework:spring-jdbc:jar:4.3.7.RELEASE:compile
[INFO] +- org.springframework:spring-beans:jar:4.3.6.RELEASE:compile (version managed from 4.3.7.RELEASE)
[INFO] | \- (org.springframework:spring-core:jar:4.3.6.RELEASE:compile - version managed from 4.3.7.RELEASE; omitted for duplicate)
[INFO] +- org.springframework:spring-core:jar:4.3.6.RELEASE:compile
[INFO] \- org.springframework:spring-tx:jar:4.3.6.RELEASE:compile (version managed from 4.3.7.RELEASE)
[INFO] +- (org.springframework:spring-beans:jar:4.3.6.RELEASE:compile - version managed from 4.3.7.RELEASE; omitted for duplicate)
[INFO] \- (org.springframework:spring-core:jar:4.3.6.RELEASE:compile - version managed from 4.3.7.RELEASE; omitted for duplicate)

Jackson throwing nosuchmethod error while

I have following class which i am returning from spring rest server
public class Message {
private String name;
private String text;
public Message(String name, String text) {
this.name = name;
this.text = text;
}
public String getName() {
return name;
}
public String getText() {
return text;
}
}
And I am getting following error when i try to access the api
g.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.type.TypeFactory.constructType(Ljava/lang/reflect/Type;Ljava/lang/Class;)Lcom/fasterxml/jackson/databind/JavaType;
org.springframework.web.servlet.DispatcherServlet.triggerAfterCompletionWithError(DispatcherServlet.java:1302)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:977)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:969)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:860)
javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:845)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
here is my jackson mapping tree via mvn dependency:tree | grep jackson
[INFO] +- org.codehaus.jackson:jackson-mapper-asl:jar:1.9.9:compile
[INFO] | \- org.codehaus.jackson:jackson-core-asl:jar:1.9.9:compile
[INFO] \- com.fasterxml.jackson.core:jackson-databind:jar:2.7.0:compile
[INFO] +- com.fasterxml.jackson.core:jackson-annotations:jar:2.7.0:compile
[INFO] \- com.fasterxml.jackson.core:jackson-core:jar:2.7.0:compile
and here is my actual jackson dependency in pom.xml
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.9</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.7.0</version>
</dependency>
I have tried including latest version of both libraries. I am not sure what i am missing here.
Which Spring version are you using?
Check out the library requirements for Spring on the Spring wiki.
If you're using Spring 4+, you don't need org.codehaus dependencies.
Now there are some issues with Jackson 2.7 - this version will be supported in Spring 4.3 (see SPR-13728 and SPR-13483). In the meantime, you should stick to Jackson 2.6+.

What sort of database will I get with an Apache Wicket Application?

So I've done my Object Oriented design, put together a database schema to go with my design, and promised an impossibly short deadline for delivery I've decided to make my life "easier" by using a Web Framework.
Spring seems insanely complicated (and rather inelegant at a superficial glance) and Roo is impossible to understand and/or get help with on the forums beyond doing anything beyond a basic CRUD app.
I am using (and learning!) Wicket then to accomplish my task. I am spending a lot of time trying to figure out how Wicket creates and uses the database and if I understand correctly it does this automagically from the POJOs that I will be creating. I creating objects that use objects in moderately complex ways, however, and I would like to have a better idea of what the end result is going to look like in mySQL.
Does anyone have any information or links that explain what resulting schema looks like from a Wicket application?
It's been 2+ years since I last used Wicket, but AFAIK it doesn't handle persistence at all.. While Wicket is a very good framework IMHO, you have to handle the database layer yourself with Hibernate or some other ORM (or no ORM at all, of course)
It seems to me like you are coming from the PHP or .Net world and are not used to the way things work in Java (with the emphasis on work). In short: there is no free lunch and if you just glance at Spring or Roo and conclude these are too complicated, you might have some rough times ahead. Java offers a lot of frameworks and flexibility, but you have to do the work.
That said, I love Wicket although it does have somewhat of a learning curve. Wicket has a great approach to templating and resolving all business and control logic in actual Java code. Also, Wicket has an active community with very extensive documentation, wiki's and examples. Wicket does, as Joril pointed out, not do anything related to Object Relational Mapping (ORM) or persistence in general AFAIK. There might be extensions or Wicket-related projects that offer something for this.
Here is my advice for you on how to tackle this:
Use Maven2 and Spring (yes, Spring) and import the following dependencies in your pom.xml:
<properties>
<spring.version>3.0.0.RELEASE</spring.version>
<wicket.version>1.4.10</wicket.version>
</properties>
<dependencyManagement>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>org.springframework.context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>org.springframework.orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>com.springsource.org.apache.commons.dbcp</artifactId>
<version>1.2.2.osgi</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>com.springsource.org.apache.commons.pool</artifactId>
<version>1.5.3</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.mysql.jdbc</groupId>
<artifactId>com.springsource.com.mysql.jdbc</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>com.springsource.org.hibernate</artifactId>
<version>3.3.2.GA</version>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>com.springsource.javax.persistence</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>com.springsource.org.hibernate.annotations</artifactId>
<version>3.4.0.GA</version>
<exclusions>
<exclusion>
<groupId>org.apache.commons</groupId>
<artifactId>com.springsource.org.apache.commons.logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.wicket</groupId>
<artifactId>wicket</artifactId>
<version>${wicket.version}</version>
</dependency>
<dependency>
<groupId>org.apache.wicket</groupId>
<artifactId>wicket-spring</artifactId>
<version>${wicket.version}</version>
<exclusions>
<exclusion>
<artifactId>spring</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.wicket</groupId>
<artifactId>wicket-extensions</artifactId>
<version>${wicket.version}</version>
</dependency>
Annotate your model classes with JPA/Hibernate annotations like so (just an example that shows several common constructs):
#Entity(name = "User")
#Table(name = "users", uniqueConstraints = { #UniqueConstraint(columnNames = { "email" }) })
#SecondaryTable(name = "user_picture")
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String email;
private String name;
private String password;
#Lob
#Column(table = "users_picture", length = 524288)
private byte[] picture;
private Date birthDate;
private String phonenumber;
#ManyToOne(fetch = FetchType.EAGER)
private Address homeAddress;
#Enumerated(EnumType.STRING)
private Gender gender;
#CollectionOfElements(fetch = FetchType.EAGER)
#Enumerated(EnumType.STRING)
private Set<Weekday> workdays = new HashSet<Weekday>();
Use the hibernate3-maven-plugin to generate your database from your annotated model classes. This is a huge time saver. The database gets generated during the test phase of maven2. There are other plugins (DBUnit) that help you to fill your database with test data or the like (you can use old school .sql scripts as well). If you change something in your model, the change automatically propagates to your database (after a maven build of course) which is great during development.
Add this to your pom (I prefer making a multi-module maven project with modules for frontend, backend and api; this would go into your backend pom):
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>hibernate3-maven-plugin</artifactId>
<version>2.0-alpha-1</version>
<configuration>
<components>
<component>
<name>hbm2ddl</name>
<implementation>
annotationconfiguration
</implementation>
</component>
</components>
<componentProperties>
<drop>true</drop>
<jdk5>true</jdk5>
<propertyfile>
target/classes/jdbc.properties
</propertyfile>
<skip>${maven.test.skip}</skip>
</componentProperties>
</configuration>
<executions>
<execution>
<phase>process-test-resources</phase>
<goals>
<goal>hbm2ddl</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.5</version>
</dependency>
</dependencies>
</plugin>
</plugins>
This is what the generated table would look like:
+--------------------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------------------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| email | varchar(255) | YES | UNI | NULL | |
| name | varchar(255) | YES | | NULL | |
| password | varchar(255) | YES | | NULL | |
| birthDate | datetime | YES | | NULL | |
| phonenumber | varchar(255) | YES | | NULL | |
| gender | varchar(255) | YES | | NULL | |
| address | bigint(20) | YES | MUL | NULL | |
+--------------------------------+--------------+------+-----+---------+----------------+
(users_workdays and users_picture are secondary tables referring to this entity)
All my examples are based on the use of a MySQL database; you can replace with with any old RDBMS.
I hope this helps you a) to wake up and smell the ashes, b) get your Wicket project up to speed ORM-wise
cheers!
If you aren't locked into MySQL, you may also want to consider some of the so-called noSQL databases out there. Wicket is tremendous at doing things in an object-oriented manner, and if you are not creating an enterprise application that requires scads of people who are already trained in specific technologies like MySQL, you may significantly reduce your total cost of ownership by not taking the SQL path.

Categories