GWT + IntelliJ Idea - adding a server side library - java

I am trying to implement a GWT project in IntelliJ Idea 15. I have no problems (at least obvious) with GWT and its superdev mode - I can run an application and play with it. I can do RPC calls.
However, now I am trying to add JPA/Hibernate support to use a database. And here I have troubles. In the project I have a GWT facet (2.6.1), a JPA facet (with hibernate implementation), and a web facet (for web dd). Using Open Module Settings -> Libraries -> New Project Library I have added gwt-servlet.jar, and using maven (its not a maven project, just using the feature of Idea) libraries: c3p0:c3p0:0.9.1.2, org.hibernate:hibernate-entitymanager:5.0.3.Final, org.postgresql:postgresql:9.3-1101-jdbc41 ; that is the configuration.
Using this persistence unit properties (excerpt):
<property name="hibernate.connection.driver_class" value="org.postgresql.Driver"/>
<property name="hibernate.c3p0.min_size" value="5" />
<property name="hibernate.c3p0.max_size" value="20" />
<property name="hibernate.c3p0.timeout" value="300" />
<property name="hibernate.c3p0.max_statements" value="50" />
<property name="hibernate.c3p0.idle_test_period" value="3000" />
In GWT RPC servlet I try to create EntityManager instance:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("ThreatPersistenceUnit");
EntityManager em = emf.createEntityManager();
Query query = em.createQuery("SELECT a FROM Asset a");
...
But when I try to run it in the IDEA using default GWT run configuration (Jetty), I get following exception:
javax.persistence.PersistenceException: Unable to build entity manager factory
caused by
Caused by: java.lang.ClassNotFoundException: Could not load requested class : org.postgresql.Driver
Also, before the exception I get following warning:
WARN: HHH000022: c3p0 properties were encountered, but the c3p0 provider class was not found on the classpath; these properties are going to be ignored.
So it seems the server cannot see both c3p0 and postgre jdbc driver.
I tried to google, the closest problem/solution I found is this SO answer. I have put the libraries both to the project and to the artifact. However, I am not sure what the replier meant by the Jetty lib. Where would I find Jetty installation, if I am using just the GWT's default server?
Plus, what seems quite weird to me is that before I had a similar problem (I dont remember if it was exactly the ClassNotFoundException) with GWT RPC that I was able to resolve by adding a gwt-servlet.jar to the libraries - why then adding these other libraries does not help? At least it seems that it does not have any problems with hibernate, since it provides the warnings and so on.

OK, even though it is a stupid mistake, maybe someday in the future someone else will make it, so for future reference this was the issue:
I had set the SDK and sources version of the project as 1.6; the hibernate and other libraries seem to been compiled in the same or lower version. However, the postgre driver was compiled using a newer version - when I have set the source version to 1.7 and set as an SDK the Java 8 SDK, the program crashed at some different exception (but that was due to my programming error - unrelated). I found this out only after I tried (in total desperation) to create a new object of the driver manually in the code (not to delegate the creation to persistence provider) - then I got the major minor version exception and I knew what is the problem.

Related

No suitable driver found for jdbc:sqlserver in Spring framework

I'm working in IntelliJ Ultimate on a Spring based web application. I have downloaded the necessary jar from Microsoft (https://www.microsoft.com/en-us/download/details.aspx?id=11774), and it is in my class path.
I have the following code in my web app:
try {
conn = DriverManager.getConnection(strSQLConnection, strSQLUserUpdates, strSQLPWUpdates);
} catch (SQLException e) {
e.printStackTrace();
}
When I run the web app (On a Tomcat 9.0.0.M8 server), I get a "No suitable driver found for jdbc:sqlserver" error in the Server log.
However, I run the exact same code outside the Spring framework, the connection is established without issue.
I was missing the necessary datasource bean in my application context file. Adding the following to my application context (-servlet.xml) fixed the issue:
<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
</bean>
Ensure that any of your dependencies isn't downloading your jdbc driver in other version (in case you use maven or gradle).
And second thought: if your dependency has scope provided for jdbc driver, add lib manually to tomcat/libs folder.

