How do I use jsp files in Spring Roo? - spring

I made a simple Roo project in STS. It created several .jspx files, which I guess are the templates. I'd like to be able to put some HTML and CSS in those, but whenever I change anything significant, I get an exception. For example, when I add some basic HTML:
<div><span><p>Hello</p></span></div>
I get this exception:
SEVERE: Servlet.service() for servlet [msa] in context with path [/msa] threw exception [Request processing failed; nested exception is org.apache.tiles.impl.CannotRenderException: ServletException including path '/WEB-INF/layouts/default.jspx'.] with root cause
org.apache.jasper.JasperException: /WEB-INF/views/homepage/index.jspx (line: 14, column: 6) The content of elements must consist of well-formed character data or markup.
Or let's say I need to loop through a List I get from my controller:
<c:forEach var="announcement" items="${results}">
<option value ="10"><c:out value="${announcement.author}"/></option>
</c:forEach>
Then I get this exception:
SEVERE: Servlet.service() for servlet [msa] in context with path [/msa] threw exception [Request processing failed; nested exception is org.apache.tiles.impl.CannotRenderException: ServletException including path '/WEB-INF/layouts/default.jspx'.] with root cause
org.apache.jasper.JasperException: /WEB-INF/views/homepage/index.jspx (line: 12, column: 54) The prefix "c" for element "c:forEach" is not bound.
I'm not sure why it's so difficult to make simple changes to this template file. After doing quite a bit of searching, I found that the syntax of .jspx files is different than that of .jsp files, and is not recommended for hand-editing. How do I configure Roo to use .jsp files instead? Is this even possible?
Edit: Here's an example of the whole file:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<div xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:spring="http://www.springframework.org/tags" xmlns:util="urn:jsptagdir:/WEB-INF/tags/util" version="2.0">
<jsp:directive.page contentType="text/html;charset=UTF-8"/>
<jsp:output omit-xml-declaration="yes"/>
<spring:message code="label_homepage_index" htmlEscape="false" var="title"/>
<util:panel id="title" title="${title}">
<spring:message code="application_name" htmlEscape="false" var="app_name"/>
<h3>
<spring:message arguments="${app_name}" code="welcome_titlepane"/>
</h3>
<div><span><p>Hello</p></span></div>
<c:forEach var="announcement" items="${results}">
<option value ="10"><c:out value="${announcement.author}"/></option>
</c:forEach>
</util:panel>
</div>
You can comment out the first example I gave to see the problem with the second. But the issue isn't really these specific cases, it's that I can't use regular HTML in my templates, which will make writing my pages much more difficult. How can I get around that?

