esb mule passing the parameters to the method via http - esb

I have a test method:
#Test
public void testHello_with_muleXmlConfig() throws Exception {
MuleClient client = new MuleClient("mule-config-test.xml");
client.getMuleContext().start();
MuleMessage result = client.send("http://127.0.0.1:8080/hello", "some data", null);
assertNotNull(result);
assertNull(result.getExceptionPayload());
assertFalse(result.getPayload() instanceof NullPayload);
assertEquals("hello", result.getPayloadAsString());
}
Here (client.send("http://127.0.0.1:8080/hello", "some data", null)), I'm passing the parameter/data = 'some data'.
And I have a class:
public class HelloWorld {
public String sayHello() {
return "hello";
}
}
which is exposed as spring bean in mule-config.xml:
<spring:bean id="helloWorld" class="org.mule.application.hello.HelloWorld"/>
<flow name="HelloWorld">
<inbound-endpoint address="http://127.0.0.1:8080/hello"/>
<invoke method="sayHello" object-ref="helloWorld"/>
</flow>
What I should do to pass the parameter 'hello' into the 'sayHello()' method. If just changing it to 'sayHello(String text)' - it will not work.

You need to add this to the invoke element:
methodArguments="#[message.getPayload()]" methodArgumentTypes="java.lang.String"

Not sure about how/if invoke works: I suggest you use component instead.
If you change your method to accept a String, like for example:
public String sayHello(final String text)
{
return "hello:" + text;
}
then you also need to use an object-to-string-transformer to deserialize the inbound input stream to a String:
<flow name="HelloWorld">
<inbound-endpoint address="http://127.0.0.1:8080/hello" />
<object-to-string-transformer />
<component>
<spring-object bean="helloWorld" />
</component>
</flow>

Try This :
add this in your flow :
<invoke object-ref="helloWorld" method="sayHello" methodArguments="#[message.inboundProperties.'http.query.params'.name]" doc:name="Invoke" />
and this is the invoked method :
public String sayHello(String name) {
return String.format("Hello %s!", name);
}

Related

SpringBatch ItemProcessor: process a List<?> not one Item

