Skip to content
Permalink
Browse files
Implemented: REST, adding segmented URI support for webtools/entitymaint
(OFBIZ-11007)

After implemeted Rest mechanism on rev. 1868963 by Mathieu Lirzin,
I reviewed the rest url implemented by Artemiy Rozovyk for entitymaint in webtools.

With discussion with Mathieu and Leila, I selected this pattern :

    entity/[cover]/{entityName}/{pkValues: .*}

and implemented like this :

    entity/list -> list all entities
    entity/find/Party -> search
    entity/find/Party/Company -> displaying form for Party with id Company
    entity/create/Party -> creation form for a Party
    entity/edit/Party/Company/Company -> edit form for Party with id Company
    entity/change/Party/Company -> call crud following given http method
    entity/relations/Party -> View relation for Party

The old uris were currently kept and the oldest GenericWebEvent.updateGeneric() were updated to support rest method information.

Thanks Mathieu, Artemiy and Leila for their help to complete this improvement.
  • Loading branch information
nmalin committed Jan 9, 2020
1 parent c3d53e6 commit 6e1c7b5958cc1a80be5746bfd177136a1feabe0d
@@ -100,6 +100,10 @@
<value xml:lang="zh">无法删除(写错误)</value>
<value xml:lang="zh-TW">無法刪除(寫錯誤)</value>
</property>
<property key="genericWebEvent.delete_succeeded">
<value xml:lang="en">Delete succeeded</value>
<value xml:lang="fr">La suppression a été effectuée: </value>
</property>
<property key="genericWebEvent.entity_name_not_specified">
<value xml:lang="en">The entityName was not specified, but is required</value>
<value xml:lang="es">El nombre de la entidad no fue especificado, pero es requerido</value>
@@ -41,8 +41,9 @@ if (modelEntity) {
ModelReader entityModelReader = delegator.getModelReader()
//create the search form with auto-fields-entity
String dynamicAutoEntityFieldSearchForm = """<?xml version="1.0" encoding="UTF-8"?><forms xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://ofbiz.apache.org/Widget-Form" xsi:schemaLocation="http://ofbiz.apache.org/Widget-Form http://ofbiz.apache.org/dtds/widget-form.xsd">
<form name="FindGeneric" type="single" target="FindGeneric?entityName=${entityName}">
<form name="FindGeneric" type="single" target="entity/find/${entityName}">
<auto-fields-entity entity-name="${entityName}" default-field-type="find" include-internal="true"/>
<field name="restMethod"><hidden value="GET"/></field>
<field name="noConditionFind"><hidden value="Y"/></field>
<field name="searchOptions_collapsed" ><hidden value="true"/></field>
<field name="searchButton"><submit/></field>"""
@@ -81,9 +82,16 @@ if (modelEntity) {
dynamicAutoEntitySearchFormRenderer.render(writer, context)
context.dynamicAutoEntitySearchForm = writer

// In case of composite pk
String pk = modelEntity.pkNameString()
String res = ""
for (w in pk.split(", ")) {
res = "${res}/\${${w}}"
}

//prepare the result list from performFind
String dynamicAutoEntityFieldListForm = """<?xml version="1.0" encoding="UTF-8"?><forms xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://ofbiz.apache.org/Widget-Form" xsi:schemaLocation="http://ofbiz.apache.org/Widget-Form http://ofbiz.apache.org/dtds/widget-form.xsd">
<form name="ListGeneric" type="list" target="FindGeneric" list-name="listIt"
<form name="ListGeneric" type="list" method="post" target="entity/find/${entityName}" list-name="listIt"
odd-row-style="alternate-row" default-table-style="basic-table light-grid hover-bar" header-row-style="header-row-2">
<actions>
<service service-name="performFind">
@@ -100,10 +108,7 @@ if (modelEntity) {
"<field name=\"${modelField.name}\" sort-field=\"true\"/>"
}
dynamicAutoEntityFieldListForm += """
<field name="viewGeneric" title=" "><hyperlink target="ViewGeneric" description="view">
<auto-parameters-entity entity-name="${entityName}"/>
<parameter param-name="entityName" value="${entityName}"/>
</hyperlink></field>
<field name="viewGeneric" title=" "><hyperlink target="entity/find/${entityName}${res}" description="view"/></field>
<sort-order><sort-field name="viewGeneric"/></sort-order>
</form></forms>"""

@@ -28,7 +28,6 @@ import org.apache.ofbiz.entity.model.ModelRelation
import org.apache.ofbiz.entity.model.ModelKeyMap
import org.apache.ofbiz.base.util.UtilFormatOut
import org.apache.ofbiz.base.util.UtilMisc
import org.apache.ofbiz.base.util.UtilValidate
import java.sql.Timestamp
import java.sql.Date
import java.sql.Time
@@ -58,25 +57,31 @@ context.put("hasAllDelete", hasAllDelete)
context.put("hasViewPermission", hasViewPermission)
context.put("hasCreatePermission", hasCreatePermission)
context.put("hasUpdatePermission", hasUpdatePermission)
context.put("hasDeletePermission" , hasDeletePermission)
context.hasDeletePermission = hasDeletePermission

boolean useValue = true
String curFindString = "entityName=" + entityName
String currentFindString = entityName
GenericPK findByPK = delegator.makePK(entityName)
Iterator pkIterator = entity.getPksIterator()
while (pkIterator.hasNext()) {
ModelField field = pkIterator.next()
ModelFieldType type = delegator.getEntityFieldType(entity, field.getType())
String fval = parameters.get(field.getName())
if (fval) {
curFindString = curFindString + "&" + field.getName() + "=" + fval
findByPK.setString(field.getName(), fval)
String fieldValues = parameters.get("pkValues")
HashMap<String,String> pkNamesValuesMap = new HashMap<>()
if (fieldValues != null) {
Iterator pkParamIterator = Arrays.asList(fieldValues.split("/")).iterator()
while (pkIterator.hasNext() && pkParamIterator.hasNext()) {
ModelField field = pkIterator.next()
String fieldValue = pkParamIterator.next()
if (fieldValue) {
currentFindString += "/" + fieldValue
pkNamesValuesMap[field.getName()] = fieldValue
findByPK.setString(field.getName(), fieldValue)
}
}
}
parameters << pkNamesValuesMap
context.pkNamesValuesMap = pkNamesValuesMap
context.put("findByPk", findByPK.toString())

curFindString = UtilFormatOut.encodeQuery(curFindString)
context.put("curFindString", curFindString)
context.currentFindString = UtilFormatOut.encodeQuery(currentFindString)

GenericValue value = null
//only try to find it if this is a valid primary key...
@@ -136,7 +141,7 @@ if (value == null && (findByPK.getAllFields().size() > 0)) {
}
context.put("pkNotFound", pkNotFound)

String lastUpdateMode = parameters.get("UPDATE_MODE")
String lastUpdateMode = parameters.get("restMethod")
if ((session.getAttribute("_ERROR_MESSAGE_") != null || request.getAttribute("_ERROR_MESSAGE_") != null) &&
lastUpdateMode != null && !"DELETE".equals(lastUpdateMode)) {
//if we are updating and there is an error, do not use the entity data for the fields, use parameters to get the old value
@@ -61,7 +61,9 @@ public class GenericWebEvent {
public static String updateGeneric(HttpServletRequest request, HttpServletResponse response) {
String entityName = request.getParameter("entityName");
Locale locale = UtilHttp.getLocale(request);

if (UtilValidate.isEmpty(entityName)) {
entityName = (String) request.getAttribute("entityName");
}
if (UtilValidate.isEmpty(entityName)) {
String errMsg = UtilProperties.getMessage(GenericWebEvent.err_resource, "genericWebEvent.entity_name_not_specified", locale) + ".";
request.setAttribute("_ERROR_MESSAGE_", errMsg);
@@ -95,6 +97,16 @@ public static String updateGeneric(HttpServletRequest request, HttpServletRespon
}

String updateMode = request.getParameter("UPDATE_MODE");
if (updateMode == null && request.getParameter("restMethod") == null) {
updateMode = "CREATE";
}
if (updateMode == null) {
switch (request.getParameter("restMethod")) {
case "PUT": updateMode = "UPDATE"; break;
case "DELETE": updateMode = "DELETE"; break;
default: updateMode = "CREATE"; break;
}
}

if (UtilValidate.isEmpty(updateMode)) {
String errMsg = UtilProperties.getMessage(GenericWebEvent.err_resource, "genericWebEvent.update_mode_not_specified", locale) + ".";
@@ -156,6 +168,8 @@ public static String updateGeneric(HttpServletRequest request, HttpServletRespon
// Delete actual main entity last, just in case database is set up to do a cascading delete, caches won't get cleared
try {
delegator.removeByPrimaryKey(findByEntity.getPrimaryKey());
String confirmMsg = UtilProperties.getMessage(GenericWebEvent.err_resource, "genericWebEvent.delete_succeeded", locale) ;
request.setAttribute("_EVENT_MESSAGE_", confirmMsg);
} catch (GenericEntityException e) {
String errMsg = UtilProperties.getMessage(GenericWebEvent.err_resource, "genericWebEvent.delete_failed", locale) + ": " + e.toString();
Debug.logWarning(e, errMsg, module);
@@ -127,7 +127,7 @@ under the License.
</#if>

<#if "entity" == artifactInfo.getType()>
<div><a href="<@ofbizUrl>FindGeneric?entityName=${artifactInfo.modelEntity.getEntityName()}&amp;find=true&amp;VIEW_SIZE=50&amp;VIEW_INDEX=0</@ofbizUrl>">All Entity Data</a></div>
<div><a href="<@ofbizUrl>entity/find/${artifactInfo.modelEntity.getEntityName()}?noConditionFind=Y</@ofbizUrl>">All Entity Data</a></div>
<h2>Entity Fields</h2>
<table>
<#list artifactInfo.modelEntity.getFieldsUnmodifiable() as modelField>
@@ -79,21 +79,13 @@ under the License.
<td<#if anchor?has_content> ${anchor}</#if>>${entity.entityName}<#if entity.viewEntity == 'Y'>&nbsp;(${uiLabelMap.WebtoolsEntityView})</#if></td>
<#assign anchor="">
<td class="button-col">
<#if entity.viewEntity == 'Y'>
<#if entity.entityPermissionView == 'Y'>
<a href='<@ofbizUrl>ViewRelations?entityName=${entity.entityName}</@ofbizUrl>'>${uiLabelMap.WebtoolsReln}</a>
<a href='<@ofbizUrl>FindGeneric?entityName=${entity.entityName}</@ofbizUrl>'>${uiLabelMap.WebtoolsFind}</a>
<a href='<@ofbizUrl>FindGeneric?entityName=${entity.entityName}&amp;noConditionFind=Y</@ofbizUrl>'>${uiLabelMap.WebtoolsAll}</a>
</#if>
<#else>
<#if entity.entityPermissionCreate == 'Y'>
<a href='<@ofbizUrl>ViewGeneric?entityName=${entity.entityName}</@ofbizUrl>' title='${uiLabelMap.CommonCreate}'>${uiLabelMap.WebtoolsCreate}</a>
</#if>
<#if entity.entityPermissionView == 'Y'>
<a href='<@ofbizUrl>ViewRelations?entityName=${entity.entityName}</@ofbizUrl>' title='${uiLabelMap.WebtoolsViewRelations}'>${uiLabelMap.WebtoolsReln}</a>
<a href='<@ofbizUrl>FindGeneric?entityName=${entity.entityName}</@ofbizUrl>' title='${uiLabelMap.WebtoolsFindRecord}'>${uiLabelMap.WebtoolsFind}</a>
<a href='<@ofbizUrl>FindGeneric?entityName=${entity.entityName}&amp;noConditionFind=Y</@ofbizUrl>' title='${uiLabelMap.WebtoolsFindAllRecords}'>${uiLabelMap.WebtoolsAll}</a>
</#if>
<#if entity.viewEntity != 'Y' && entity.entityPermissionCreate == 'Y'>
<a href='<@ofbizUrl>entity/create/${entity.entityName}</@ofbizUrl>' title='${uiLabelMap.CommonCreate}'>${uiLabelMap.WebtoolsCreate}</a>
</#if>
<#if entity.entityPermissionView == 'Y'>
<a href='<@ofbizUrl>entity/relations/${entity.entityName}</@ofbizUrl>'>${uiLabelMap.WebtoolsReln}</a>
<a href='<@ofbizUrl>entity/find/${entity.entityName}</@ofbizUrl>'>${uiLabelMap.WebtoolsFind}</a>
<a href='<@ofbizUrl>entity/find/${entity.entityName}?noConditionFind=Y</@ofbizUrl>'>${uiLabelMap.WebtoolsAll}</a>
</#if>
</td>
<#if right_col>
@@ -63,7 +63,7 @@ under the License.
</div>
<div>${entity.title}&nbsp;
<#if !forstatic>
<a target='main' href="<@ofbizUrl>FindGeneric?entityName=${entity.entityName}&amp;noConditionFind=Y</@ofbizUrl>">[${uiLabelMap.WebtoolsViewData}]</a>
<a target='main' href="<@ofbizUrl>entity/find/${entity.entityName}?noConditionFind=Y</@ofbizUrl>">[${uiLabelMap.WebtoolsViewData}]</a>
</#if>
<#if !forstatic>
<a target='main' href="<@ofbizUrl>ArtifactInfo?name=${entity.entityName}&amp;type=entity</@ofbizUrl>">[${uiLabelMap.WebtoolsArtifactInfo}]</a>
@@ -50,15 +50,22 @@ function ShowTab(lname) {
<h2>${uiLabelMap.WebtoolsWithPk}: ${findByPk}</h2>
<br />
<div class="button-bar">
<a href='<@ofbizUrl>FindGeneric?entityName=${entityName}&amp;noConditionFind=Y</@ofbizUrl>' class="buttontext">${uiLabelMap.WebtoolsBackToFindScreen}</a>
<a href='<@ofbizUrl>entity/find/${entityName}</@ofbizUrl>' class="buttontext">${uiLabelMap.WebtoolsBackToFindScreen}</a>
<#if enableEdit = "false">
<#if hasCreatePermission>
<a href='<@ofbizUrl>ViewGeneric?entityName=${entityName}&amp;enableEdit=true</@ofbizUrl>' class="buttontext create">${uiLabelMap.CommonCreate}</a>
<a href="<@ofbizUrl>ViewGeneric?${curFindString}&amp;enableEdit=true</@ofbizUrl>" class="buttontext">${uiLabelMap.CommonEdit}</a>
<form action="<@ofbizUrl>entity/edit/${currentFindString}</@ofbizUrl>" method="get">
<input type="submit" value="${uiLabelMap.CommonEdit}" />
</form>
</#if>
<#if value?has_content>
<#if hasDeletePermission>
<a href='<@ofbizUrl>UpdateGeneric?UPDATE_MODE=DELETE&amp;${curFindString}</@ofbizUrl>' class="buttontext delete">${uiLabelMap.WebtoolsDeleteThisValue}</a>
<form action='<@ofbizUrl>entity/change/${currentFindString}</@ofbizUrl>' method="delete" name="updateForm">
<input type="hidden" value="DELETE" name="restMethod"/>
<#list pkNamesValuesMap.keySet() as pkName>
<input type="hidden" value="${pkNamesValuesMap.get(pkName)}" name="${pkName}"/>
</#list>
<input type="submit" value="${uiLabelMap.WebtoolsDeleteThisValue}" />
</form>
</#if>
</#if>
</#if>
@@ -104,14 +111,13 @@ function ShowTab(lname) {
<#if pkNotFound>
<p>${uiLabelMap.WebtoolsEntityName} ${entityName} ${uiLabelMap.WebtoolsWithPk} ${findByPk} ${uiLabelMap.WebtoolsSpecifiedEntity2}.</p>
</#if>
<form action='<@ofbizUrl>UpdateGeneric?entityName=${entityName}</@ofbizUrl>' method="post" name="updateForm">
<form action='<@ofbizUrl>entity/change/<#if value?has_content>${currentFindString}<#else>${entityName}</#if></@ofbizUrl>' method="post" name="updateForm">
<#assign showFields = true>
<#assign alt_row = false>
<table class="basic-table" cellspacing="0">
<#if value?has_content>
<#if hasUpdatePermission>
<#if newFieldPkList?has_content>
<input type="hidden" name="UPDATE_MODE" value="UPDATE"/>
<#list newFieldPkList as field>
<tr<#if alt_row> class="alternate-row"</#if>>
<td class="label">${field.name}</td>
@@ -131,7 +137,6 @@ function ShowTab(lname) {
<#if hasCreatePermission>
<#if newFieldPkList?has_content>
<p>${uiLabelMap.WebtoolsYouMayCreateAnEntity}</p>
<input type="hidden" name="UPDATE_MODE" value="CREATE"/>
<#list newFieldPkList as field>
<tr<#if alt_row> class="alternate-row"</#if>>
<td class="label">${field.name}</td>
@@ -204,6 +209,7 @@ function ShowTab(lname) {
<#assign alt_row = !alt_row>
</#list>
<#if value?has_content>
<input type="hidden" name="restMethod" value="PUT"/>
<#assign button = "${uiLabelMap.CommonUpdate}">
<#else>
<#assign button = "${uiLabelMap.CommonCreate}">
@@ -212,7 +218,7 @@ function ShowTab(lname) {
<td>&nbsp;</td>
<td>
<input type="submit" name="Update" value="${button}" />
<a href="<@ofbizUrl>ViewGeneric?${curFindString}</@ofbizUrl>" class="smallSubmit">${uiLabelMap.CommonCancel}</a>
<a href="<@ofbizUrl>entity/find/${entityName}</@ofbizUrl>" class="smallSubmit">${uiLabelMap.CommonCancel}</a>
</td>
</tr>
</#if>
@@ -29,7 +29,7 @@ under the License.
<h2>${uiLabelMap.WebtoolsForEntity}: ${entityName}</h2>
<br />
<div class="button-bar">
<a href="<@ofbizUrl>FindGeneric?entityName=${entityName}</@ofbizUrl>" class="smallSubmit">${uiLabelMap.WebtoolsBackToFindScreen}</a>
<a href="<@ofbizUrl>entity/find/${entityName}</@ofbizUrl>" class="smallSubmit">${uiLabelMap.WebtoolsBackToFindScreen}</a>
</div>
<br />
<table class="basic-table hover-bar" cellspacing="0">
@@ -44,7 +44,7 @@ under the License.
<#list relations as relation>
<tr<#if alt_row> class="alternate-row"</#if>>
<td>${relation.title}</td>
<td class="button-col"><a href='<@ofbizUrl>FindGeneric?entityName=${relation.relEntityName}</@ofbizUrl>'>${relation.relEntityName}</a></td>
<td class="button-col"><a href='<@ofbizUrl>entity/find/${relation.relEntityName}</@ofbizUrl>'>${relation.relEntityName}</a></td>
<td>${relation.type}</td>
<td>${relation.fkName}</td>
<td>

0 comments on commit 6e1c7b5

Please sign in to comment.