I try to use Grails 1.3.7 with plugin gorm-jpa 0.7.1 to enable JPA persistence using EclipseLink 2.2.0 as a persistence provider.
When running the app and clicking on the controller of a JPA annotated entity I get an "UnwantedTokenException" from JPQLParser of EclipseLink:
Executing action [list] of controller [model.PersonController] caused exception:
An exception occurred while creating a query in EntityManager:
Exception Description: Syntax error parsing the query [select person from model.Person as person ], line 1, column 24: syntax error at [.].
Internal Exception: UnwantedTokenException(found=., expected 80);
at org.eclipse.persistence.internal.libraries.antlr.runtime.BaseRecognizer.recoverFromMismatchedToken(BaseRecognizer.java:587)
[...]
at org.eclipse.persistence.internal.jpa.parsing.jpql.JPQLParser.parse(JPQLParser.java:134)
It seems that EclipseLink has a problem with the dot in "model.Person".
How to solve this issue?
To reproduce the issue setup a grails project as follows:
grails create-app GrailsJPA
cd GrailsJPA
grails uninstall-plugin hibernate
grails install-plugin gorm-jpa
grails create-domain-class model.Person
Edit "grails-app\domain\model\Person.groovy" as follows:
package model
import javax.persistence.*;
#Entity
class Person {
#Id
#GeneratedValue
long id;
#Basic
long version;
#Basic
String firstName
#Basic
String lastName
static constraints = {
firstName(nullable:true)
lastName(nullable:true)
}
}
Generate controller and view for the defined entity:
grails generate-controller model.Person
grails generate-view model.Person
Edit "grails-app\conf\spring\resources.groovy" as follows:
beans = {
entityManagerFactory(org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean) {
beanClassLoader = ref("classLoader")
dataSource = ref("dataSource")
loadTimeWeaver = new org.springframework.instrument.classloading.SimpleLoadTimeWeaver()
}
transactionManager(org.springframework.orm.jpa.JpaTransactionManager) {
entityManagerFactory = entityManagerFactory
}
}
Create a file "web-app\WEB-INF\classes\META-INF\persistence.xml" as follows:
<?xml version="1.0" encoding="UTF-8"?>
<persistence 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_1_0.xsd" version="1.0">
<persistence-unit name="manager" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>model.Person</class>
<properties>
<property name="eclipselink.ddl-generation" value="create-tables"/>
</properties>
</persistence-unit>
</persistence>
Download EclipseLink 2.2.0 installer ZIP from http://www.eclipse.org/eclipselink/downloads/2.2.0 and extract "eclipselink.jar" from "eclipselink\jlib\" in ZIP to grails project dir:
lib\eclipselink.jar
Now run the grails application:
grails run-app
Browse to
http://localhost:8080/GrailsJPA
Now click on controller "model.PersonController" to reproduce the above exception.
Any ideas on how to resolve this issue?
I managed to get EclipseLink 2.3.0 JPA provider to work with domain classes that are not inside a package in the following way.
In the following I will show how to setup a grails application that is using EclipseLink as a JPA provider to persist domain classes and run the application in a Tomcat 6 web container.
Start by
creating a new grails project
uninstall the default hibernate plugin
install the gorm-jpa plugin which enables gorm-like behaviour on top of JPA
create a new domain class "Person" for testing
grails create-app GrailsJPA
cd GrailsJPA
grails uninstall-plugin hibernate
grails install-plugin gorm-jpa
grails create-domain-class Person
Hint: Do not put domain classes in packages. EclipseLink will fail when processing e.g. "model.Person" because of the dot in the name, but will do fine with e.g. "Person" (compare to above post).
Edit "grails-app\domain\Person.groovy" as follows:
import javax.persistence.*;
#Entity
class Person {
#Id
#GeneratedValue
long id;
#Basic
long version;
#Basic
String firstName
#Basic
String lastName
static constraints = {
firstName(nullable:true)
lastName(nullable:true)
}
}
Generate a controller and a view for the defined entity:
grails generate-controller Person
grails generate-view Person
Now we need to modify the generated controller slightly, so that all actions modifying the entity (save, edit, update, delete) are encapsulated in a transaction (compare to bug GPGORMJPA-6). This is done by encapsulating the whole action into a "Person.withTransaction" block.
Edit "grails-app\controllers\PersonController.groovy" as follows:
[...]
def save = {
Person.withTransaction {
[...original code stays in this block...]
}
}
[...]
def edit = {
Person.withTransaction {
[...original code stays in this block...] }
}
}
def update = {
Person.withTransaction {
[...original code stays in this block...]
}
}
def delete = {
Person.withTransaction {
[...original code stays in this block...]
}
}
[...]
Now we define a persitence unit "manager" that specifies a set of classes to manage persistence for (class "Person") and which JPA provider to use for these classes (in our case EclipseLink).
Create a file "web-app\WEB-INF\classes\META-INF\persistence.xml" as follows:
<?xml version="1.0" encoding="UTF-8"?>
<persistence 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_1_0.xsd" version="1.0">
<persistence-unit name="manager" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>Person</class>
<properties>
<property name="eclipselink.ddl-generation" value="create-tables"/>
</properties>
</persistence-unit>
</persistence>
Please note: The file will be deleted if "target" dir of project is cleaned, e.g. when "grails clean" is called explicitly. So it's a good idea to make a backup of the file outside of the "target" dir.
To make EclipseLink available to the grails project, download EclipseLink 2.3.0 installer ZIP and extract "eclipselink.jar" from "eclipselink\jlib\" in ZIP to "lib" folder of grails project:
lib\eclipselink.jar
Now we need to make sure, that an "entityManagerFactory" and "transactionManager" bean are created when the web application is started. The beans will provide the needed access to the JPA provider that will manage all the persistency.
Edit "grails-app\conf\spring\resources.groovy" as follows:
beans = {
entityManagerFactory(org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean) {
dataSource = ref("dataSource")
beanClassLoader = ref("classLoader")
loadTimeWeaver = new org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver()
}
transactionManager(org.springframework.orm.jpa.JpaTransactionManager) {
entityManagerFactory = entityManagerFactory
}
}
Please note that we specified a special loadTimeWeaver in the above declarations, that enables the JPA persistence provider to hook into java bytecode on the fly during runtime. When using EclipseLink this is essential. If just using org.springframework.instrument.classloading.SimpleLoadTimeWeaver for testing purposes, this enables the web app to start, but when accessing JPA entities you will encounter exceptions like "0 is not a known entity type", as the persistence provider is unable to hook into the management of the entity classes at runtime.
The use of InstrumentationLoadTimeWeaver is a bit of a hassle, as it will only work, if
the java virtual machine executing the web app server is started using "spring-agent" java agent, AND
our web app is loaded by the Tomcat server using a special classloader named "TomcatInstrumentableClassLoader"
To achieve this, first download spring-agent-2.5.6.SEC02.jar and spring-instrument-tomcat-3.0.5.RELEASE.jar.
Assume that you have installed Tomcat server in directory %CATALINA_HOME%.
Copy the downloaded jar files "spring-agent-2.5.6.SEC02.jar" and "spring-instrument-tomcat-3.0.5.RELEASE.jar" to %CATALINA_HOME%\lib
Now we modify "%CATALINA_HOME%\bin\catalina.bat" that is used by e.g. the start and stop scripts of Tomcat to make sure the JVM executing Tomcat runs with the "spring-agent" java agent.
Add the following to "%CATALINA_HOME%\bin\catalina.bat" in section "Execute The Requested Command" after all the echos:
if exist "%CATALINA_HOME%\lib\spring-agent-2.5.6.SEC02.jar" set JAVA_OPTS=%JAVA_OPTS% -javaagent:%CATALINA_HOME%\lib\spring-agent-2.5.6.SEC02.jar
When Tomcat is started, the script will now check if "spring-agent-2.5.6.SEC02.jar" is in the lib dir, and if this is the case, it will add it as the java agent to the JAVA_OPTS that are used as command line parameters to the JVM when starting Tomcat.
To enable the "TomcatInstrumentableClassLoader" as class loader for our web application we add the file "web-app\META-INF\context.xml" to our grails project, with the following content:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>
</Context>
Please note that the tags in "context.xml" are case sensitive. So do not try to change <Context> to <context> (or similar things) - this will fail!
Before we package and deploy our web application, we define which datasource to use for persistency. For testing, we just define a HSQLDB in-memeory database.
Edit "grails-app\conf\DataSource.groovy" as follows:
[...]
development {
dataSource {
dbCreate = "create-drop"
url = "jdbc:hsqldb:mem:testDB"
}
}
test {
dataSource {
dbCreate = "create-drop"
url = "jdbc:hsqldb:mem:testDb"
}
}
production {
dataSource {
dbCreate = "create-drop"
url = "jdbc:hsqldb:mem:testDB"
}
}
[...]
Now we are ready to create a WAR archive of our web app using:
grails war
The WAR will be placed in the "target" directory of our project.
In "%CATALINA_HOME%\webapps"
create a directory "GrailsJPA"
extract all contents of the created WAR archive into this directory
Please note: Do not place WAR in "%CATALINA_HOME%\webapps" and hope that it is deployed on startup of Tomcat. This will fail!
Now start the Tomcat server using script
"%CATALINA_HOME%\bin\startup.bat"
After Tomcat is up and running, use your browser to browse to
http://localhost:8080/GrailsJPA
Now click on controller "PersonController" to create, update, list and delete Person entities via JPA using EclipseLink JPA provider.
But using domain classes that are inside of a package will still fail with the exception mentioned in the above post. This issue is still unresolved.
Download links
Grails 1.3.7
http://grails.org/Download
EclipseLink 2.3.0
http://www.eclipse.org/eclipselink/downloads/2.3.0
Tomcat 6
http://tomcat.apache.org/download-60.cgi
spring-instrument-tomcat-3.0.5.RELEASE.jar
http://mvnrepository.com/artifact/org.springframework/spring-instrument-tomcat
spring-agent-2.5.6.SEC02.jar
http://mvnrepository.com/artifact/org.springframework/spring-agent
Related
I have a problem with running Cucumber tests in a khipster project (I can reproduce it with jhipster as well) when I configure it to use oauth2.
I create the project with the following configuration file (I call it mono.jdl):
application {
config {
applicationType monolith
authenticationType oauth2
baseName helloworld
buildTool maven
packageName com.example.helloworld
testFrameworks [cucumber]
}
entities *
}
I generate the project with a command: khipster import-jdl mono.jdl.
I create a very simple Cucumber test. I create a feature file (src/test/features/kuku/kuku.feature):
Feature: just a test
Scenario: my scenario
And one two three
and a file with steps (src/test/kotlin/com/example/helloworld/cucumber/stepdefs/KukuStepDefs.kt):
package com.example.helloworld.cucumber.stepdefs
import io.cucumber.java.en.When
class KukuStepDefs : StepDefs() {
#When("one two three")
fun magic() {
println("four five six")
}
}
I try to run the integration test with a command ./mvnw integration-test. However, it fails with a following error:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.example.helloworld.web.rest.LogoutResource required a bean of type 'org.springframework.security.oauth2.client.registration.ClientRegistrationRepository' that could not be found.
The following candidates were found but could not be injected:
- Bean method 'clientRegistrationRepository' in 'OAuth2ClientRegistrationRepositoryConfiguration' not loaded because OAuth2 Clients Configured Condition registered clients is not available
Action:
Consider revisiting the entries above or defining a bean of type 'org.springframework.security.oauth2.client.registration.ClientRegistrationRepository' in your configuration.
How can I fix this problem?
The solution is to find CucumberContextConfiguration class. It contains such annotation:
#ContextConfiguration(classes = [HelloworldApp::class])
We must change it to:
import com.example.helloworld.config.TestSecurityConfiguration
(...)
#ContextConfiguration(classes = [HelloworldApp::class, TestSecurityConfiguration::class])
I am sitting in front of a Grails 3.1.4 Application. The build.gradle file looks like this:
buildscript {
...
}
version "01.01.12.99"
...
ext {
...
}
repositories {
...
}
dependencyManagement {
...
}
dependencies {
...
}
From one of my Service Classes I want to access the version variable. Is this somehow built in into Grails or am I trying to do something impossible? Are there ways to load this variable from a Service class?
I searched a bit and found this, but it accesses the Grails version not the project version.
Well, I recently started using Grails 3. Here I got the solution:
println System.properties.getProperty("info.app.version")
And you will get "01.01.12.99". This is working on Grails 3.1.8 for me.
Another way to achieve this (in addition to the solution provided by Shashank Agrawal) is relying on grailsApplication bean, with the following code:
grailsApplication.config.getProperty('info.app.version')
I tested this with Grails 3.1.9 and 3.2.7.
I have a project built with Gradle with 3 subprojects: trawler, adaptrice, frontage. Trawler is Groovy/Java, adaptrice is a Grails 3.1.7 app, frontage is a Grails 3 plugin used by adaptrice.
The top settings.gradle says include 'trawler', 'adaptrice', 'frontage', adaptrice/build.gradle contains,
grails {
plugins {
compile project(':frontage')
}
}
All this as per the Grails documentation. Everything works -- almost. The doWithSpring method in the plugin descriptor (class FrontageGrailsPlugin) looks like this,
Closure doWithSpring() { {->
entityPropGrabberFactory(EntityPropGrabberFactory) {
constraintsEvaluator = ref(ConstraintsEvaluator.BEAN_NAME)
proxyHandler = ref('proxyHandler')
}
}}
It is never executed when I do run-app for the adaptrice Grails app. There is a NPE when a supposedly injected bean is used. If I move the body of doWithSpring to the .../spring/resources.groovy of the adaptrice Grails app then it really works.
So my question is, what causes the doWithSpring in a Grails 3 plugin descriptor to be executed? Do I have to do something special when the plugin also is a subproject?
I've enabled jdbcStore in QuartzConfig
quartz {
jdbcStore = true
autoStartup = true
}
and provided quartz.properties in grails-app/conf directory:
...
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
...
The problem is that when I run grails in local dev environment with grails rA those properties are ignored and I get an exception:
Caused by: org.quartz.JobPersistenceException: Couldn't store trigger 'RebillJobSimpleTrigger' for 'com.payment.rebill.RebillJob' job:Bad value for type long : \xaced00057.....
at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeTrigger(JobStoreSupport.java:1241)
at org.quartz.impl.jdbcjobstore.JobStoreSupport$5.execute(JobStoreSupport.java:1147)
at org.quartz.impl.jdbcjobstore.JobStoreSupport$40.execute(JobStoreSupport.java:3670)
at org.quartz.impl.jdbcjobstore.JobStoreCMT.executeInLock(JobStoreCMT.java:242)
In live environment everything works ok, however I'm unable to run the project in embedded jetty.
Elaboration:
The exception is thrown because my custom quartz.properties are ignored (Thus instead of PostgreSQLDelegate the StdJDBCDelegate is used which is unable to read BLOB from DB).
I use quartz grails plugin version 0.4.2 which contains empty grails-app/conf/quartz.properties and I think there is some class loader issue which loads this empty file instead of my own quartz.properties file.
Looking into the plugin the properties file is configured in QuartzGrailsPlugin.groovy's spring bean:
quartzScheduler(SchedulerFactoryBean) {
configLocation = "classpath:quartz.properties"
...
(There is some spring bean builder magic which converts the "classpath:quartz.properties" String to spring's Resource class, since SchedulerFactoryBean's configLocation property is of type Resource).
When I debug the initialization on line 554 of SchedulerFactoryBean the configLocation leads to empty file despite my quartz.properties are not empty.
When I manually change the quartz spring bean to read file from different location everything works:
quartzScheduler(SchedulerFactoryBean) {
configLocation = "classpath:data/quartz.properties"
...
However I can't change the quartz plugin itself. Do you have any idea how to fix this locally ?
I use grails version 2.1.2
I'm using WebLogic 10.3 with JPA 1.0.
The entity class is:
#Entity
public class ZoneAgency implements Serializable {
public ZoneAgency() {
super();
}
#Id
#Column(name = "zoneid", nullable = false)
private Integer zoneId;
#Id
#Column(name = "agencyid", nullable = false)
private Integer agencyId;
}
It is also added in persistence.xml:
<?xml version="1.0" encoding="windows-1252" ?>
<persistence 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_1_0.xsd"
version="1.0">
<persistence-unit name="smthModel">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/smthDS</jta-data-source>
<class>smth.model.entities.ZoneAgency</class>
<properties>
<property name="eclipselink.target-server" value="WebLogic_10"/>
<property name="javax.persistence.jtaDataSource" value="jdbc/smthDS"/>
<property name="eclipselink.cache.shared.default" value="false"/>
</properties>
</persistence-unit>
</persistence>
I use this class in the following invocation:
Query query = entityManager.createNativeQuery("call get_zone_agency_by_channel_type_rr(?,?)", ZoneAgency.class);
where get_zone_agency_by_channel_type_rr is a stored procedure that returns the result of this select:
select t_zone_id as zoneid, t_agency_id as agencyid;
This entity class is wrapped inside a jar file that is used as a dependency in a web application (war file). This war is wrapped inside an ear file and deployed on WebLogic.
The problem is that
when I install/update the deployment, the entityManager.createNativeQuery invocation works fine;
when I stop the Web application and then restart it, I get the following error:
Exception Description: Missing descriptor for [class smth.model.entities.ZoneAgency].
Query: ReadAllQuery(referenceClass=ZoneAgency sql="call get_zone_agency_by_channel_type_rr(?,?)")
What could the problem be?
It seems to be a class loader issue. My guess is that the old persistence unit with the old classes are still deployed in the server.
When you use a container managed (injected/jta) persistence unit the server take care of undeploying it.
When you use an application managed persistence unit (Persistence.createEntityManagerFactory()), then you must ensure you close it before redeploying a live server. Otherwise it will remain deployed.