org.hibernate.console.HibernateConsoleRuntimeException: NoClassDefFoundError

I am trying to configure hibernate in Eclipse but i am having some problems when i try to generate the Hibernate Code:
org.hibernate.console.HibernateConsoleRuntimeException: Received a
NoClassDefFoundError, probably the console configuration classpath is
incomplete or contains conflicting versions of the same class Received
a NoClassDefFoundError, probably the console configuration classpath
is incomplete or contains conflicting versions of the same class
org.hibernate.console.HibernateConsoleRuntimeException: Received a
NoClassDefFoundError, probably the console configuration classpath is
incomplete or contains conflicting versions of the same class Received
a NoClassDefFoundError, probably the console configuration classpath
is incomplete or contains conflicting versions of the same class
java.lang.NoClassDefFoundError:
org/apache/commons/collections/MultiMap
org/apache/commons/collections/MultiMap
java.lang.ClassNotFoundException:
org.apache.commons.collections.MultiMap cannot be found by
org.jboss.tools.hibernate.runtime.v_5_1_5.0.1.Final-v20160331-1852-B88
org.apache.commons.collections.MultiMap cannot be found by
org.jboss.tools.hibernate.runtime.v_5_1_5.0.1.Final-v20160331-1852-B88
This is how my projects libraries look like
And this is my hibernate.cfg.xml
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory name="ConexionHibernate">
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.password">hr</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:#localhost:1521:xe</property>
<property name="hibernate.connection.username">hr</property>
<property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
</session-factory>
</hibernate-configuration>
Before i have it with a tons more of jar files, but looking in other topics i tried to delete them. Before i had this jars, just in case i deleted someone i should not.
Old version of my project library
Thank you in advance!
I already solve the problem.
First of all i downloaded again all the jars from the hibernate website http://hibernate.org/orm/downloads/, concretely the 5.1.1 version.
I added to my project all the jars, not just the ones from the required folder, as i did the first time. And finally i downgraded the Hibernate console version to 4.3 and whoala! its working!

Class autodetection in persistence.xml from src/test

