If you want to migrate to OpenXava 7.0 or newer look at the new migration instructions
assertValue("date", "5/25/21");
assertValue("date", "5/25/2021");
setConditionValues("1");
execute("List.filter"); // This does not save "Number = 1" automatically
// Here you do more stuff
selectListConfiguration("Number = 1"); // FAILS IN v6.5
setConditionValues("1");
execute("List.filter");
execute("List.saveConfiguration"); // ADD THESE LINES TO SAVE...
execute("SaveListConfiguration.save"); // ...THE QUERY EXPLICITLY
// Here you do more stuff
selectListConfiguration("Number = 1"); // Now it works
String [] listActions = {
"Print.generatePdf",
"Print.generateExcel",
"ImportData.importData",
"CRUD.new",
"CRUD.deleteSelected",
"CRUD.deleteRow",
"List.filter",
"List.orderBy",
"List.viewDetail",
"List.hideRows",
"List.sumColumn",
// "List.changeConfiguration", // REMOVE THIS LINE
"List.changeColumnName",
"ListFormat.select"
};
assertActions(listActions);
assertLabelInList(0, "Year of Invoice");
assertLabelInList(0, "Year of invoice");
execute("List.goNextPage", "collection=myCollection");
execute("Collection.edit", "row=10,viewObject=xava_view_myCollection");
setValue("name", "Modified name");
execute("Collection.save");
// execute("List.goNextPage", "collection=myCollection"); // REMOVE THIS LINE
assertValueInCollection("myCollection", 0, 0, "Modified name");
<% if (org.openxava.web.Browsers.isIE(request)) { %>
<script type='text/javascript' src="<%=request.getContextPath()%>/xava/js/css-vars-ponyfill.js?ox=<%=oxVersion%>"></script>
<script type='text/javascript'>cssVars({ }); </script>
<% } %>
String applicationName = request.getContextPath().substring(1);
MetaApplication metaApplication = MetaApplications.getMetaApplication(applicationName);
MetaApplication metaApplication = MetaApplications.getMainMetaApplication();
execute("ImageEditor.changeImage", "newImageProperty=image");
String imageURL = System.getProperty("user.dir") + "/test-images/cake.gif";
setFileValue("newImage", imageURL);
execute("LoadImage.loadImage");
uploadFile("image", "test-images/cake.gif");
execute("Gallery.edit", "galleryProperty=photos");
execute("Gallery.addImage");
String imageURL = System.getProperty("user.dir") + "/test-images/foto-javi.png";
setFileValue("newImage", imageURL);
execute("LoadImageIntoGallery.loadImage");
execute("Gallery.close");
updateFile("photos", "test-images/foto-javi.png");
@View(members="number, description, screenshots, date")
@View(members="number, description; screenshots; date")
@View(members="number, description, attachments, date")
@View(members="number, description; attachments; date")
@View(members=
"datasheet [ #title;" +
" releaseDate, director;" +
" writers, starring;" +
" scripts;" + // FILES
"]"
)
@View(members=
"datasheet [ #title;" +
" releaseDate, director;" +
" writers, starring;" +
"]" +
"scripts [ scripts ]"
)
HtmlPage page = (HtmlPage) getWebClient().getCurrentWindow().getEnclosedPage(); waitAJAX(); // ADD THIS LINE BEFORE USING page
If you tests uses exclusively the methods on ModuleTestBase you don't need to change anything.
Bean Validation 2.0 is compatible with 1.1, so most of your code will continue working as always. However, Bean Validation 2.0 includes some new annotations that were before in Hibernate Validator, so if you imported both Hibernate Validator and Bean Validation maybe some of your code will not compile. For example:
import javax.validation.constraints.*; import org.hibernate.validator.constraints.*; public class MyClass { // @NotBlank // NOW IT PRODUCES COMPILATION ERROR
@javax.validation.constraints.NotBlank // QUALIFY THE ANNOTATION
private String mainStreet;
Now @NotBlank is in both javax.validation.constraints and org.hibernate.validator.constraints. Just remove the org.hibernate.validator.constraints import or, if you still need Hibernate Validator, qualify the @NotBlank annotation (that is use @javax.validation.constraints.NotBlank).
If you uses directly the HtmlUnit API, via getWebClient() or getHtmlPage() from ModuleTestBase, you have to adapt your code to the new HtmlUnit. We have collected here some changes we have noted.
For example, the methods starting by getHtmlElement... now are getElement..., just you need to remove the Html. So, you should change:
HtmlElement iCharts = chartsLink.getHtmlElementsByTagName("i").get(0);
By:
HtmlElement iCharts = chartsLink.getElementsByTagName("i").get(0);
The click() method no longer fires the onclick event. So you have to change:
button.click();
By:
getHtmlPage().executeJavaScript(button.getOnClickAttribute());
Changing the value of a HtmlInput does not throw the onchange event, so you have to change:
input.setValueAttribute(value);By:
input.setValueAttribute(value); if (!Is.emptyString(input.getOnChangeAttribute())) { input.fireEvent(Event.TYPE_CHANGE); }
And possibly more things, consult the HtmlUnit doc.
Because of the new HtmlUnit we no longer have a way to change the language without resetting the module. So maybe you have to adapt some of your tests. For example:
execute("CRUD.new"); ... setLocale("es"); // Here the module is reset execute("CRUD.new"); // ADD THIS LINE ...
In this case the setLocale() reset the module starting in list mode, so we call to CRUD.new in order the test continue working as always.
Given we use JPA API in our applications most of our code will work without any change. However, maybe we find some details that work slightly differently. For example, for this entity definition:
public class Customer { @OneToMany private Collection<Seller> sellers;
The next code no longer works:
customer.setSellers(Collections.emptySet());Now you have to write:
customer.setSellers(new ArrayList<>());
Maybe, you find another little details you have adjust, consult the Hibernate doc. Anyways, we explain the more important ones in the points below.
Hibernate 5.3 has a bug that duplicates the foreign keys if you use hibernate.hbm2ddl.auto=update against the DB you were using with Hibernate 4.3. If you database is tolerant with duplicate foreign keys there is no problem, otherwise you can get some warnings or even errors. By now, the only solution to this is to remove all the foreign keys of your database by hand, so Hibernate creates them correctly on starting.
Since Hibernate 5.3 the next configuration for persistence.xml does not work:
<properties> <property name="hibernate.hbm2ddl.auto" value="update"/> </properties>
You have to define a hibernate.default_schema in order it work correctly. If you don't use a schema just define the default schema for your database, for example PUBLIC for HSQLDB, like this:
<properties> <property name="hibernate.hbm2ddl.auto" value="update"/> <property name="hibernate.default_schema" value="PUBLIC"/> </properties>On the other hand, the updateSchema ant task work nicely even without schema.
With Hibernate 5.3 hibernate.default_schema no longer has effect for MySQL, now you have to use hibernate.default_catalog instead. Since OpenXava 6.1.2 we have modified the OpenXava APIs in order to work as always, recognizing hibernate.default_schema even for MySQL. However, the automatic schema generation on startup (that is hibernate.hbm2dll.auto=update or javax.persistence.schema-generation.database.action=update) is a Hibernate business, so we cannot fix it. If you use it, you should change hibernate.default_schema by hibernate.default_catalog.
Summarizing, if you use MySQL change in persistence.xml:
<properties> <property name="hibernate.hbm2ddl.auto" value="update"/> <property name="hibernate.default_schema" value="COMPANYB"/> </properties>
By:
<properties> <property name="hibernate.hbm2ddl.auto" value="update"/> <property name="hibernate.default_catalog" value="COMPANYB"/> </properties>
Note, hibernate.default_catalog instead of hibernate.default_schema. Only for MySQL.
In Hibernate 5.3 @GeneratedValue(strategy=GenerationType.AUTO) is no longer IDENTITY by default, at least for HSQLDB. So, if you use HSQLDB and don't want to change your tables structure you have to change this:
@Id
@GeneratedValue(strategy=GenerationType.AUTO)// Or just @GeneratedValue private int id;
By this:
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY) private int id;
In your id properties with GenerationType.AUTO.
In Hibernate 5.3 they have changed the method signatures of the type converters, those used in @Type annotation. If you have created your own Hibernate custom converter you have to make some slight modifications in your method signatures, concretely you have to change SessionImplementer by SharedSessionContractImplementor as parameter. For example, you should change this line:
public Object nullSafeGet(ResultSet resultSet, String[] names, SessionImplementor sessionImplementor, Object owner) throws HibernateException, SQLException {
By this one:
public Object nullSafeGet(ResultSet resultSet, String[] names, SharedSessionContractImplementor sessionImplementor, Object owner) throws HibernateException, SQLException {
The same for all methods that use SessionImplementer of any UserType or CompositeUser implementation.
In order the new Hibernate 5.3 works with Liferay you have to create a file portal-ext.properties in the webapps/ROOT/WEB-INF/classes folder of the Tomcat in your Liferay, with the next entry:
portal.security.manager.strategy=none
If you have not modified your Welcome and FirstSteps pages then remove web/naviox/welcome.jsp and web/naviox/firstSteps.jsp from your project before doing the updateOX. If you have your own Welcome or FirstSteps page then edit them to change the references to naviox.css (as explained below) and remove all references to NaviOXStyle Java class that no longer exists.
Moreover, it has been moved from Addons to OpenXava. So, if you use it in some custom JSP, such as welcome.jsp, you have to change:
<link href="<%=request.getContextPath()%>/naviox/style/naviox.css?ox=<%=oxVersion%>"
rel="stylesheet" type="text/css">
<link href="<%=request.getContextPath()%>/xava/style/light.css?ox=<%=oxVersion%>" rel="stylesheet" type="text/css">
Still better you can include the CSS of the current theme instead of an ad hoc CSS, in this way:
<link href="<%=request.getContextPath()%>/xava/style/<%=XavaPreferences.getInstance().getStyleCSS()%>?ox=<%=oxVersion%>" rel="stylesheet" type="text/css">
getView().findObject();
if (!getView().findObject()) { addError("object_with_key_not_found") }
execute("Mode.detailAndFirst"); -- Change by --> execute("List.viewDetail", "row=0");
execute("DetailList.detailAndFirst"); -- Change by --> execute("List.viewDetail", "row=0");
execute("DetailList.list"); -- Change by --> execute("Mode.list");
execute("Mode.split"); // Remove this line from your test, maybe you have to adapt your test
private String [] listActions = {
"Print.generatePdf",
"Print.generateExcel",
"ImportData.importData",
"CRUD.new",
"CRUD.deleteSelected",
"CRUD.deleteRow",
// "Mode.detailAndFirst", // REMOVE THIS LINE
// "Mode.split", // REMOVE THIS LINE
"List.filter",
"List.orderBy",
"List.viewDetail",
"List.hideRows",
"List.sumColumn",
"List.changeConfiguration",
"List.changeColumnName",
"ListFormat.select"
}; assertActions(listActions);
execute("CRUD.new"); execute("Collection.new", "viewObject=xava_view_buildings");
execute("CRUD.new"); setValue("name", "SOMETHING"); // ADD THIS execute("Collection.new", "viewObject=xava_view_buildings");
execute("List.viewDetail", "row=0"); // Instead of: execute("CRUD.new"); execute("Collection.new", "viewObject=xava_view_buildings");
String [] actions = { "Navigation.previous", "Navigation.first", "Navigation.next", "CRUD.new", "CRUD.save", "CRUD.delete", "CRUD.refresh", "Mode.list", "Mode.split", "Collection.new", "Collection.removeSelected", "CollectionCopyPaste.cut", // ADD THIS ENTRY "Print.generatePdf", "Print.generateExcel", "List.filter", "List.orderBy", "List.sumColumn", // ALWAYS PRESENT, EVEN IF COLLECTION IS EMPTY "List.changeColumnName" }; assertActions(actions);
assertValueInList(2, 4, "Yes");You should change it by:
assertValueInList(2, 4, "Paid");If the property label is "Paid".
assertValueInList(2, 4, "No");By:
assertValueInList(2, 4, "");On the other hand if you want to keep the old behavior, just add the next entry in your editors.xml file:
<editor url="booleanEditor.jsp"> <formatter class="org.openxava.formatters.BooleanFormatter" > <set property="nullAsFalse" value="true"/> </formatter> <list-formatter class="org.openxava.formatters.BooleanIconListFormatter" /> <for-type type="boolean" /> <for-type type="java.lang.Boolean" /> </editor>Note the use of BooleanIconListFormatter for list formatter.
private String [] listActions = { "Print.generatePdf", "Print.generateExcel", "ExtendedPrint.myReports", "CRUD.new", "CRUD.deleteSelected", "CRUD.deleteRow", "Mode.detailAndFirst", "Mode.split", "List.filter", "List.orderBy", "List.viewDetail", "List.hideRows", "List.sumColumn", "List.changeConfiguration", "ListFormat.select", "List.changeColumnName", // ADD THIS ENTRY "ImportData.importData" // ADD THIS ENTRY }; assertActions(listActions);
String [] actionsAfterNew = { "Navigation.previous", "Navigation.first", "Navigation.next", "CRUD.new", "CRUD.save", // "CRUD.delete", // REMOVE THIS LINE "CRUD.refresh", "Mode.list", "Mode.split", "List.filter", "List.orderBy", "Print.generatePdf", "Print.generateExcel" }; assertActions(actionsAfterNew);
String [] actions = { "Navigation.previous", "Navigation.first", "Navigation.next", "CRUD.new", "CRUD.save", "CRUD.delete", // "CRUD.search", // REMOVE THIS LINE "CRUD.refresh", "Mode.list", "Mode.split", }; assertActions(actions);If you use CRUD.search in your test you can change it by CRUD.refresh, that is change:
execute("CRUD.search"); setValue("number", "123"); execute("Search.search");By:
setValue("number", "123"); execute("CRUD.refresh");Moreover, if you want that the search action comes back use the new SearchForCRUD controller that just contains the classic seach action. To define a module with search in application.xml add the SearchForCRUD controller:
<module name="Delivery"> <model name="Delivery"/> <controller name="Typical"/> <controller name="SearchForCRUD"/> <!-- ADD THIS LINE --> </module>Another option si to define it in controllers.xml in this way:
<controller name="Author"> <extends controller="Typical"/> <extends controller="SearchForCRUD"/> <!-- ADD THIS LINE --> <action name="doSomething" class="com.mycompany.test.actions.DoSomethingAction" /> </controller>Even if you add the search action back with SearchForCRUD you have to change your JUnit tests because search is no longer in CRUD but in SearchForCRUD. Therefore you have to change:
execute("CRUD.search");By:
execute("SearchForCRUD.search");Also we have a TypicalWithSearch controller that have all the Typical action plus search, just as the old Typical. If you want to use it by default write the next code at the beginning of your application.xml:
<default-module> <controller name="TypicalWithSearch"/> </default-module>
public void testCreateExamWithAtLeastOneQuestion() throws Exception { assertListRowCount(0); // NOW THIS LINE FAILS execute("CRUD.new"); setValue("name", "ADMISSION"); execute("CRUD.save"); ... }If the module has no rows, now it starts in detail mode so the first line will fail. We can just change to list mode at the beginning:
public void testCreateExamWithAtLeastOneQuestion() throws Exception { execute("Mode.list"); // ADD THIS LINE assertListRowCount(0); execute("CRUD.new"); setValue("name", "ADMISSION"); execute("CRUD.save"); ... }Or if you test goes directly to detail mode, like in this example, just remove the first part of the test:
public void testCreateExamWithAtLeastOneQuestion() throws Exception { // assertListRowCount(0); // REMOVE THIS LINE // execute("CRUD.new"); // REMOVE THIS LINE setValue("name", "ADMISSION"); execute("CRUD.save"); ... }
private String [] listActions = { "Mode.detailAndFirst", "Mode.split", "List.filter", "List.orderBy", "List.viewDetail", "List.hideRows", "List.sumColumn", // "List.changeConfigurationName" // REMOVE THIS ENTRY "List.changeConfiguration" // ADD THIS ENTRY }; assertActions(listActions);
@Entity public class Invoice { private int year; private int number; private Date date; @ManyToOne private Customer customer; @Stereotype("FILES") @Column(length=32) private String files; ... }In previous versions we get in list: year, number, date, files
@NewAction("Invoice.addDeliveries") @OneToMany(mappedBy="invoice") private Collection<Delivery> deliveries;By:
@AddAction("Invoice.addDeliveries") @OneToMany(mappedBy="invoice") private Collection<Delivery> deliveries;
execute("Collection.view", "row=1,viewObject=xava_view_customers");By:
execute("Collection.edit", "row=1,viewObject=xava_view_customers");Note, now it's not "Collection.view" but "Collection.edit".
assertLabelInList(4, "Name of Customer");By this:
assertLabelInList(4, "Customer");
private String [] listActions = { "Print.generatePdf", "Print.generateExcel", // REMOVE THIS LINE "ExtendedPrint.myReports", "CRUD.new", "CRUD.deleteSelected", ... }; assertActions(listActions);Though the action is not available by default, it still exists in OpenXava and works perfectly. Indeed there is a new controller TypicalExtendedPrint to facilitate its use. If you want to continue using the My reports feature just change Typical by TypicalExtendedPrint in your application.xml and controllers.xml, even you can declare it as default controller.
private String [] listActions = { "Mode.detailAndFirst", "Mode.split", "List.filter", "List.orderBy", "List.viewDetail", "List.hideRows", "List.sumColumn", "List.changeConfigurationName" // ADD THIS ENTRY }; assertActions(listActions);
protected void setUp() throws Exception { createEntitiesUsingJPA(); // Now it fails, because JPA is not still initialized super.setUp(); }Change it by:
protected void setUp() throws Exception { super.setUp(); // JPA is initialized here createEntitiesUsingJPA(); }
form.getSelectByName("ox_MyApp_MyModule__myReference___id").setSelectedAttribute("TheValue", true);By:
HtmlInput comboInput = form.getInputByName("ox_MyApp_MyModule__myReference___id"); comboInput.setValueAttribute("TheValue"); ((HtmlInput) comboInput.getPreviousElementSibling()).setValueAttribute("Something"); // A trick to avoid that JavaScript reset the real value ((HtmlInput) comboInput.getNextElementSibling()).setValueAttribute("Something"); // A trick to avoid that JavaScript reset the real value
<action name="delete" mode="detail" confirm="true" class="com.mycompany.myapp.actions.MyDeleteAction" image="delete.gif" keystroke="Control D"/>By this:
<action name="delete" mode="detail" confirm="true" class="com.mycompany.myapp.actions.MyDeleteAction" icon="delete" keystroke="Control D"/>To see all available icons look at Material Design Icons.
useIconsInsteadOfImages=falseThen all the actions, included the standard ones, will use the old colorful images.
<property name="schema.path" value="../OpenXavaTest/lib/hsqldb.jar"/>
By this:<property name="schema.path" value="../OpenXava/lib/hsqldb.jar"/>
public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException {By:
public Object nullSafeGet(ResultSet resultSet, String[] names, SessionImplementor sessionImplementor, Object owner) throws HibernateException, SQLException {And this:
public void nullSafeSet(PreparedStatement ps, Object value, int index) throws HibernateException, SQLException {By:
public void nullSafeSet(PreparedStatement ps, Object value, int index, SessionImplementor sessionImplementor) throws HibernateException, SQLException {Of course, if you call these methods you have to adapt the calling code too. For example, a code like this:
((UserType) hibernateType).nullSafeSet(ps, o, 1);Now it would be:
((UserType) hibernateType).nullSafeSet(ps, o, 1, null);Note that sending a null for the new extra parameter is enough.
<persistence-unit name="default" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <property name="hibernate.ejb.cfgfile" value="/hibernate-jpa.cfg.xml"/> <!-- REMOVE THE NEXT LINES <property name="hibernate.ejb.event.pre-insert" value="org.openxava.hibernate.impl.CalculatorsListener, org.openxava.hibernate.impl.ReferenceConverterToDBListener, org.openxava.hibernate.impl.DefaultValueCalculatorsListener"/> <property name="hibernate.ejb.event.pre-update" value="org.openxava.hibernate.impl.CalculatorsListener, org.openxava.hibernate.impl.ReferenceConverterToDBListener"/> <property name="hibernate.ejb.event.pre-delete" value="org.openxava.hibernate.impl.CalculatorsListener"/> <property name="hibernate.ejb.event.post-load" value="org.openxava.hibernate.impl.CalculatorsListener"/> --> </properties> </persistence-unit>Also if you use XML components you no longer can have a reference used as key if the value does not exist in the referenced table. This case is no longer allowed by Hibernate. This case has never been supported in JPA. You should think in a different way of solving your issue, such as adding an autogenerated key or creating the corresponding row in the referenced table.
<persistence-unit name="default"> ... <properties> ... <!-- Add the next entry --> <property name="hibernate.connection.release_mode" value="after_transaction"/> </properties> </persistence-unit>
import org.hibernate.validator.*;By:
import javax.validation.constraints.*; import org.hibernate.validator.constraints.*;In the case of @Digits apart of changing the above imports you have to change the parameter names, changing this:
@Digits(integerDigits=10, fractionalDigits=6)By:
@Digits(integer=10, fraction=6)You cannot longer use InvalidStateException of Hibernate Validator 3. Therefore, if you use it to throw a validation error from your entity or action you have to change it by other exception. For example, a code like this:
@PreRemove public void validateOnRemove() { if (number == 1) { throw new InvalidStateException( new InvalidValue [] { new InvalidValue( "one_not_deletable", getClass(), "number", getNumber(), this) } ); } }Now it could be written in this way:
@PreRemove public void validateOnRemove() { if (number == 1) { throw new javax.validation.ValidationException("one_not_deletable"); } }If you have defined your own validator with the Old Hibernate Validator you should rewrite it using the Bean Validation standard. Don't worry, converting it is very easy. In your annotation change @ValidatorClass by @Constraint and add groups() and payload(), thus:
@Constraint(validatedBy = MyValidator.class) // Instead of @ValidatorClass(PropertyValidatorValidator.class) public @interface MyAnnotation { ... // Add the next code Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }And in the validator class change this:
public class RequiredValidator implements Validator<Required> {By:
public class RequiredValidator implements ConstraintValidator<Required, Object> {And this:
public boolean isValid(Object value) {By:
public boolean isValid(Object value, ConstraintValidatorContext context) {You can keep the rest of your code as is.
try { XPersistence.commit(); } catch (RollbackException ex) { if (ex.getCause() instanceof InvalidStateException) { InvalidStateException iex = (InvalidStateException) ex.getCause(); int invalidValuesCount = iex.getInvalidValues().length; String property = iex.getInvalidValues()[0].getPropertyName(); String message = iex.getInvalidValues()[0].getMessage(); ... } }You should write it in this way:
try { XPersistence.commit(); } catch (RollbackException ex) { if (ex.getCause() instanceof ConstraintViolationException) { ConstraintViolationException cex = (ConstraintViolationException) ex.getCause(); int invalidValuesCount = cex.getConstraintViolations().size(); ConstraintViolation v = cex.getConstraintViolations().iterator().next(); String property = v.getPropertyPath().toString()); String message = v.getMessage()); ... } }
<non-jta-data-source>java:comp/env/jdbc/YourApplicationDS</non-jta-data-source>By this:
<non-jta-data-source>java://comp/env/jdbc/YourApplicationDS</non-jta-data-source>And in hibernate.cfg.xml change this:
<property name="hibernate.connection.datasource">java:comp/env/jdbc/YourApplicationDS</property>By this:
<property name="hibernate.connection.datasource">java://comp/env/jdbc/YourApplicationDS</property>Note the // before comp. If you use JNDI names in other places you shoud change them too. The good thing is that newer Tomcat versions also work in this way, so if you use always this notation your application will work in any Tomcat.
public class OrderLogic { @Formula("productPrice * qtyOrdered") public void deriveAmount() { } }Remove the above class and move the calculation in @Formula annotation to a @PrePersist and @PreUpdate method in the entity, thus:
@Entity public class Order { ... @PrePersist @PreUpdate private void deriveAmount() { amount = new BigDecimal(qtyOrdered).multiply(productPrice); } }Furthermore, you have to remove the next entry from your persistence.xml:
<property name="hibernate.current_session_context_class" value="com.autobizlogic.abl.session.LogicThreadLocalSessionContext"/>
<!-- Generates the schema from scratch. Shows it in console, but does not execute it --> <target name="generateSchema"> <ant antfile="../OpenXava/build.xml" target="generateSchemaJPA"> <property name="persistence.unit" value="junit"/> <!-- ADD THE NEXT LINE FOR V5.3 --> <property name="schema.path" value="../OpenXavaTest/lib/hsqldb.jar"/> </ant> </target>
Invoice invoice = (Invoice) getView().getEntity(); if (invoice.getCustomer().getNumber() == 0) { // In v5.2 if customer is empty an empty customer is returnedBy:
Invoice invoice = (Invoice) getView().getEntity(); if (invoice.getCustomer() == null) { // In v5.2.1 if customer is empty a null is returned
getWebClient().setCssEnabled(true);By:
getWebClient().getOptions().setCssEnabled(true);And:
HtmlElement console = getHtmlPage().getElementById("xava_console");By:
HtmlElement console = getHtmlPage().getHtmlElementById("xava_console");And many more things. Unfortunately, HtmlUnit team refactor their library in each new minor version, so HtmlUnit is never backward compatible.
@DefaultValueCalculator( value=UnitPriceCalculator.class, properties=@PropertyValue( name="productNumber", from="product.number") ) private BigDecimal unitPrice;With versions previous to 5.1 when product.number changes unitPrice is recalculated only if it has not value yet. Since version 5.1 unitPrice is recalculated always that product.number changes.
@OnChange(OnChangeProductRecalculateUnitPriceAction.class) private Product product; private BigDecimal unitPrice;
autologinUser=admin autologinPassword=adminIn this way your tests will run fine without recode them.
public void testMyTest() throws Exception { login("admin", "admin"); ... }
<filter> <filter-name>naviox</filter-name> <filter-class>com.openxava.naviox.web.NaviOXFilter</filter-class> </filter> <filter-mapping> <filter-name>naviox</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping> <filter-mapping> <filter-name>naviox</filter-name> <servlet-name>naviox</servlet-name> </filter-mapping> <filter-mapping> <filter-name>naviox</filter-name> <servlet-name>module</servlet-name> </filter-mapping>Also change:
<servlet> <servlet-name>naviox</servlet-name> <servlet-class>com.openxava.naviox.web.NaviOXServlet</servlet-class> </servlet>By:
<servlet> <servlet-name>modules</servlet-name> <servlet-class>org.openxava.web.servlets.ModuleServlet</servlet-class> </servlet>And change:
<servlet-mapping> <servlet-name>naviox</servlet-name> <url-pattern>/modules/*</url-pattern> </servlet-mapping>By:
<servlet-mapping> <servlet-name>modules</servlet-name> <url-pattern>/modules/*</url-pattern> </servlet-mapping>Finally remove:
<servlet-mapping> <servlet-name>naviox</servlet-name> <url-pattern>/m/*</url-pattern> </servlet-mapping>With the above changes in OpenXava/web.xml you have removed the menus and login. You must execute updateOX ant target to update the web.xml of your project.
styleClass=org.openxava.web.style.Liferay51Style styleCSS=liferay51/css/everything_unpacked.css
<module name="FilterByMonth"> <model name="FilterByMonth"/> <controller name="FilterByMonth"/> </module>Anyways, always it has been needed to declare the modules for transient classes in order to generate portlets, therefore if you work with portals you already have the modules defined.
javaLoggingLevel=FINESTBy:
javaLoggingLevel=FINEIf you want to keep a moderate amount of trace.
Objects.execute(myObject, "doSomething");Instead now you have to write:
XObjects.execute(myObject, "doSomething");
public class MyModuleTest extends ModuleTestBase { ... @Override protected String getModuleURL() { // return super.getModuleURL() + "?myParameter=5"; // With ? in v4.x.x return super.getModuleURL() + "&myParameter=5"; // With & in v5.0 } }
@Digits(integer=10) private BigDecimal amount;With v4.x it had 2 fraction digits because default scale for BigDecimal is 2. However, since v5.0 it has 0 digits, because not specifying fraction is equals to write fraction=0. This allows you to have BigDecimal numbers with 0 for fraction part, but it could do than some of your existing numeric properties stop to use 2 fraction digits. To fix it, just specify fraction explicitly, thus:
@Digits(integer=10, fraction=2) private BigDecimal amount;
assertValue("myBigDecimalNumber", "20");by this:
assertValue("myBigDecimalNumber", "20.00");
assertPopupPDFLinesCount(5); // Maybe now there are 6 lines, because the header uses 2 lines
@View(members= ... "remarks { advice, shortcut; remarks }" ... )Where the remarks property is inside a remarks section. Until now if you write this:
getView().setHidden("remarks", true);You hid the remarks property, however since OpenXava 4.8.1 you'll hide the remarks section. In this case, if you still want to hide the property and not the section you should rename the section, as following:
@View(members= ... "comment { advice, shortcut; remarks }" ... )
int[] selected = tab.getSelected(); for (int i = 0; i < selected.length; i++){ Map key = (Map) tab.getTableModel().getObjectAt(selected[i]); .... }by:
Map[] selected = tab.getSelectedKeys(); for (int i = 0; i < selected.length; i++){ Map key = selected[i]; .... }
my_message=It can't be in that wayby
my_message=It can''t be in that wayNote, you have to change ' by ''.
<input id="<%=propertyKey%>" name="<%=propertyKey%>" class="<%=style.getEditor()%> <%=numericClass%>" type="<%=inputType%>" tabindex="1" <!-- Now, you have put this--> ... />
baseCondition = "select NUMBER, DESCRIPTION, FAMILY.DESCRIPTION " + "from XAVATEST.SUBFAMILY, XAVATEST.FAMILY " + "where SUBFAMILY.FAMILY = FAMILY.NUMBER"You have to rewrite it in this way:
baseCondition = "select e.number, e.description, f.description " + "from Subfamily e, Family f " + "where e.familyNumber = f.number"The syntax of JPQL and SQL is very alike, usually you will not need to do big changes other that using property and entity names intestad of column and table names. You have to use e as alias for the main entity.
@DescriptionsList( // It does not works because THINGID is a column name, so JPA does not recognized it condition="${thing.number} = (SELECT THINGID FROM ${Thing} WHERE name = 'CAR')" )The solution is using property names instead of column names, in this case changing THINGID by number is enough to fix the problem:
@DescriptionsList( // It works because we use the property name, number, instead of THINGID condition="${thing.number} = (SELECT number FROM ${Thing} WHERE name = 'CAR')" )Another option is to write the complete sentence in pure JPQL, given that the ${} are no longer required, as following:
@DescriptionsList( // We can use a pure JPQL query without ${propertyName} condition="e.thing.number = (SELECT t.number FROM Thing t WHERE t.name = 'CAR')" )If you use JPQL you have to use e as alias for the main entity.
public class MyOnSelectElementAction extends OnSelectElementBaseAction { public void execute() throws Exception { doSomethingThatModifiesTheCollection(); getView().refreshCollections(); // Since v4.5 you have to add this line } }
private String [] listActions = { "Mode.detailAndFirst", "Mode.split", "List.filter", "List.customize", "List.orderBy", "List.viewDetail", "List.hideRows", "List.sumColumn" // ADD THIS ENTRY }; assertActions(listActions);
<for-type type="boolean" converter-class="org.openxava.converters.Boolean01Converter" cmp-type="java.lang.Integer"/> <for-type type="java.lang.Boolean" converter-class="org.openxava.converters.Boolean01Converter" cmp-type="java.lang.Integer"/>Remember, adding these lines is rarely necessary, regenerating code must be enough. If you application is a JPA application (the usual case) you do not need to do anything.
public class Delivery { @Id @Column(length=5) private int number; @Id @ManyToOne(fetch=FetchType.LAZY) private DeliveryType type; // The type must exist in the database always ... }The reference to DeliveryType must exist always in the database.
Delivery delivery = new Delivery(); DeliveryType deliveryType = new DeliveryType(); // We create a new DeliveryType, // instead of searching it deliveryType.setNumber(66); // The DeliveryType 66 already exist in database delivery.setType(deliveryType); ... XPersistence.getManager().persist(delivery);But, this does not work with Hibernate 3.6, instead you have to write it in the next way:
Delivery delivery = new Delivery(); DeliveryType deliveryType = XPersistence.getManager() .find(DeliveryType.class, 66); // We searh it delivery.setType(deliveryType); XPersistence.getManager().persist(delivery);
@Entity @IdClass(CustomerContactPersonKey.class) public class CustomerContactPerson { @Id @ManyToOne(fetch=FetchType.LAZY) private Customer customer; // No more @Id fields ... }And the reference to it in this way:
@ManyToOne(fetch=FetchType.LAZY) @JoinColumn(name="CUSTOMERCONTACT") // With no referencedColumnName attribute private CustomerContactPerson customerContactPerson;And it worked fine. However, with Hibernate 3.6 this does not work. Fortunately, there is a way of achieving the same effect. Just write your entity in this way:
@Entity // @IdClass is no longer used public class CustomerContactPerson implements java.io.Serializable { // Must implement Serializable @Id @ManyToOne(fetch=FetchType.LAZY) private Customer customer; // No more @Id fields ... }And the reference in this way:
@ManyToOne(fetch=FetchType.LAZY) @JoinColumns({ @JoinColumn(name="CUSTOMERCONTACT", referencedColumnName="CUSTOMER_NUMBER") // referencedColumnName is mandatory }) private CustomerContactPerson customerContactPerson;
@Entity @Table(name = "`TABLES`") @DiscriminatorColumn(name="ID", discriminatorType=DiscriminatorType.STRING, length=20)This would work without problem in 3.4, but will complain in 3.6 (and I believe in 3.5 too). You have to use a Hibernate annotation @DiscriminatorOptions like this:
@Entity @Table(name = "`TABLES`") @DiscriminatorColumn(name="ID", discriminatorType=DiscriminatorType.STRING, length=20) @DiscriminatorOptions(insert = false) // <-- Hibernate dependent annotationAnd it will work.
String host = getProperty("host"); // Until v4m5 // Must be replace with String host = getXavaJUnitProperty("host"); // Since v4m6This change was needed to allow using Groovy to write JUnit tests.
<module name="ChangeProductsPrice"> <model name="Product"/> <controller name="Navigation"/> <!-- You have to add this --> <controller name="ChangeProductsPrice"/> </module>
String [] listActions = { "Print.generatePdf", "Print.generateExcel", "CRUD.new", "CRUD.deleteSelected", "Mode.detailAndFirst", "Mode.split", // YOU HAVE TO ADD THIS "List.filter", "List.customize", "List.orderBy", "List.viewDetail", "List.hideRows", }; assertActions(listActions);If you do not like this new split mode, you can remove it from your aplication adding the next entry in xava.properties:
defaultModeController=DetailListIn this case the mode controller is not Mode but DetailList, this implies that you have to change your junit tests:
// execute("Mode.list"); // NO if defaultModeController=DetailList in xava.properties execute("DetailList.list"); // OK if defaultModeController=DetailList in xava.properties
// execute("CRUD.deleteSelected", "row=2"); // NO, since 4m5 execute("CRUD.deleteRow", "row=2"); // YESMoreover, given that CRUD.deleteRow is available by default for all module, if you use assertActions() in your tests maybe you have to add it to the list of actions.
public class MySearchAction extends ViewBaseAction { public void execute() throws Exception { ... getView().setKeyEditable(false); // You have to call setKeyEditable() getView().setEditable(true); // and setEditalbe() explicitly ... } }
setValue("number", "1"); execute("CRUD.search"); assertValue("description", "Number one");It does not work now. You must rewrite it. To do it, you have 2 options. The first one is to adapt your test to the new CRUD.search action behavior:
execute("CRUD.search"); // It shows a dialog setValue("number", "1"); execute("Search.search"); // It does the search and close the dialog assertValue("description", "Number one");The second option is changing "CRUD.search" by "CRUD.refresh", since the old CRUD.search has been renamed as CRUD.refresh:
setValue("number", "1"); execute("CRUD.refresh"); // Instead of CRUD.search assertValue("description", "Number one");Moreover, given that CRUD.refresh is available by default for all modules, if you use assertActions() in your tests maybe you have to add it to the list of actions.
Map values = MapFacace.getValues("Person", key, members); values.remove(MapFacade.MODEL_NAME); // Maybe you need this line
Classes.getSimpleName(theClass);by this:
theClass.getSimpleName();
public class MyCollectionDetailAction extends ViewBaseAction { public void execute() throws Exception { ... getView().setValue("name", "Pepe"); // Now getView() is the dialog view getPreviousView().setValue("name", "Pepe"); // getPreviousView() is the // view has opened the dialog closeDialog(); } }That is, maybe you have to change getView() by getPreviousView() in some of your action.
// details is the name of the collection setValue("details.quantity", "6"); // Now WRONG! You have to remove 'details' setValue("quantity", "6"); // CORRECT! Without collection nameAlso the actions available on editing a collection element (so inside a dialog) do not use any argument:
execute("Collection.save", "viewObject=xava_view_section1_details"); // WRONG! execute("Collection.save"); // CORRECT!If you want to access to the actions or members of the main view, you have to close the dialog first:
execute("Invoice.editDetail", "row=1,viewObject=xava_view_section1_details"); assertValue("quantity", "234"); closeDialog(); // Needed before executing CRUD.save execute("CRUD.save");When you save the collection element the dialog is closed, so if you want to add another detail you have to open the dialog again:
execute("Collection.save"); // This closes the dialog execute("Collection.new", // It's needed to call to 'new' again, to open the dialog "viewObject=xava_view_section1_details");In nested collections you have to change the value of viewObject argument of the row actions, again because now it inside of a dialog that is itself the root view:
execute("Collection.new", "viewObject=xava_view_deliveryPlaces_receptionists"); // WRONG! execute("Collection.new", "viewObject=xava_view_receptionists"); // CORRECT! Only the last // nested collection nameThis does not only appies to viewObject but also to other references to a nested collection in action argument. See the next example:
// WRONG: Using "deliveryPlaces.receptionists", the full qualified name setConditionValues("deliveryPlaces.receptionists", new String[] { "J"} ); execute("List.filter", "collection=deliveryPlaces.receptionists"); assertCollectionRowCount("deliveryPlaces.receptionists", 1); assertValueInCollection("deliveryPlaces.receptionists", 0, 0, "JUAN"); // CORRECT: Using "receptionists", the simple name setConditionValues("receptionists", new String[] { "J"} ); execute("List.filter", "collection=receptionists"); assertCollectionRowCount("receptionists", 1); assertValueInCollection("receptionists", 0, 0, "JUAN");In general, if your test fails try to remove the collection name as prefix from member name, action argument, etc.
// Only for collections of entities with no @AsEmbedded execute("Collection.edit", "row=0,viewObject=xava_view_customers"); // WRONG! 'edit' is not longer used execute("Collection.view", "row=0,viewObject=xava_view_customers"); // CORRECT! Now 'view' action is usedThis also implies that the view for element has not editable the key properties and has no delete action. Maybe you have to adapt your test:
// Inside the dialog that displays the collection element assertEditable("number"); // WRONG! Key fields are not editable execute("Collection.remove"); // WRONG! 'remove' action are not availableThis change does not apply to collection with @AsEmbeddable, CascadeType.REMOVE or CascadeType.ALL.
public class MyAction extends BaseAction implements IModuleContextAction { public void setContext(ModuleContext context) { super.setContext(context); // You must add this line this.context = context; } }Another option is to remove the implements IModuleContextAction and the setContext() method, and to use getContext(), protected method from BaseAction to access to the context.
<controller name="MyReference"> <action name="search" hidden="true" show-dialog="true" class="org.openxava.test.actions.MySearchAction" image="images/search.gif"> <use-object name="xava_view"/> <use-object name="xava_referenceSubview"/> <!-- This line must be removed <use-object name="xava_currentReferenceLabel"/> --> <use-object name="xava_tab"/> </action> </controller>Also it's convenient for search actions and other reference actions to use show-dialog="true" (show-dialog has been dropped in v4m2) in order to show the searching in a dialog, such as the standard OX search actions.
execute("Delivery.generateNumber", "xava.keyProperty=xava.Delivery.number");by
execute("Delivery.generateNumber", "xava.keyProperty=number");Just deleting xava.Delivery in this case.
HtmlImage image = (HtmlImage) page.getHtmlElementsByName("xava.Formula.ingredients.image").get(0);You need to change by the next code:
HtmlImage image = (HtmlImage) page.getHtmlElementsByName(decorateId("ingredients.image")).get(0);You use here decorateId(). Also note the you have to remove the prefix xava.Formula.
<script> function showMap(v) { ... } </script> <!-- JSP code here -->You have to move it to custom-editors.js, in this way:
if (openxava == null) var openxava = {}; if (openxava.editors == null) openxava.editors = {}; // googleMapEditor if (openxava.editors.googleMap == null) openxava.editors.googleMap = {}; openxava.editors.googleMap.showMap = function(v){ ... }And now inside your editor instead of calling to the function in this way:
<input ... onclick="showMap(value)"/>
you have to do it qualifiying the function:<input ... onclick="openxava.editors.googleMap.showMap(value)"/>
// It's not a collection action public class TranslateAllCarrierNameAction extends ViewBaseAction { public void execute() throws Exception { for (Iterator it=Carrier.findAll().iterator(); it.hasNext(); ) { Carrier c = (Carrier) it.next(); c.translate(); // Carrier is modified, // these data are show currently in a collection of the view } getView().refreshCollections(); // To refresh the data of the // displayed collections } }That is, maybe you need to add getView().refreshCollections() if the collection data are not refreshed after executing your action.
execute("Reference.search", "keyProperty=xava.Carrier.warehouse.zoneNumber");and the link in the page has keyProperty=xava.Carrier.warehouse.number, that is, it's not exactly equal; in the case of the HttpUnit it works, but in the case of the HtmlUnit it does not work. You cannot execute actions that are not available to the users by means of links or buttons, moreover your test must execute the action exactly in the same way that the user do it.
allowDuplicateSubmit(); click("MyController.myAction");Calling to allowDuplicateSubmit() is mandatory before to use click(). The click() method throw the events associated to the button or link but does not work well in many cases. From now on, using HtmlUnit, the execute() just simulates a click(), and does it well, so click() and allowDuplicateSubmit() are no longer needed. If you have a code as the above one, you can replace it for something as this:
execute("MyController.myAction");
String [] condition = { " ", "", "", "V" }; setConditionValues(condition);When you want to fill the 4th element and the 2nd one was a combo (an enum or boolean). Note that you need to put a blankspace in the first one, really in all before the combo. This tricky, needed because of HttpUnit, is no longer needed. Now you can write this:
String [] condition = { "", "", "", "V" }; setConditionValues(cndition);Without bother about blankspaces. Though spaces are still allowed.
assertError("Object of type Invoice does not exists with that key");by
assertError("Object of type Invoice does not exists with key Year:2008, Number:1");
@Entity public class Customer { @Required private int number; @Required private String name; @Required private String remarks; ... }And you run the next code:
Customer c = new Customer(); c.setNumber(1); c.setName("JUANITO"); // We left remarks property empty XPersistence.getManager().save(c); XPersistence.commit();The code works with OX3.0, but fails with OX3.0.1, because in OX3.0.1 the @Required constraint is enforced when you save using JPA. In OX3.0, and older, validation was applied only when you save using OpenXava (con MapFacade, or OX standard action).
execute("Sections.change", "activeSection=2"); ... execute("CRUD.new"); setValue("propertyInSection2", "the value"); // This property is in section 2In this case you have to return to the section 2 explicitly:
execute("Sections.change", "activeSection=2"); ... execute("CRUD.new"); // You must add the next line, because after 'new' we are in section 0 execute("Sections.change", "activeSection=2"); setValue("propertyInSection2", "the value"); // This property is in section 2
persistenceProviderClass=org.openxava.model.impl.HibernatePersistenceProvider
try { MapFacade.validate("Invoice", values); } catch (RemoteException ex) { ... }Then you must change the RemoteException by a SystemException:
try { MapFacade.validate("Invoice", values); } catch (SystemException ex) { ... }Moreover, XavaException is now a runtime exception. But this does not requires any change in your code.
MapFacade.create("Customer", customerValues); MapFacade.create("Invoice", invoiceValues);These two lines were two transaction. If the invoice creation fails the customer was saved. That is, MapFacade had an autocommit police.
mapFacadeAutoCommit=trueSecond option: commit the transaction manually. For example, the above code can be write in this way:
MapFacade.create("Customer", customerValues); MapFacade.commit(); MapFacade.create("Invoice", invoiceValues); MapFacade.commit();
images.table=XAVATEST.IMAGESNow you write this instead:
images.schema=XAVATEST
images.table=IMAGES
assertLabelInList(2, "Name"); // for customer.namenow must write:
assertLabelInList(2, "Name of Customer"); // for customer.name
assertValue("amount", "20");by this one:
assertValue("amount", "20.00");Or, if your prefer the old formatting style you can deactivate the formatter or use another editing your editors.xml file.
execute("Reference.createNew", "model=Family2,keyProperty=xava.Product2.family.number"); assertAction("Mode.list"); // Since 2.2.1 it failsThe assertAction("Mode.list") has to be removed.
execute("Collection.new", "viewObject=xava_view_customers"); setValue("customers.number", getCustomerNumber2()); assertValueIgnoringCase("customers.name", getCustomer2().getName()); assertCollectionRowCount("customers",0); execute("Collection.save", "viewObject=xava_view_customers"); assertCollectionRowCount("customers",1);by this one:
assertCollectionRowCount("customers",0); execute("Collection.add", "viewObject=xava_view_customers"); assertValueInList(5, 0, getCustomer2().getName()); execute("AddToCollection.add", "row=5"); assertMessage("1 element(s) added to Customers of Seller"); assertCollectionRowCount("customers",1);Moreover, now the user can add several entities at once, thus a code as this:
execute("Collection.new", "viewObject=xava_view_customers"); setValue("customers.number", getCustomerNumber1()); assertValueIgnoringCase("customers.name", getCustomer1().getName()); assertCollectionRowCount("customers", 0); execute("Collection.save", "viewObject=xava_view_customers"); assertMessage("Customer associated to Seller"); assertCollectionRowCount("customers", 1); setValue("customers.number", getCustomerNumber2()); assertValueIgnoringCase("customers.name", getCustomer2().getName()); execute("Collection.save", "viewObject=xava_view_customers"); assertCollectionRowCount("customers",2);can be done in this way:
execute("Collection.add", "viewObject=xava_view_customers"); assertValueInList(4, 0, getCustomer1().getName()); assertValueInList(5, 0, getCustomer2().getName()); checkRow(4); checkRow(5); execute("AddToCollection.add"); assertMessage("2 element(s) added to Customers of Seller"); assertCollectionRowCount("customers",2);
execute("Collection.save", "viewObject=xava_view_section1_details"); execute("Collection.new", "viewObject=xava_view_section1_details"); // To removeby this one:
execute("Collection.save", "viewObject=xava_view_section1_details");That is, remove the "Collection.new" call, because after save the detail, the "new" action is automatically executed, thus the user interface is ready to enter a new detail.
String [] actions = { "Navigation.previous", "Navigation.first", "Navigation.next", "CRUD.new", "CRUD.save", "CRUD.delete", "CRUD.search", "Collection.new", "Collection.removeSelected" }; assertActions(actions);you must change it by:
String [] actions = { "Navigation.previous", "Navigation.first", "Navigation.next", "CRUD.new", "CRUD.save", "CRUD.delete", "CRUD.search", "Collection.new", "Collection.removeSelected", "List.filter", // New "List.orderBy", // New "List.customize", // New "List.hideRows", // New "Print.generatePdf", // New "Print.generateExcel" // New }; assertActions(actions);
<target name="generarPortlets"> <ant antfile="../OpenXava/build.xml" target="generarPortlets"/> </target>Must change it by:
<target name="generarPortlets"> <ant antfile="../OpenXava/build.xml" target="generatePortlets"/> </target>
public void testSomething() throws Exception { assertValue("number", ""); execute("MyControllers.myAction"); // This does not change number value assertValue("number", "0"); // because OX parse empty string as 0 (until 2.1.2) ... }You now have to write in this way:
public void testSomething() throws Exception { assertValue("number", ""); execute("MyControllers.myAction"); // This does not change number value assertValue("number", ""); // because now (since 2.1.3) OX parse empty string as null ... }
<session-factory> <property name="hibernate.connection.datasource">@datasource.prefix@/@datasource@</property> <property name="hibernate.dialect">@hibernate.dialect@</property> <property name="hibernate.jdbc.use_get_generated_keys">false</property> <property name="hibernate.show_sql">false</property> @hibernate.properties@ ... </session-factory>Second, in your configuration file for websphere (for example websphere-as400.properties) you have to add:
hibernate.properties=<property name="hibernate.transaction.manager_lookup_class">\n\ \t\t\torg.hibernate.transaction.WebSphereTransactionManagerLookup\n\ \t\t</property>\n\ \t\t<property name="transaction.factory_class">\n\ \t\t\torg.hibernate.transaction.JTATransactionFactory\n\ \t\t</property>
DrivingLicenceKey key = new DrivingLicenceKey(); key.setType("C "); key.setLevel(1); setValue("drivingLicence.KEY", key.toString());But, if you uses a pure POJOs version, without Key classes, you have to write:
DrivingLicence key = new DrivingLicence(); key.setType("C "); key.setLevel(1); setValue("drivingLicence.KEY", key.toString());It's better to use the last way, because it's valid for POJOs and EJBs.
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.datasource">@datasource.prefix@/@datasource@</property> <property name="hibernate.dialect">@hibernate.dialect@</property> <property name="hibernate.show_sql">false</property> </session-factory> </hibernate-configuration>In addition you have to include the hibernate.dialect property in your configuration files:
hibernate.dialect=org.hibernate.dialect.HSQLDialect
Customer customer = CustomerUtil.getHome().findByName("PEPE"); String name = customer.getName();By this:
ICustomer customer = CustomerUtil.getHome().findByName("PEPE"); String name = customer.getName();If you use specific EJB methods then you need cast to remote interface:
Customer customer = CustomerUtil.getHome().findByName("PEPE"); CustomerKey key = customer.getPrimaryKey();By this:
CustomerRemote customer = CustomerUtil.getHome().findByName("PEPE"); CustomerKey key = customer.getPrimaryKey();That is, change Customer by ICustomer when possible, if not possible change Customer by CustomerRemote.