Access flow variable in java code mule - scope

I stored some information in a variable, but I do not know how to access it in my java code...
Example:
<sub-flow name="EnrichMessage" doc:name="EnrichMessage">
<component doc:name="Scenario01" class="Class01"/>
<set-variable variableName="Parameters" value="#[payload]" doc:name="Variable"/>
<flow-ref name="SubFlow01" doc:name="SubFlow01"/>
<component doc:name="Scenario02" class="Class02"/>
</sub-flow>
I already saw some incomplete answers, but still don't know how to do that. Anyone can post a complete answer?
Thanks.

In java there are a few ways to access variables depending the type of java class you are using:
onCall event class
public Object onCall(MuleEventContext eventContext, #Payload String payload)
throws Exception {
String returnPath = eventContext.getMessage().getProperty("myReturnPath", PropertyScope.OUTBOUND);
If the MuleMessage is passed:
public void process(#Payload MuleMessage payload ){
String returnPath = messge.getProperty("myReturnPath", PropertyScope.OUTBOUND);
Using an OutboundHeader annotation
public void process(#Payload String payload, #OutboundHeaders Map headers ){
String prop = headers.get("propname");

Add new Java Component to your flow and create new Java class implement Callable interface.
public Object onCall(MuleEventContext eventContext) throws Exception {
MuleMessage msg = eventContext.getMessage();
// you can access MuleMessage here
return msg;
}
Then, you can access your MuleMessage.
String method = msg.getProperty("http.method", PropertyScope.INBOUND);
If you want to add new property
msg.setProperty("foo", "bar", PropertyScope.INVOCATION);

Related

JSF with custom Annotation

I am using primefaces version 5 and I am adding messages regarding to a specific actions like save :
public void save(Tenant tenant) {
tenantDao.save(tenant);
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Save success"));
}
Since I had a lot of these actions I tried to simplify this by creating a custom annotation called Message:
#Target(Runtime)
#Retention(Method)
public #interface Message {
String value();
}
and in my dao class :
public class TenantDao {
#Message("Saved Successfully")
public Tenant save(Tenant t) {
return em.save(t);
}
}
To read this annotation I have overridden the ELResolver the method invoke
public Object invoke(ELContext context,
Object base,
Object method,
Class<?>[] paramTypes,
Object[] params) {
Object result = super.invoke(context,method,paramTypes,params);
Method m = base.getClass().getMethod(method,paramTypes);
if(m.getAnnotation(Message.class) != null) {
addMessahe(m.getAnnotation(Message.class).value());
}
return result;
}
This was called in property (rendered, update, ..) but not in action listener
After a lot of debugging I discovered that theactionListener is called from MethodExpression class. So, I wrapped the MethodExpression class, and override the method invoke.
The problem now is that there are no way to retreive the class Method from MethodExpression class, also if I used the expression #{tenantDao.save(tenant)} the method getMethodInfo from MethodExpression will throw an exception.
Are there any way to read tAnnotation from any jsf context ?
I know that using Spring with AOP may solve this but I am not using Spring now.
Thanks

Store sessionScope java.util.TreeMap variable in a document in xPage

I am working on an application where I am creating a java.util.TreeMap containing data fetched from various other documents of the application and then assigning that treemap to a sessionsScope variable. This is working fine.
Now I want to provide a functionality wherein I need to store this map inside a NotesDocument.
But when I try doing this, I am getting an error.
var doc:NotesDocument = database.createDocument();
doc.replaceItemValue("Form","testForm");
print("json = "+sessionScope.get("Chart_Map"));
doc.replaceItemValue("Calender_Map",sessionScope.get("Chart_Map"));
doc.save();
Exception:
Error while executing JavaScript action expression
Script interpreter error, line=4, col=13: [TypeError] Exception occurred calling method NotesDocument.replaceItemValue(string, java.util.TreeMap) null**
Is it possible to store a java.util.TreeMap in a notesdocument field?
If yes then how to implement that?
If no then why not? has that something to do with serializability?
You can't store Java objects inside Document fields unless you use the MimeDomino Document data source
http://www.openntf.org/main.nsf/blog.xsp?permaLink=NHEF-8XLA83
Or even better the new openntf Domino API that has this functionallity built in
http://www.openntf.org/main.nsf/project.xsp?r=project/OpenNTF%20Domino%20API
using MimeStorage
Fredrik is right, the MimeDomino makes most sense. If you are not ready and your field isn't too big for a normal Notes item, you could use CustomDataBytes as Sven suggested - or you use JSON by subclassing TreeMap. It could look like this:
import java.util.TreeMap;
import java.util.Vector;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import lotus.domino.Item;
import lotus.domino.NotesException;
public class TreeMapItem extends TreeMap<String, String> {
private static final long serialVersionUID = 1L;
public static TreeMapItem load(Item source) throws JsonSyntaxException, NotesException {
Gson g = new Gson();
TreeMapItem result = g.fromJson(source.getText(), TreeMapItem.class);
return result;
}
public void save(Item target) throws NotesException {
Gson g = new Gson();
target.setValueString(g.toJson(this));
}
}
I used Google's Gson, it is quite easy, but you might need to deploy it as plug-in for the Java security to work. There is build in JSON in XPages too - a little more work. An alternate approach would be to use 2 fields in Domino, one to load the keys from and one for the values - it would be in line with Domino practises from classic.
A third approach would be be to store the values separated using a pipe character:
#SuppressWarnings({ "unchecked", "rawtypes" })
public void saveCompact(Item target) throws NotesException {
Vector v = new Vector();
for (Map.Entry<String, String> me : this.entrySet()) {
v.add(me.getKey()+"|"+me.getValue());
}
target.setValues(v);
}
#SuppressWarnings("rawtypes")
public static TreeMapItem loadCompact(Item source) throws NotesException {
TreeMapItem result = new TreeMapItem();
Vector v = source.getValues();
for (Object o : v) {
String[] candidate = o.toString().split("|");
if (candidate.length > 1) {
result.put(candidate[0], candidate[1]);
}
}
return result;
}
Let us know how it works for you

cxf jax-rs: How to get basic types marshalled as XML?

I have a cxf JAX-RS service which looks something like the one below. When I submit a request with requested type "application/xml" I would expect that cxf automatically converts my return value into xml. This works for the method getData, but not for the other 2 methods. The other 2 methods return a simple String representation of the return value such as 2.0 or true. How do I get cxf to return a XML document for all 3 methods?
#WebService
#Consumes("application/xml")
#Produces("application/xml")
public interface MyServiceInterface {
final static String VERSION = "2.0";
#WebMethod
#GET
#Path("/version")
String getVersion();
#WebMethod
#GET
#Path("/data/{user}")
Data[] getData(#PathParam("user") String username) throws IOException;
#WebMethod
#GET
#Path("/user/{user}")
boolean doesUserExist(#PathParam("user") String username);
}
The issue is that neither String nor boolean has a natural representation as an XML document; XML requires an outer element, and neither CXF nor JAXB (the XML binding layer) knows what it should be.
The simplest method is to return the basic type inside a little JAXB-annotated wrapper:
#XmlRootElement
public class Version {
#XmlValue
public String version;
}
#XmlRootElement
public class UserExists {
#XmlValue
public boolean exists;
}
#WebService
#Consumes("application/xml")
#Produces("application/xml")
public interface MyServiceInterface {
final static String VERSION = "2.0";
#WebMethod
#GET
#Path("/version")
// TYPE CHANGED BELOW!
Version getVersion();
#WebMethod
#GET
#Path("/data/{user}")
Data[] getData(#PathParam("user") String username) throws IOException;
#WebMethod
#GET
#Path("/user/{user}")
// TYPE CHANGED BELOW!
UserExists doesUserExist(#PathParam("user") String username);
}
The other way of doing this would be to register providers that know how to convert strings and booleans into XML, but that's messy and affects your whole application in unexpected ways and you really shouldn't do that for simple types, OK?

Handling Serialization Exceptions in ServiceStack

I am using ServiceStack to create a service which accepts request from and HTML form (POSTed). One of the DTO properties is an Enum, and when the input doesn't match the Enum members, I get the following exception:
Error occured while Processing Request: KeyValueDataContractDeserializer: Error converting to type: Requested value 'MyValue' was not found.
System.Runtime.Serialization.SerializationException: KeyValueDataContractDeserializer: Error converting to type: Requested value 'MyValue' was not found. ---> System.ArgumentException: Requested value 'MyValue' was not found.
at System.Enum.TryParseEnum(Type enumType, String value, Boolean ignoreCase, EnumResult& parseResult)
at System.Enum.Parse(Type enumType, String value, Boolean ignoreCase)
at ServiceStack.ServiceModel.Serialization.StringMapTypeDeserializer.PopulateFromMap(Object instance, IDictionary`2 keyValuePairs)
How can I intercept this exception and handle it myself in my service code?
There are a couple of ways to handle this situation:
You can make the DTO Enum property a string (since everything can successfully deserialize into a string :) and then convert that yourself manually i.e.
using ServiceStack.Common; //ToEnum<> is an extension method
public class RequestDto
{
public string EnumString { get; set; }
}
public override object OnGet(RequestDto request)
{
MyEnum defaultValue = MyEnum.None;
try {
defaultValue = request.EnumString.ToEnum<MyEnum>();
} catch {}
}
The other alternative is to completely remove it from the request DTO and get value manually from the IHttpRequest Context like:
public class RequestDto {}
public override object OnGet(RequestDto request)
{
MyEnum enumValue = MyEnum.DefaultValue;
try {
var enumStr = base.RequestContext.Get<IHttpRequest>().QueryString["EnumString"];
enumValue = enumStr.ToEnum<MyEnum>();
} catch {}
}
I generally discourage the use of enums on DTOs for many reasons, the primary one being on XML/SOAP endpoints the XSD treats them as a restricted set of values which is a pain in when trying iteratively to evolve your web services as you will need to re-gen the clients to add a new value.
By convention the way I deal with it is to have all enums as strings but provide some metadata on the DTO which points to the target type (which helps in VS.NET/R# navigation and metadata tools).
public class RequestDto
{
[References(typeof(MyEnum))]
public string EnumString { get; set; }
}

Adding new dynamic properties

we read in msdn we "Adding new dynamic properties" by using DynamicObject Class
i write a following program
public class DemoDynamicObject : DynamicObject
{
}
class Program
{
public static void Main()
{
dynamic dd = new DemoDynamicObject();
dd.FirstName = "abc";
}
}
But when i run this program it gives runtime error :'DemoDynamicObject' does not contain a definition for 'FirstName'
if we adding dynamic property by using DynamicObject Class then why it can give this error
can anyone tell me reason and solution?
When using DynamicObject as your base class, you should provide specific overrides to TryGetMember and TrySetMember to keep track of the dynamic properties you are creating (based on the DynamicObject MSDN documentation):
class DemoDynamicObject: DynamicObject
{
Dictionary<string, object> dictionary
= new Dictionary<string, object>();
public override bool TryGetMember(
GetMemberBinder binder, out object result)
{
string name = binder.Name;
return dictionary.TryGetValue(name, out result);
}
public override bool TrySetMember(
SetMemberBinder binder, object value)
{
dictionary[binder.Name] = value;
return true;
}
}
If you just want to have a dynamic object that you can add properties to, you can simply use an ExpandoObject instance, and skip the custom class inheriting from DynamicObject.

Resources