I have a persistence.xml at src/main/resources/META-INF/ and another at src/test/... which differ only in the value of the database:
<properties>
<property name="hibernate.archive.autodetection" value="class, hbm"/>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost/lanchecker-prod" />
and:
<properties>
<property name="hibernate.archive.autodetection" value="class, hbm"/>
<property name="hibernate.connection.url" value="jdbc:mysql://localhost/lanchecker-test" />
However I'm also using class autodetection which works fine for the main resource but fails when I use the test resource.
Is there any way to get this to work or am I obliged to use explicit class naming?
EDIT:
The linked suggestion doesn't actually work it it requires the project is built and tested as a .jar. In my case I'm attempting to do the testing under Eclipse, which can resolve the src/test/resources/META-INF/ location.
I tried adding:
<jar-file>${PROJECT_LOC}/src/main/java/biz/ianw/lanchecker/</jar-file>
but that resulted in:
Exception in thread "main" java.lang.ExceptionInInitializerError
...
Caused by: javax.persistence.PersistenceException: Unable to build entity manager factory
...
Caused by: java.lang.IllegalArgumentException: Unable to visit JAR file:${PROJECT_LOC}/src/main/java/biz/ianw/lanchecker/. Cause: Illegal character in opaque part at index 6: file:${PROJECT_LOC}/src/main/java/biz/ianw/lanchecker/
And then:
<jar-file>C:\Users\Ian\git\LANchecker\src\main\java\biz\ianw\lanchecker\</jar-file>
which passed entity manager factory startup, but still failed later with:
Exception in thread "main" java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: RouteCabinFares is not mapped [select rcf from RouteCabinFares rcf]
(RouteCabinFares is one of the classes I'm attempting to autolocate).
Maybe this technique can only be used to autolocate in jar files?
As far as I can tell what I'm trying to do here is not possible.
The best work around I've come up with is to remove the properties you wish to vary from the persistence.xml, in this case:
<property name="hibernate.connection.url" value="jdbc:mysql://localhost/lanchecker-test" />
and specify them at runtime using code similar to:
Properties properties = new Properties();
properties.setProperty("hibernate.connection.url", "jdbc:mysql://localhost/lanchecker-test");
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("lanchecker", properties);
The actual property values can then be injected at runtime via Spring. This involves separating standard properties into persistence.xml and varying properties into spring.xml and is, to my mind, extremely hokey.
I get the impression that Spring Boot might offer a simpler solution but at the expense at another framework so, for the moment, the above is what I'm going for.

How do I make JNDI names compatible with both GlassFish and WildFly

I am developing a Java EE 7 application and have a requirement for the application to be deployed onto application servers running either GlassFish 4.0 or WildFly 8.1.0. The issue I've got is GlassFish and WildFly use slightly different formats for JNDI names but I can't see how to make my application compatible with both.
In GlassFish my persistence.xml file references the data source jdbc/myDataSouce, but in WildFly the data source needs to be java:/jdbc/myDataSource.
The same is also true for classes that are annotated with #Resource. In GlassFish the annotation for a class using JavaMail would be #Resource(name = "mail/myMailSession"), but to deploy onto WildFly this would need to be #Resource(name = "java:mail/myMailSession").
I know that I could unpack the EAR and JAR files to manually edit files such as persistence.xml but I can't do that for classes that have been annotated with #Resource.
Is there a way I can allow my complied application to be deployed onto GlassFish and WildFly without maintaining two different versions of the code? I'm assuming the answer probably lies with application specific deployment descriptors but I can't find any examples that cover these two scenarios.
Can anyone point me in the right direction please?
You can modify the Wildfly JNDi names and strip the undesired prefixes from the respective JNDI names to find the least common denominator in both app servers. The following works for me with Glassfish and JBoss AS 7.1. Since I expect Wildfly to be backwards-compatible to JBoss in this regard, I guess it'll work for Wildfly as well.
Persistence
Inject as:
#PersistenceContext(unitName="TestPU")
private EntityManager entityManager;
or via ejb-jar.xml:
<persistence-context-ref>
<persistence-context-ref-name>entityManager</persistence-context-ref-name>
<persistence-unit-name>TestPU</persistence-unit-name>
<injection-target> ... </injection-target>
</persistence-context-ref>
The corresponding persistence.xml:
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="TestPU" transaction-type="JTA">
<jta-data-source>datasources/TestDS</jta-data-source>
<class>org.jeeventstore.persistence.jpa.EventStoreEntry</class>
<properties>
<property name="hibernate.show_sql" value="false"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.connection.charSet" value="UTF-8"/>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.logging.level.sql" value="FINE"/>
<property name="eclipselink.logging.parameters" value="true"/>
<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
</properties>
</persistence-unit>
</persistence>
(note the simple jta-data-source JNDI name)
Here's a glassfish-resources.xml file used to specify a Derby database on deployment, a similar setup can be used for MySQL or Postgres.
<resources>
<jdbc-resource pool-name="ArquillianEmbeddedDerbyPool"
jndi-name="datasources/TestDS"/>
<jdbc-connection-pool name="ArquillianEmbeddedDerbyPool"
res-type="javax.sql.DataSource"
datasource-classname="org.apache.derby.jdbc.EmbeddedDataSource"
is-isolation-level-guaranteed="false">
<property name="databaseName" value="target/databases/derby"/>
<property name="createDatabase" value="create"/>
</jdbc-connection-pool>
</resources>
And the settings from the JBoss standalone.xml:
<datasource jta="true" jndi-name="java:/datasources/TestDS" pool-name="TestDS" enabled="true" use-ccm="false">
<connection-url>jdbc:postgresql://localhost/test_db</connection-url>
...
</datasource>
Resources
I have not injected a JavaMail component on Glassfish, but similar to the datasoruce settings, it might be worth a try to strip the "java:" part from the #Resource annotation as well.
#Resource(name = "mail/myMailSession")
and then configure Wildfly such that that the mail resource is available at the "java:mail/myMailSession" JNDI location.
Injection via ejb-jar.xml
Another option is to manually inject the fields via a ejb-jar.xml file, and then use a build tool such as maven to copy either of ejb-jar-glassfish.xml or ejb-jar-wildfly.xml to the desired ejb-jar.xml at assembly time.
In one of our projects we use a mixed approach to avoid the burden with the xml configuration: We configure a small number of "provider" beans via ejb-jar.xml to inject, e.g., the persistence context into a PersistenceContextProvider, and then use CDI to inject the PersistenceContextProvider into the EJBs via #EJB, which are found without further configuration since they reside in the same EAR.
I haven't hit the mail-dilemma just yet. But I've ran into the same problem your having when it comes to data source definition and my solution has been to not setup the data sources using the server's console, but make them deployable together with your archive using the #DataSourceDefinition annotation. Turns out WildFly won't complain about java:app/blabla.. if the data source is setup during deployment!
Here is a real world example for you that works on both GlassFish and WildFly:
https://github.com/martinanderssondotcom/java-ee-concepts/../ArquillianDS.java
Note that the data source JNDI name declared is:
java:app/env/ArquillianDS
And here is the related persistence.xml file (don't mind the name of the file in this repository, the repository represents a test project that build archives during runtime and the app will change the name of the file in the archive to persistence.xml):
https://github.com/MartinanderssonDotcom/java-ee-concepts/../persistence-update.xml
Also note that the persistence unit need a data source located using this JNDI name:
java:app/env/ArquillianDS
This deployment works perfectly fine with both GlassFish and WildFly. I've noted that if we declare the data source during deployment, then we pay the price of not seeing the data source listed anywhere in the admin gui/console. For me, that is a small price to pay in order to have a truly portable application. As an added bonus, I don't have to write lengthy installation/setup instructions. For all my projects, the data source is an intrinsic part of the application and I don't mind having a class file in the archive that represents the data source.
The above data source is using a Java DB (or "Apache Derby" for old school people). As some comments in the ArquillianDS.java file describe: GlassFish has problems using a simple URL connection string combined with Java DB. Hence I resorted to specifying all attributes of the #DataSourceDefinition explicitly. Recently in another project of mine (alas not a public one), I used the same construct of deployment time data source definition but targeting MySQL. Here's that data source definition and it works on both servers:
#DataSourceDefinition(
name = "java:app/env/maLivechatDS",
url = "jdbc:mysql://localhost:3306/malivechat_db?createDatabaseIfNotExist=true&user=root&password",
className = "com.mysql.jdbc.jdbc2.optional.MysqlDataSource"
)
#ManagedBean
public class MySQLDataSource { }
Note that the driver is MysqlDataSource and not MysqlXADataSource. One point in my application uses a rather complex transaction scheme and GlassFish ran into problems if I used the XA-driver. However, the non-XA driver used by my application still work properly with JTA transactions so for me, it was just a cheap trick to get the boat floating. You should probably use the XA-driver.
For JNDI Portability with portable DataSourceDefinition annotation, I test it On payara-5.192, wildfly-17.0.1, tomee-8-M3 and openLiberty-19.0.0.7
#DataSourceDefinition(
name = "java:app/env/jdbc/mysql_app_name",
className = "com.mysql.cj.jdbc.MysqlConnectionPoolDataSource",
url = "jdbc:mysql://localhost:3306/db_name?characterEncoding=utf-8&zeroDateTimeBehavior=CONVERT_TO_NULL&user=root&password=password",
minPoolSize = 1,
properties = {"characterEncoding=utf-8","zeroDateTimeBehavior=CONVERT_TO_NULL"})
I used it with MySQL connector 8.
refer to reference. for wildfly I created a startup bean class for configuration and set the annotation in the startup class.
for openLiberty add in server.xml
<application id="app_name" contextRoot="/app_name" name="app_name" location="../app_name.war" type="war">
<classloader commonLibraryRef="mysql"/>
</application>
<library id="mysql">
<file name="/path_to/mysql-connector-java-8.0.17.jar"/>
</library>
and put the war file in
usr/servers/defaultServer
folder