Regarding your first example, it seems like you may have put your stuff in the wrong place. Maybe paste the whole file (it's short) so we can see if there's actually an error.
In the second example, the exception says "The prefix "c" for element "c:forEach" is not bound.". That usually means your xmlns prefix probably isn't declared in the jspx header.

Related

Replace element by XPath

I try to replace some element of my input XML in Citrus Framework.
My Spring context contains:
<citrus:namespace-context>
<citrus:namespace prefix="def" uri="http://sample.com/xmlns/2005"/>
</citrus:namespace-context>
My input file starts with:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<ns0:canonicalMessageHeader xmlns:ns0="http://sample.com/xmlns/2005">
<ns0:headerVersion>1.0</ns0:headerVersion>
<ns0:bodyVersion>1.0</ns0:bodyVersion>
<ns0:trackingInfo>
<ns0:eventHandlerInitInfo>
<ns0:processInfo>
<ns0:adapterTrackingId>214F27DF-E1FB-4E84-9122-390C5876ABD2:1</ns0:adapterTrackingId>
...
My endpoint is configured in that way:
<send endpoint="jms:topic:Order.Request?timeout=10000&connectionFactory=DEVconnectionFactoryFrom">
<message>
<resource file="com/sample/citrus/messages/input/SalesOrderTo.xml"/>
<element value="${track}" path="SOAP-ENV:Envelope/SOAP-ENV:Header/def:canonicalMessageHeader/def:trackingInfo/def:eventHandlerInitInfo/def:processInfo/def:adapterTrackingId"/>
I have the following error:
Can not evaluate xpath expression 'SOAP-ENV:Envelope/SOAP-ENV:Header/def:canonicalMessageHeader/def:trackingInfo/def:eventHandlerInitInfo/def:processInfo/def:adapterTrackingId'
at com/sample/citrus/SalesOrderToIT(sequential:45)
at com/sample/citrus/SalesOrderToIT(send:48-82)
Caused by: javax.xml.xpath.XPathExpressionException: org.apache.xpath.domapi.XPathStylesheetDOM3Exception: Prefix must resolve to a namespace: def
What's the possible cause of this error?
Best Regards
Global namespace declaration support is missing in Citrus when overwriting message elements in a send operation via XPath. This issue has been tracked: https://github.com/christophd/citrus/issues/331
In the meantime you have to use the exact same namespace prefix as in the message template file - in your case ns0:
Also you could throw away XPath overwrite and use the dot notated Node overwrite like this:
<send endpoint="jms:topic:Order.Request?timeout=10000&connectionFactory=DEVconnectionFactoryFrom">
<message>
<resource file="com/sample/citrus/messages/input/SalesOrderTo.xml"/>
<element value="${track}" path="Envelope.Header.canonicalMessageHeader.trackingInfo.eventHandlerInitInfo.processInfo.adapterTrackingId"/>
</message>
</send>
The dot notation is not based on namespaces but uses the local element names for finding the element in the message template. Obviously not as powerful as XPath but it works with current version of the framework.
You defined nso as namespace prefix in XML but then use def on the XPath, should be nso.

Parsing an xml embedded within another xml using XPath Spring

I'm parsing an xml String using the 'evaluate' function provided by Xpath to read the contents embedded within specific tags in the xml. But i'm having trouble while trying to parse an xml which is embeded within a set of tags which i want to parse.
<Channel>
<channelId>SD0987</channelId>
<parameters>
<param>org.springframework.messaging.MessageHandlingException: HTTP request execution failed for URI [https://nike-dev.coupahost.com/api/suppliers?return_object=limited]; nested exception is org.springframework.web.client.HttpClientErrorException: 400 Bad Request</param>
<param><?xml version="1.0" encoding="UTF-8"?>
<errors>
<error>
<![CDATA[Unable to find valid PaymentTerm record for payment_term with keys {"code"=>"9999"}. Possible keys are ["id", "code"]. Please verify your xml.]]>
</error>
</errors>
</param>
<param>6-5100</param>
<param><?xml version="1.0" encoding="UTF-8"?><supplier><name>SuTestVDR008-6-5100</name><display-name>SuTestVDR008-6 (SANDALS) - VAT Registration Number - Indirect Europe - INACTIVE</display-name><status>active</status><deleted type="boolean">true</deleted><vendor-account-group-code>1001</vendor-account-group-code><vendor-number>SuTestVDR008-6</vendor-number><on-hold type="boolean">false</on-hold><language-code>E</language-code><purchase-organization-code>5100</purchase-organization-code><group-key>1234</group-key><vendor-partner-type-code>Z4</vendor-partner-type-code><currency-code>EUR</currency-code><primary-address><street1>#### JIU BI VILLAGE</street1><street2>77774</street2><city>GUANGZHOU CITY</city><state>190-Guangdong</state><postal-code>511480</postal-code><country><code>CN</code></country></primary-address><payment-term><code>9999</code></payment-term><content-groups><content-group><name>730_Company Code</name></content-group></content-groups><po-method>prompt</po-method><invoice-matching-level>3-way</invoice-matching-level></supplier></param>
</parameters>
</Channel>
In the above xml sample, i need to read and retrieve everything that is within the tags "param".
Currently, i'm first getting a count of the param tags and then looping thru them to get the data within the tags -
paramCount = XPathUtils.evaluate(originalPayload,"count(/Channel/parameters/param)",XPathUtils.STRING);
for(int i=1;i<=pCount;i++){
pList.add(XPathUtils.evaluate(originalPayload, "/Channel/parameters/param[" +i+ "]",XPathUtils.STRING)
}
This works fine with other xmls but not with the sample given above. I get the below error -
"[Fatal Error] :5:17:The processing instruction target matching "[xX][mM][lL]" is not allowed."
If i remove the part "?xmlversion="1.0" encoding="UTF-8"?
it parses the tags but the output is -
org.springframework.messaging.MessageHandlingException: HTTP request execution failed for URI [https://nike-dev.coupahost.com/api/suppliers?return_object=limited]; nested exception is org.springframework.web.client.HttpClientErrorException: 400 Bad Request
Unable to find valid PaymentTerm record for payment_term with keys {"code"=>"9999"}. Possible keys are ["id", "code"]. Please verify your xml.
6-5100
SuTestVDR008-6-5100SuTestVDR008-6 (SANDALS) - VAT Registration Number - Indirect Europe - INACTIVEactivetrue1001SuTestVDR008-6falseE51001234Z4EUR#### JIU BI VILLAGE77774GUANGZHOU CITY190-Guangdong511480CN9999730_Company Codeprompt3-way
So as you can see, it just captured the content within the various tags and printed it.
My ask is to print all the text in between the
<param >
tags as is with all the indentation in place.
So the output expected is -
org.springframework.messaging.MessageHandlingException: HTTP request execution failed for URI [https://nike-dev.coupahost.com/api/suppliers?return_object=limited]; nested exception is org.springframework.web.client.HttpClientErrorException: 400 Bad Request
<?xml version="1.0" encoding="UTF-8"?>
<errors>
<error>
<![CDATA[Unable to find valid PaymentTerm record for payment_term with keys {"code"=>"9999"}. Possible keys are ["id", "code"]. Please verify your xml.]]>
</error>
</errors>
6-5100
<?xml version="1.0" encoding="UTF-8"?>
<supplier><name>SuTestVDR008-6-5100</name><display-name>SuTestVDR008-6 (SANDALS) - VAT Registration Number - Indirect Europe - INACTIVE</display-name><status>active</status><deleted type="boolean">true</deleted><vendor-account-group-code>1001</vendor-account-group-code><vendor-number>SuTestVDR008-6</vendor-number><on-hold type="boolean">false</on-hold><language-code>E</language-code><purchase-organization-code>5100</purchase-organization-code><group-key>1234</group-key><vendor-partner-type-code>Z4</vendor-partner-type-code><currency-code>EUR</currency-code><primary-address><street1>#### JIU BI VILLAGE</street1><street2>77774</street2><city>GUANGZHOU CITY</city><state>190-Guangdong</state><postal-code>511480</postal-code><country><code>CN</code></country></primary-address><payment-term><code>9999</code></payment-term><content-groups><content-group><name>730_Company Code</name></content-group></content-groups><po-method>prompt</po-method><invoice-matching-level>3-way</invoice-matching-level></supplier>
Any ideas?
For that task your content in the <param> must be wrapped to the <![CDATA[ .. ]]>. Otherwise it becomes as a part of the root XML and loses it purpose to be the relaxed data for the XPath result.

Scriptella: How to handle the error while fetching data from XML through Xpath

i have one query regarding data fetching from XML xpath.
<query connection-id="in">
CommunicationCenter/Response/MenuData/Menu/Noun
<!--something I have to do inside script using the data fetched from xpath-->
</query>
My question is - suppose 1 of the XML doesn't have this structure of Xpath. It has "OtherCommCenter/MenuData/Menu/Noun" or something else structure. Then, when I run the job, it says the job is executed with no exception & as it does not get any value from xpath, nothing is happened. Means it gives back null. So, how do I catch the error there? I have to know which element in xpath creates the problem or if that is not possible, at least which xml is creating this error in structure ?
(because in my project, there are multiple XMLs I have to handle & I am doing that by submitting jobs to ExecutorService like you described in How to ETL multiple files using Scriptella?)
P.S. for the last part, I am doing like this
<connection id="in" driver="xpath" url="$input"/>
where "input" is the map key for the different xml file name.
can anybody help me? it is necessary to know asap for my project.
Here is an artificial example. Let's say there are kind of XMLs - people and cars.
people.xml:
<people>
<person></person>
</people>
Cars.xml:
<cars>
<car/>
</car>
The following xml runs 2 queries for /people/person and /cars/car and set global flags if at least one record was found:
<etl>
<connection driver="jexl" id="jexl"/>
<connection driver="xpath" id="xpath" url="input.xml"/>
<connection id="log" driver="text"/>
<query connection-id="xpath">
/people/person
<script connection-id="jexl">
# set flag to true if at least one element was found
etl.globals['people']=true;
</script>
</query>
<script connection-id="log" if="!etl.globals['people']">
WARNING: No people found in the XML file
</script>
<query connection-id="xpath">
/cars/car
<script connection-id="jexl">
etl.globals['cars']=true;
</script>
</query>
<script connection-id="log" if="!etl.globals['cars']">
WARNING: No cars found in the XML file
</script>
</etl>

EL in <sec:authorize> access attribute

Is it not possible to use EL in access attribute? I dislike to hardcode the role names in the tag, instead would like to use a constant. But it is throwing an exception saying:
org.apache.jasper.JasperException: abc.jsp(19,4) According to TLD or
attribute direc tive in tag file, attribute access does not accept
any expressions
Here is what I have in jsp(using unstandard taglib for constants):
<%#taglib uri="http://jakarta.apache.org/taglibs/unstandard-1.0" prefix="un"%>
<un:useConstants className="com.xxx.PrivilegeConstants" var="privilege" />
.....
<sec:authorize access="hasRole('${privilege.USER_ROLE}')"> // throwing ex here
security content here....
</sec:authorize>
Is there any other alternative? Thanks in advance...
Looks like the support was added later on. See the JIRA here. Using the version which adds this support should work, I guess.

Black Magic in Grails Data Binding?

As described in http://n4.nabble.com/Grails-Data-Binding-for-One-To-Many-Relationships-with-REST-tp1754571p1754571.html i'm trying to automatically bind my REST data.
I understand now that for one-to-many associations the map that is required for the data binding must have a list of ids of the many side such as:
[propName: propValue, manyAssoc: [1, 2]]
However, I'm getting this exception
Executing action [save] of controller [com.example.DomainName] caused exception: org.springframework.orm.hibernate3.HibernateSystemException: IllegalArgumentException occurred calling getter of com.example.DomainName.id; nested exception is org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of com.example.DomainName.id
However, even weirder is the update action that is generated for the controller. There we have the databinding like this:
domainObjectInstance.properties = params['domainObject']
But, and this is the really weird thing, params['domainObject'] is null! It is null because all the domainObject fields are passed directly in the params map itself. If I change the above line to
domainObjectInstance.properties = null
the domainObject is still updated! Why is this happening and more important, how can I bind my incoming XML automatically if it comes in this format (the problem is the one-to-many associations):
<product>
<name>Table</name>
<brand id="1" />
<categories>
<category id="1" />
<category id="2" />
</categories>
</product>
It's not 100% clear from your example - what exactly is the contents of your "params" when you try to bind.
If you don't have "domainObject.xxx=yyy" post parameters defined, then nothing will be in params['domainObject']. Namespacing like that is not necessary in most cases, and required the form fields to use the prefix.
I'm guessing your data is coming in as "xxx=yyy" not "domainObject.xxx=yyy".
Furthermore, I'm not sure that [1,2] for associations is right either. Surely that should be [id:1, id:2] ?

Resources