I have to modify a process made with SpringBatch, the procedure it's easy.
Actually, the program reads records from a database and exports the results to XML files (one by each table)
Now, I want to write JSON files instead XML files, I didn't find how to make it possible, but reading and reading I have something close to that I want.
I wrote an ItemProcessor class like this
#Component("jSONObjectProcessor")
public class JSONObjectProcessor implements ItemProcessor<Object, String> {
private Gson gson = new Gson();
private List<Object> array = new ArrayList<Object>();
#Override
public String process(Object item) throws Exception {
array.add(item);
return gson.toJson(array);
}
}
Obviously, if I have 6 items; this going to return 6 List, like it does right now
1st item
[
{
"number":0,
"string":"abc",
"desc":"abcdefg"
}
]
2nd item
[
{
"number":0,
"string":"abc",
"desc":"abcdefg"
},
{
"number":1000,
"string":"xyz",
"desc":"uvwxyz"
}
]
//more lists by the total of items
To write the files I'm using org.springframework.batch.item.file.FlatFileItemWriter class.
I want to find the way to return all the items in a List and give it JSON form and write this json in the file. I'm in the correct way or there are another, more elegant form. It's possible?
Thanks!
Update
I have made the changes (thanks #Sanj), but I miss the comma (,) delimiter between each object.
My ItemWriter it's defined like this
<bean id="itemWriterRegConstantes" scope="step"
class="org.springframework.batch.item.file.FlatFileItemWriter">
<property name="resource" value="#{jobParameters['fileOutput']}" />
<property name="shouldDeleteIfExists" value="true" />
<property name="lineAggregator">
<bean class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
<property name="delimiter" value="," />
</bean>
</property>
<property name="footerCallback" ref="headerFooterCallback" />
<property name="headerCallback" ref="headerFooterCallback" />
</bean>
The output file now looks like this
[
{"number":0,"string":"abcd","desc":"efgh"} //no comma
{"number":1000,"string":"xyz","valor":"xyzw"}
]
How add it?
Additionaly, how can I print all the content in a single line? (to minify the content) It's possible?
My Solution
I had to create my own class (really I made change to the FlatFileItemWriter SpringBatch class, it's here
Output: a file with an one line JSON array content.
Thanks!
Return single json for every item from ItemProcessor
#Component("jSONObjectProcessor")
public class JSONObjectProcessor implements ItemProcessor<Object, String> {
private Gson gson = new Gson();
#Override
public String process(Object item) throws Exception {
return gson.toJson(item);
}
}
Create header and footer call backs. Basically they will be used to start and close the array respectively.
public class JSONHeaderFooterCallBack implements FlatFileHeaderCallback, FlatFileFooterCallback{
#Override
public void writeHeader(Writer writer) throws IOException {
writer.write("[" + System.getProperty("line.separator"));
}
#Override
public void writeFooter(Writer writer) throws IOException {
writer.write("]");
}
}
Associate the callbacks with FlatFileItemWriter
FlatFileItemWriter<String> writer = new FlatFileItemWriter<String>();
//Setting header and footer.
JSONHeaderFooterCallBack headerFooterCallback = new JSONHeaderFooterCallBack();
writer.setHeaderCallback(headerFooterCallback);
writer.setFooterCallback(headerFooterCallback);
writer.setResource(new FileSystemResource(System.getProperty("user.dir") + "/output.json"));
Now you can use "writer" to write all records as a json array to a file.
---update--
Use CustomLineAggregator to append comma at the end of every record:
public class CustomLineAggregator<String> implements LineAggregator<String> {
#Override
public String aggregate(String item) {
return item+",";
}
}

Null value in json whereas retrieving all the values in log in struts,spring and hibernate

I am using Struts,Spring and Hibernate Integration. I have written a method in DAO implementation to return list object from db.When I trigger the action to call the DAO ,I get correct values in log whereas i get null values in json file. Kindly suggest me some solution.
My basic requirement is that I want to get Json response(for List object) to be sent from action to jsp.
Thanks in advance.
Struts.xml
<action name="loadJsonAction" class="loadJsonActionClass"
method="loadGrid">
<result name="success" type="json">/pages/jsp/index.jsp
</result>
<result name="error">/pages/jsp/index.jsp
</result>
</action>
Application Context.xml
<bean id="deviceDao" class="com.example.daoImpl.DeviceDaoImpl">
<property name="hibernateTemplate" ref="hibernateTemplate"></property>
</bean>
<bean id="deviceService"
class="com.example.serviceImpl.DeviceServiceImpl">
<property name="deviceDao" ref="deviceDao" />
<property name="transactionManager" ref="transactionManager"></property>
</bean>
<bean id="loadJsonActionClass" class="com.example.action.DeviceInfoAction">
<property name="deviceService" ref="deviceService" />
</bean>
Code in Action Class
public String loadGrid() {
getDeviceService().getDeviceInfoById(1);
return "success";
}
Code in Service Class
#Override
public List<Device> getDeviceInfoById(Integer id) {
return getDeviceDao().getDeviceInfoById(id);
}
Code in Dao Class
#Override
public List<Device> getDeviceInfoById(final Integer id) {
return this.hibernateTemplate.execute(new HibernateCallback() {
public Object doInHibernate(Session session) {
Device deviceInfo;
Criteria criteria = session.createCriteria(Device.class);
criteria.add(Restrictions.eq("id", id));
List<Device> deviceList = criteria.list();
if (deviceList .size() != 0) {
logger.debug("device name from db "
+ deviceList .get(0).getDeviceName());
deviceInfo = deviceList .get(0);
}
return deviceList ;
}
});
}
JSON Respose
{"accountId":null,"androidVersion":null,"baseLocationId":null,"basebandVersion":null,"bluetoothAddress":null,"brand":null,"buildNumber":null,"device":null,"deviceAddedDate":null,"deviceDetails":null,"deviceFileInfo":null,"deviceId":null,"deviceImageUrl":null,"deviceName":null,"deviceNetworkInfo":null,"deviceSettingsInfo":null,"deviceType":null,"emailId":null,"firstName":null,"groupId":null,"imeiNo1":null,"imeiNo2":null,"isDeviceTracked":null,"isDualMode":null,"isSdCardAvailable":null,"kernelVersion":null,"lastName":null,"lastUpdateBy":null,"lastUpdatedDate":null,"manufacturer":null,"model":null,"nickName":null,"osVersion":null,"phoneNumber":null,"product":null,"rowStatus":null,"screensize":null,"serialNumber":null}
values in log
DEBUG[DeviceDaoImpl$2]: device name from db: generic
Since I am using Spring and ModelDriven in Action, it processes everything as a Model.As there was no field for deviceList before in model,I was not able to get the response as List. Now I added deviceList to model class and set the deviceList to the value retrieved from database using the following code :
deviceBean.setDeviceList(getDeviceService().getDeviceInfoById(1));
Now it works fine

Spring Data Rest - Configure pagination

Using Spring Data REST with JPA in version 2.1.0.
How can I configure the pagination in order to have the page argument starting at index 1 instead of 0 ?
I have tried setting a custom HateoasPageableHandlerMethodArgumentResolver with an mvc:argument-resolvers, but that doesn't work:
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="org.springframework.data.web.HateoasPageableHandlerMethodArgumentResolver">
<property name="oneIndexedParameters" value="true"/>
</bean>
</mvc:argument-resolvers>
</mvc:annotation-driven>
Note that this behaviour is perfectly coherent with the documentation for mvc:argument-resolver that says:
Using this option does not override the built-in support for
resolving handler method arguments. To customize the built-in support
for argument resolution configure RequestMappingHandlerAdapter
directly.
But how can I achieve this ? If possible, in a clean and elegant way ?
The easiest way to do so is to subclass RepositoryRestMvcConfiguration and include your class into your configuration:
class CustomRestMvcConfiguration extends RepositoryRestMvcConfiguration {
#Override
#Bean
public HateoasPageableHandlerMethodArgumentResolver pageableResolver() {
HateoasPageableHandlerMethodArgumentResolver resolver = super.pageableResolver();
resolver.setOneIndexedParameters(true);
return resolver;
}
}
In your XML configuration, replace:
<bean class="….RepositoryRestMvcConfiguration" />
with
<bean class="….CustomRestMvcConfiguration" />
or import the custom class instead of the standard one in your JavaConfig file.
I have configured the RequestMappingHandlerAdapter using a BeanPostProcessor, however I believe that's neither clean, nor elegant. That looks more like a hack. There must be a better way ! I'm giving the code below just for reference.
public class RequestMappingHandlerAdapterCustomizer implements BeanPostProcessor {
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof RequestMappingHandlerAdapter) {
RequestMappingHandlerAdapter adapter = (RequestMappingHandlerAdapter)bean;
List<HandlerMethodArgumentResolver> customArgumentResolvers = adapter.getCustomArgumentResolvers();
if(customArgumentResolvers != null) {
for(HandlerMethodArgumentResolver customArgumentResolver : customArgumentResolvers) {
if(customArgumentResolver instanceof HateoasPageableHandlerMethodArgumentResolver) {
HateoasPageableHandlerMethodArgumentResolver hateoasPageableHandlerMethodArgumentResolver = (HateoasPageableHandlerMethodArgumentResolver)customArgumentResolver;
hateoasPageableHandlerMethodArgumentResolver.setOneIndexedParameters(true);
}
}
}
}
return bean;
}
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
}
<beans ...>
<bean class="util.spring.beanpostprocessors.RequestMappingHandlerAdapterCustomizer" />
</beans>
I use to do it using a customizer, which is something that they keep adding for more and more components with every new version:
#Bean
public PageableHandlerMethodArgumentResolverCustomizer pageableResolverCustomizer() {
return resolver -> resolver.setOneIndexedParameters(true);
}
You can put this in any #Configuration class, but ideally you should put it (with any other customization) in one that implements RepositoryRestConfigurer.