Embedded GlassFish ignores Maven test resources

I have several session beans that I have written unit tests for. I have setup Maven to include a persistence.xml in the src/main/resources/META-INF directory that refers to a local MySQL database for development purposes. I have another persistence.xml in src/test/resources/META-INF directory that refers to the embedded Derby database __default. The tests are deployed to an embedded GlassFish 3.1 container.
When I run the tests however, I get the following error:
java.lang.RuntimeException: javax.naming.NamingException: Lookup failed for 'jdbc/mylog'
jdbc/mylog is the MySQL database that the persistence unit in the main directory refers to. It is obviously ignoring the persistence unit in the test directory but I have no clue as to why.
Maven is setting the classpath correctly as far as I can tell, with test-classes before classes and a peek in the actual target/test-classes/META-INF directory reveals that it copied the correct, embedded Derby, persistence unit.
[DEBUG] Test Classpath :
[DEBUG] C:\Users\Laurens\Documents\Projects\Mylog\target\test-classes
[DEBUG] C:\Users\Laurens\Documents\Projects\Mylog\target\classes
[DEBUG] C:\Users\Laurens\.m2\repository\org\eclipse\persistence\eclipselink\2.2.0\eclipselink-2.2.0.jar
[DEBUG] C:\Users\Laurens\.m2\repository\org\eclipse\persistence\javax.persistence\2.0.3\javax.persistence-2.0.3.jar
[DEBUG] C:\Users\Laurens\.m2\repository\org\eclipse\persistence\org.eclipse.persistence.jpa.modelgen.processor\2.2.0\org.eclipse.persistence.jpa.modelgen.processor-2.2.0.jar
[DEBUG] C:\Users\Laurens\.m2\repository\org\glassfish\extras\glassfish-embedded-all\3.1\glassfish-embedded-all-3.1.jar
[DEBUG] C:\Users\Laurens\.m2\repository\javax\javaee-web-api\6.0\javaee-web-api-6.0.jar
[DEBUG] C:\Users\Laurens\.m2\repository\junit\junit\4.8.1\junit-4.8.1.jar
Any hint on how to have GlassFish use the proper persistence unit very much appreciated! Thanks!
When running tests using embedded Glassfish, the JPA provider does not use the classpath displayed on the command-line, before executing the maven-surefire-plugin goal (that is used to run the test phase). Embedded Glassfish deploys the artifacts that are available as part of a test scope, as a ScatteredArchive. This scattered archive is typically created in the java.io.tmpdir directory usually with the name gfembed<a_random_number>tmp, unless the embedded Glassfish configuration specified the location of a Glassfish installation root, and a Glassfish domain.
When the embedded Glassfish domain is prepared with the deployed scattered archive, the files to be deployed are typically copied into an exploded directory that houses all the classes (including all dependencies) required by the application. This directory typically happens to be present in the GF_EMBED_DOMAIN_HOME/applications/<application_name> directory. The persistence.xml files from your src/main/resources/META-INF and src/test/resources/META-INF directories are copied here into the <application-name>/META-INF directory. Needless to state, the one that gets copied last, or the one that doesn't get overwritten is the one that is used by the JPA provider during the tests. This always happens to be the file in src/main/resources/META-INF.
You can overcome this situation in two ways:
1. Using a custom Glassfish domain configuration file
You can specify a domain configuration file (domain.xml) that will contain the datasource definition for jdbc/mylog. This is what I do currently for it is very flexible and the domain configuration file can contain other configurations as well. The config file, needs to specified as part of test setup in the following way:
Map<String, Object> props = new HashMap<String, Object>();
props.put("org.glassfish.ejb.embedded.glassfish.installation.root", "./glassfish-install/glassfish");
container = EJBContainer.createEJBContainer(props);
context = container.getContext();
datasource = (DataSource) context.lookup("jdbc/mylog"); //You can lookup the datasource too, to confirm that your setup is successful.
The afore-mentioned glassfish-install directory and its sub-directory glassfish are present in the Maven project root (and also checked into version control); the glassfish directory must contain a directory structure of domain1/config to represent the directory structure of the Glassfish domain of name domain1. The structure in the project can be seen in the below screenshot. The other related files (the JDBC resource adapter JARs and the like), can be obtained from a Glassfish installation directory, but typically these might also be placed in the correct location by the embedded Glassfish runtime, if configured correctly.
The contents of the Glassfish domain configuration file are different from the default one used by embedded Glassfish, except for the datasource and connection pool configuration (the relevant entries added in my usecase where I perform integration tests, have been posted below):
<domain log-root="${com.sun.aas.instanceRoot}/logs" application-root="${com.sun.aas.instanceRoot}/applications" version="10.0">
<system-applications/>
<applications/>
<resources>
<jdbc-resource pool-name="MyPool" jndi-name="jdbc/mylog"/>
...
<jdbc-connection-pool driver-classname="" datasource-classname="org.apache.derby.jdbc.ClientDataSource" res-type="javax.sql.DataSource" description="" name="MyPool" ping="true">
<property name="User" value="APP"></property>
<property name="RetrieveMessageText" value="true"></property>
<property name="CreateDatabase" value="true"></property>
<property name="ServerName" value="localhost"></property>
<property name="Ssl" value="off"></property>
<property name="SecurityMechanism" value="4"></property>
<property name="TraceFileAppend" value="false"></property>
<property name="TraceLevel" value="-1"></property>
<property name="PortNumber" value="1527"></property>
<property name="LoginTimeout" value="0"></property>
<property name="Password" value="APP"></property>
<property name="databaseName" value="MYDB"></property>
</jdbc-connection-pool>
...
</resources>
<servers>
<server name="server" config-ref="server-config">
<resource-ref ref="jdbc/__TimerPool"/>
<resource-ref ref="jdbc/__default"/>
<resource-ref ref="jdbc/mylog"/>
</server>
</servers>
...
...
The default domain.xml file can be downloaded from the java.net site, and modified, in the event you wish to keep the changes as minimal as possible, instead of copying one from a Glassfish installation.
2. Copying over the persistence.xml files
One can add goals to the Maven POM file, to backup and copy the persistence.xml file from src/test/resources/META-INF to src/main/resources/META-INF, before the test phase. After the test phase is complete, the original is restored. I will not go into details of this, as a similar solution is already discussed in a related StackOverflow question. I did not use this approach for integration tests as I required changes to be done beyond the ones that can be carried in persistence.xml, like creation of a custom realm. I use it for unit-tests however, due to the fact that the JPA provider will fetch the persistence.xml file from target/classes instead of target/test-classes, despite the latter appearing first in the classpath order. If you use Hibernate as your JPA provider, enabling TRACE logging for the org.hibernate.ejb logger (as the Ejb3Configuration class is responsible for performing the lookup) would convince you that file in test-classes will not be picked up.
Note:
Most of the answer assumes Glassfish 3.1 but may hold good for upcoming versions as well.
By "embedded glassfish container", do you mean a maven plugin that runs glassfish for you? The classpath for a maven plugin is different and managed differently than the maven test classpath. You might need to be working with a different classpath.
This answer might sounds silly but I was looking for a way which lets me run those tests from eclipse by Run As -> JUnit Test. This is how I made it:
#BeforeClass
public static void setUp() throws IOException {
Files.copy(new File("target/test-classes/META-INF/persistence.xml"), new File("target/classes/META-INF/persistence.xml"));
// ...
}
I'm just copying the test/persistence.xml to classes/persistence.xml. This works.

Categories

Resources