JSON object parsing using OGNL in struts 2

I have an action class like
public class DataProcessor extends ActionSupport{
private JSONObject object;
public JSONObject getObject() {
return object;
}
public void setObject(JSONObject object) {
this.object = object;
}
#Override
public String execute() throws Exception {
.......
return SUCCESS;
}
}
My XML mapping is like
<package name="default" extends="struts-default" namespace="/">
<action name="process" class="com.demo.DataProcessor">
<result type="success">home.jsp</result>
</action>
</package>
on jsp page if i write <s:property value="object"/> it prints json data. bt if i write
<s:property value="object.name"/>
or
<s:property value="#object.name"/>
or
<s:property value="${#object.name}"/> it is printing nothing.
How can i parse json object in jsp page?
You do not need to parse JSON you need to retrieve value from it. Assuming that your object is org.json.JSONObject you can get value from it by calling get method and passing key as string.
<s:property value="object.get('name')"/>
You can parse JSON using the library function parseJSON like in this example
<s:textfield id="name" name="name"/>
<s:textfield id="mobile" name="mobile"/>
<script type="text/javascript">
$(document).ready(function() {
var obj = $.parseJSON('<s:property value="object"/>');
$("name").val(obj.name);
$("mobile").val(obj.mobile);
});
</script>
This script will replace the values (if any) from the action bean populated when JSP was rendered. The textfields should be mapped to the action bean correspondingly.

#Function Annotation in Mule

I want to use #Function Annotation in Mule. I found only
this page about it.
but I can not get good result.
I made a new project, added a Java component, created a new class and copied this code
public class MyComponent {
public Object process(#XPath("/Envelope") Document doc
#Function("uuid") String id) {
// do stuff
}
}
but I have lot of errors. I think I must configure other things but I don't know what, nor how I can use #Function.
You need to manually declare an annotation parser in your configuration in order for annotations to be processed.
Consider this POJO:
package com.acme;
import org.mule.api.annotations.expression.XPath;
import org.mule.api.annotations.expressions.Function;
import org.w3c.dom.Document;
public class AnnotatedPojo
{
public Object process(#XPath("/Envelope") final Document doc, #Function("uuid") final String id)
{
return "Envelope text: " + doc.getDocumentElement().getTextContent() + " - ID: " + id;
}
}
You can use it with this Mule configuration:
<spring:bean class="org.mule.config.endpoint.RegistryBackedAnnotationsParserFactory" />
<flow name="testAnnotatedPojo">
<http:inbound-endpoint address="http://localhost:8080/pojo"
exchange-pattern="request-response" />
<component class="com.acme.AnnotatedPojo" />
</flow>
Example call:
$ curl -H "Content-Type: application/xml" http://localhost:8080/pojo -d'<Envelope>foo</Envelope>'
Envelope text: foo - ID: 9133fc7d-a07f-11e2-b560-4d5f883736c4