I have no clue how to use a Java Transformer in Mulesoft. I want to basically take a String and convert it to a URL, but I cannot figure out how to use the Java method or anything.
What am I doing wrong? How can I take I call my method, or make it so that my method is used with the value I want it to be?
ERRORS:
org.mule.module.launcher.DeploymentInitException:
IllegalStateException: Cannot convert value of type
[transformers.StringTransformer] to required type
[org.mule.api.processor.MessageProcessor] for property
'messageProcessors[4]': no matching editors or conversion strategy
found
Caused by: org.mule.api.config.ConfigurationException: Error creating
bean with name 'streamMigrateAccountToCustomer': Initialization of
bean failed; nested exception is
org.springframework.beans.ConversionNotSupportedException: Failed to
convert property value of type [java.util.ArrayList] to required type
[java.util.List] for property 'messageProcessors'; nested exception is
java.lang.IllegalStateException: Cannot convert value of type
[transformers.StringTransformer] to required type
[org.mule.api.processor.MessageProcessor] for property
'messageProcessors[4]': no matching editors or conversion strategy
found (org.mule.api.lifecycle.InitialisationException)
(org.mule.api.config.ConfigurationException)
StringTransformer
#ContainsTransformerMethods
public class StringTransformer
{
public String website;
public String getWebsite() {
return website;
}
public void setWebsite(String website) {
this.website = website;
}
#Transformer
public String stringToURL(String string) throws MalformedURLException
{
return new java.net.URL(string).toString();
}
}
XML
<custom-transformer class="transformers.StringTransformer" doc:name="Java">
<spring:property name="website" value="#[payload.Website]"/>
</custom-transformer>
INPUT TO JAVA TRANSFORMER
%dw 1.0
%output application/java
---
{
Id: payload.Id,
Name: payload.Name,
Active_CMRR__c: payload.Active_CMRR__c,
BillingStreet: payload.BillingStreet,
BillingCity: payload.BillingCity,
BillingState: payload.BillingState,
BillingPostalCode: payload.BillingPostalCode,
BillingCountry: payload.BillingCountry,
OwnerId: payload.OwnerId,
Website: payload.Website,
Contract_End_Date__c: payload.Contract_End_Date__c,
NS_Account_Number__c: payload.NS_Account_Number__c,
Phone: payload.Phone,
Subscription_Start_Date__c: payload.Subscription_Start_Date__c,
NS_Account_Name__c: payload.NS_Account_Name__c,
type: payload.type,
Owner: {
NS_Account_Manager_Id__c: payload.Owner.NS_Account_Manager_Id__c,
Id: payload.Owner.Id,
type: payload.Owner.type,
Name: payload.Owner.Name
}
}
For a simple string manipulation I prefer to use a simple MEL expression, heres an example of creating a new variable.
<set-variable variableName="website" value="#[new java.net.URL(payload.Website).toString()]" doc:name="Variable"/>
To do a java transformations on the MuleMessage, I prefer to extend the AbstractMessageTransformer class.
public class ExampleAbstractMessageTransformer extends AbstractMessageTransformer {
#Override
public Object transformMessage(MuleMessage message, String outputEncoding) throws TransformerException {
// TODO Auto-generated method stub
HashMap<String, String> payload = new HashMap<String, String>();
String websiteUrl = new String();
//Grab Payload
payload = (HashMap<String, String>) message.getPayload();
try {
websiteUrl = stringToURL(payload.get("Website").toString());
} catch (MalformedURLException e) {
e.printStackTrace();
}
message.setInvocationProperty("websiteUrl", websiteUrl);
return message;
}
public String stringToURL(String string) throws MalformedURLException {
return new java.net.URL(string).toString();
}
}
Implementing within the Mulesoft flow. Assuming the java code is packaged as com.stackoverflow.transformers utilize the "custom-transformer" component.
<custom-transformer class="com.stackoverflow.transformers.ExampleAbstractMessageTransformer" doc:name="Java" />
you can use invoke component to call java method. check https://docs.mulesoft.com/mule-user-guide/v/3.7/invoke-component-reference
#ContainsTransformerMethods // since Mule 3.0.1
public class MyTransformers {
#Transformer
public URL stringToURL(String string) {
return new java.net.URL(string);
}
#Transformer
public List<URL> stringsToURLs(String string) {
List<URL urls = new ArrayList<URL>();
for (StringTokenizer tokenizer = new StringTokenizer(string); tokenizer.hasMoreTokens();) {
urls.add(new URL(tokenizer.nextToken()));
}
return urls;
}
}
Related
Quick background, our company connects to an ERP system (Sage) via web services for some functions. We have both c# (.net) and java code that performs calls to the Web Service (WS). Recently Sage introduced Basic Authentication into their WS.
Please note: This is a JAVA question, but I'll show an example in C# first to explain.
In the c# program, I first would create an object that is for accessing the WS:
var sageService = new CAdxWebServiceXmlCCServiceBasicAuth();
I then set up credential information:
var sageServiceCallContext = SageFactory.Instance.GetCallContext();
sageService.Credentials = new NetworkCredential(SageUser, SagePwd);
sageService.PreAuthenticate = true;
then finally the call to the specific web service method:
sageCustomerSvcResponse = sageService.run(sageServiceCallContext, "YTDPROF", sageCustomerRequestInXml);
When I set up the service object I use a custom class that looks like this:
public class CAdxWebServiceXmlCCServiceBasicAuth : CAdxWebServiceXmlCCService
{
protected override WebRequest GetWebRequest(Uri uri)
{
HttpWebRequest webRequest = (HttpWebRequest)base.GetWebRequest(uri);
NetworkCredential credentials = Credentials as NetworkCredential;
if (credentials != null)
{
string authInfo = "";
if (credentials.Domain != null && credentials.Domain.Length > 0)
{
authInfo = string.Format(#"{0}\{1}:{2}", credentials.Domain, credentials.UserName, credentials.Password);
}
else
{
authInfo = string.Format(#"{0}:{1}", credentials.UserName, credentials.Password);
};
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
webRequest.Headers["Authorization"] = "Basic " + authInfo;
}
return webRequest;
}
}
What happens is that now, when I perform any call to the web service methods, the GetWebRequest from the class is invoked every time. This is how we implemented basis authentication in c#.
How do I do this in Java?
In the java code currently, I create the service object (that which accesses the web services) this way:
WebServiceInvoker service = new WebServiceInvoker(SageWSURL,"");
and the WebServiceInvoker looks like this (truncated for brevity):
public WebServiceInvoker(String url, String dummy) throws ServiceException, IOException {
serviceLocator = new CAdxWebServiceXmlCCServiceLocator();
service = serviceLocator.getCAdxWebServiceXmlCC(url);
cc = new CAdxCallContext();
cc.setCodeLang("ENG");
cc.setCodeUser("USER");
cc.setPassword("PAWWORD");
cc.setPoolAlias("POOL");
cc.setRequestConfig("adxwss.trace.on=on&adxwss.trace.size=16384&adonix.trace.on=on&adonix.trace.level=3&adonix.trace.size=8");
log = new PrintWriter(new BufferedWriter(new FileWriter("C:/Kalio/service/orders/log.txt")));
}
the webservice locator looks like this:
public class CAdxWebServiceXmlCCServiceLocator extends org.apache.axis.client.Service implements com.adonix.www.WSS.CAdxWebServiceXmlCCService {
public CAdxWebServiceXmlCCServiceLocator() {
}
public com.adonix.www.WSS.CAdxWebServiceXmlCC getCAdxWebServiceXmlCC() throws javax.xml.rpc.ServiceException {
java.net.URL endpoint;
System.out.println("using local Sage Web Servivce URL:" + CAdxWebServiceXmlCC_address);
try {
endpoint = new java.net.URL(CAdxWebServiceXmlCC_address);
}
catch (java.net.MalformedURLException e) {
throw new javax.xml.rpc.ServiceException(e);
}
return getCAdxWebServiceXmlCC(endpoint);
}
public com.adonix.www.WSS.CAdxWebServiceXmlCC getCAdxWebServiceXmlCC(java.net.URL portAddress) throws javax.xml.rpc.ServiceException {
try {
com.adonix.www.WSS.CAdxWebServiceXmlCCSoapBindingStub _stub = new com.adonix.www.WSS.CAdxWebServiceXmlCCSoapBindingStub(portAddress, this);
_stub.setPortName(getCAdxWebServiceXmlCCWSDDServiceName());
return _stub;
}
catch (org.apache.axis.AxisFault e) {
return null;
}
}
and the specific method within that class is this:
public String getCustomer(String constructedXML) throws RemoteException {
**CAdxResultXml result = service.run(cc, "XTDPROF", constructedXML);**
CAdxMessage[] messages = result.getMessages();
for (int i = 0; i<messages.length; i++) {
CAdxMessage message = messages[i];
log.println("X3 get customer message: " + message.getMessage());
log.println("X3 get customer message type: " + message.getType());
}
return result.getResultXml();
}
So my questions is, how to I emulate that override that I see in the .net program in Java? It seems like it would be somewhere in either the service locator or invoker, but the program does not use standard http classes, but this adxwss stuff. I tried a straight c# to java conversion and that way didn't help. I have seen examples where basicAuth is implemented, but not against web service calls.
The c# is pretty clear cut, because once I create the service object using the basicAuth override, every web service calls goes through the orderride. How does that happen in Java?
I'll be happy to provide more info if needed and I'll continue to look/experiment, but at the moment I'm treading water.
Adding:
In tracing through the java code I found the specific web service call (run) where an apache "call" object is created. Is this where basicauth can be added?
public com.adonix.www.WSS.CAdxResultXml run(com.adonix.www.WSS.CAdxCallContext callContext, java.lang.String publicName, java.lang.String inputXml) throws java.rmi.RemoteException {
if (super.cachedEndpoint == null) {
throw new org.apache.axis.NoEndPointException();
}
org.apache.axis.client.Call _call = createCall();
_call.setOperation(_operations[0]);
_call.setUseSOAPAction(true);
_call.setSOAPActionURI("");
_call.setSOAPVersion(org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS);
_call.setOperationName(new javax.xml.namespace.QName("http://www.adonix.com/WSS", "run"));
setRequestHeaders(_call);
setAttachments(_call);
try { java.lang.Object _resp = _call.invoke(new java.lang.Object[] {callContext, publicName, inputXml});
if (_resp instanceof java.rmi.RemoteException) {
throw (java.rmi.RemoteException)_resp;
}
else {
extractAttachments(_call);
try {
return (com.adonix.www.WSS.CAdxResultXml) _resp;
} catch (java.lang.Exception _exception) {
return (com.adonix.www.WSS.CAdxResultXml) org.apache.axis.utils.JavaUtils.convert(_resp, com.adonix.www.WSS.CAdxResultXml.class);
}
}
} catch (org.apache.axis.AxisFault axisFaultException) {
throw axisFaultException;
}
}
The solution I came up with is not elegant, but then I'm not a guru in Java, just know enough to be given these tasks.
Our company uses Sage as our ERP system and Sage has a WSDL to define the basic web services it provides.
Sage Web Servicew WSDL
In their latest version of Sage they went with basic authentication, but did not build it into the new WSDL. Since I could not seem to extend the class (CAdxWebServiceXmlCCService), I just copied/pasted a new class called CAdxWebServiceXmlCCServiceBasicAuth. The full code is shown below if anyone ever has need to deal with something like this in a web service.
The key point where BaiscAuth set set up is in the getCAdxWebServiceXmlCC method. I added setPassword and setUserName to the stub that is returned. What this accomplishes is that every time I perform a webservice method call, that stub is now part of the header.
package com.adonix.www.WSS;
import java.net.URL;
import java.util.Base64;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import javax.xml.rpc.ServiceException;
public class CAdxWebServiceXmlCCServiceBasicAuth extends org.apache.axis.client.Service implements com.adonix.www.WSS.CAdxWebServiceXmlCCService {
public CAdxWebServiceXmlCCServiceBasicAuth() {
}
public CAdxWebServiceXmlCCServiceBasicAuth(org.apache.axis.EngineConfiguration config) {
super(config);
}
public CAdxWebServiceXmlCCServiceBasicAuth(java.lang.String wsdlLoc, javax.xml.namespace.QName sName) throws javax.xml.rpc.ServiceException {
super(wsdlLoc, sName);
}
// Use to get a proxy class for CAdxWebServiceXmlCC
private java.lang.String CAdxWebServiceXmlCC_address = "http://10.28.0.7:8124/soap-generic/syracuse/collaboration/syracuse/CAdxWebServiceXmlCC";
public java.lang.String getCAdxWebServiceXmlCCAddress() {
return CAdxWebServiceXmlCC_address;
}
// The WSDD service name defaults to the port name.
private java.lang.String CAdxWebServiceXmlCCWSDDServiceName = "CAdxWebServiceXmlCC";
public java.lang.String getCAdxWebServiceXmlCCWSDDServiceName() {
return CAdxWebServiceXmlCCWSDDServiceName;
}
public void setCAdxWebServiceXmlCCWSDDServiceName(java.lang.String name) {
CAdxWebServiceXmlCCWSDDServiceName = name;
}
public com.adonix.www.WSS.CAdxWebServiceXmlCC getCAdxWebServiceXmlCC(String userName,String password) throws javax.xml.rpc.ServiceException {
java.net.URL endpoint;
try {
endpoint = new java.net.URL(CAdxWebServiceXmlCC_address);
}
catch (java.net.MalformedURLException e) {
throw new javax.xml.rpc.ServiceException(e);
}
return getCAdxWebServiceXmlCC(endpoint,userName,password);
}
public com.adonix.www.WSS.CAdxWebServiceXmlCC getCAdxWebServiceXmlCC(java.net.URL portAddress,String userName,String password) throws javax.xml.rpc.ServiceException {
try {
com.adonix.www.WSS.CAdxWebServiceXmlCCSoapBindingStub _stub = new com.adonix.www.WSS.CAdxWebServiceXmlCCSoapBindingStub(portAddress, this);
_stub.setPortName(getCAdxWebServiceXmlCCWSDDServiceName());
_stub.setPassword(password);
_stub.setUsername(userName);
return _stub;
}
catch (org.apache.axis.AxisFault e) {
return null;
}
}
public void setCAdxWebServiceXmlCCEndpointAddress(java.lang.String address) {
CAdxWebServiceXmlCC_address = address;
}
/**
* For the given interface, get the stub implementation.
* If this service has no port for the given interface,
* then ServiceException is thrown.
*/
public java.rmi.Remote getPort(Class serviceEndpointInterface) throws javax.xml.rpc.ServiceException {
try {
if (com.adonix.www.WSS.CAdxWebServiceXmlCC.class.isAssignableFrom(serviceEndpointInterface)) {
com.adonix.www.WSS.CAdxWebServiceXmlCCSoapBindingStub _stub = new com.adonix.www.WSS.CAdxWebServiceXmlCCSoapBindingStub(new java.net.URL(CAdxWebServiceXmlCC_address), this);
_stub.setPortName(getCAdxWebServiceXmlCCWSDDServiceName());
return _stub;
}
}
catch (java.lang.Throwable t) {
throw new javax.xml.rpc.ServiceException(t);
}
throw new javax.xml.rpc.ServiceException("There is no stub implementation for the interface: " + (serviceEndpointInterface == null ? "null" : serviceEndpointInterface.getName()));
}
/**
* For the given interface, get the stub implementation.
* If this service has no port for the given interface,
* then ServiceException is thrown.
*/
public java.rmi.Remote getPort(javax.xml.namespace.QName portName, Class serviceEndpointInterface) throws javax.xml.rpc.ServiceException {
if (portName == null) {
return getPort(serviceEndpointInterface);
}
java.lang.String inputPortName = portName.getLocalPart();
if ("CAdxWebServiceXmlCC".equals(inputPortName)) {
return getCAdxWebServiceXmlCC();
}
else {
java.rmi.Remote _stub = getPort(serviceEndpointInterface);
((org.apache.axis.client.Stub) _stub).setPortName(portName);
return _stub;
}
}
public javax.xml.namespace.QName getServiceName() {
return new javax.xml.namespace.QName("http://www.adonix.com/WSS", "CAdxWebServiceXmlCCService");
}
private java.util.HashSet ports = null;
public java.util.Iterator getPorts() {
if (ports == null) {
ports = new java.util.HashSet();
ports.add(new javax.xml.namespace.QName("http://www.adonix.com/WSS", "CAdxWebServiceXmlCC"));
}
return ports.iterator();
}
/**
* Set the endpoint address for the specified port name.
*/
public void setEndpointAddress(java.lang.String portName, java.lang.String address) throws javax.xml.rpc.ServiceException {
if ("CAdxWebServiceXmlCC".equals(portName)) {
setCAdxWebServiceXmlCCEndpointAddress(address);
}
else
{ // Unknown Port Name
throw new javax.xml.rpc.ServiceException(" Cannot set Endpoint Address for Unknown Port" + portName);
}
}
/**
* Set the endpoint address for the specified port name.
*/
public void setEndpointAddress(javax.xml.namespace.QName portName, java.lang.String address) throws javax.xml.rpc.ServiceException {
setEndpointAddress(portName.getLocalPart(), address);
}
#Override
public CAdxWebServiceXmlCC getCAdxWebServiceXmlCC() throws ServiceException {
// TODO Auto-generated method stub
return null;
}
#Override
public CAdxWebServiceXmlCC getCAdxWebServiceXmlCC(URL portAddress) throws ServiceException {
// TODO Auto-generated method stub
return null;
}
}
I want to create a generic method for sending emails with attachments, I was thinking about using something like this:
public class MailAttachment<T> {
private String attachmentName;
private T attachment;
public MailAttachment(String attachmentName, T attachment) {
super();
this.attachmentName = attachmentName;
this.attachment = attachment;
}
//Getters and setters
}
Later, send the generic type and let Java decide in compilation time the instance type sent. But the compiler adds an error saying that it needs to be cast to the correct type (File, DataSource, InputStreamSource).
#Autowired
private JavaMailSender mailSender;
public void sendHtmlMail(Mail mail, MailAttachment<?> attachment) {
new Thread(() -> {
try {
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setTo(mail.getTo());
helper.setSubject(mail.getSubject());
helper.setFrom(host);
message.setContent(mail.getContent(), "text/html");
if (attachment != null) {
//Casting error
helper.addAttachment(attachment.getAttachmentName(), attachment.getAttachment());
}
mailSender.send(message);
} catch (MessagingException | MailException e) {
logger.error("Error sending email: ", e);
}
}).start();
}
So I had to use a workaround to validate and cast to the correct type, something like this:
if (attachment.getAttachment() instanceof DataSource) {
helper.addAttachment(attachment.getAttachmentName(),
(DataSource) attachment.getAttachment());
} else if (attachment.getAttachment() instanceof File) {
helper.addAttachment(attachment.getAttachmentName(),
(File) attachment.getAttachment());
} else if (attachment.getAttachment() instanceof InputStreamSource) {
helper.addAttachment(attachment.getAttachmentName(),
(InputStreamSource) attachment.getAttachment());
}
So, I was wondering if there is a better way to check this kind of stuff using only this method while keeping the generic type in the parameter?
Create an interface Attachable:
interface Attachable {
void attach(Helper helper);
}
and then implement this for the various types:
class DataSourceAttachable implements Attachable {
String name;
DataSource dataSource; // Initialize in ctor.
void attach(Helper helper) {
helper.addAttachment(name, dataSource);
}
}
// etc, for other types
Then there is no need for generics:
public void sendHtmlMail(Mail mail, Attachable attachable) {
// ...
attachable.attach(helper);
// ...
}
I try to investigate classes available in a given package. for time being i have hard coded the class name, I get so many methods which are not available in the class when i try to print all the methods and parameter type the method takes
the following is my main class where i investigate the class and its method :
package com.hexgen.reflection;
`// removed imports to post question`
import com.hexgen.tools.HexgenClassUtils;
public class HexgenWebAPITest {
#SuppressWarnings({ "rawtypes", "unchecked", "unused" })
public static void main(String[] args) {
HexgenWebAPITest test = new HexgenWebAPITest();
HexgenClassUtils hexgenClassUtils = new HexgenClassUtils();
String uri="";
String[] mappingValues=null;
HttpClientRequests httpRequest = new HttpClientRequests();
Class parames = CreateRequisitionRO[].class;
Class booleanVal;
booleanVal = Boolean.TYPE;
Class cls;
try {
List classNames = hexgenClassUtils.findMyTypes("com.hexgen.*");
Iterator<Class> it = classNames.iterator();
while(it.hasNext())
{
Class obj = it.next();
System.out.println("Methods available in : "+obj.getName());
System.out.println("===================================");
if(obj.getName().equals("com.hexgen.api.facade.HexgenWebAPI")){
cls = Class.forName(obj.getName());
cls.getClass();
Method[] method = cls.getDeclaredMethods();
int i=1;
for (Method method2 : method) {
System.out.println(+i+":"+method2.getName());
Class[] parameterTypes = method2.getParameterTypes();
for (Class class1 : parameterTypes) {
System.out.println("Parameter Type : "+class1.getName());
}
i++;
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
this is the Utility Class
package com.hexgen.tools;
// removed imports to post the question here
public class HexgenClassUtils {
#SuppressWarnings({ "rawtypes"})
public List<Class> findMyTypes(String basePackage) throws IOException, ClassNotFoundException
{
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resourcePatternResolver);
List<Class> candidates = new ArrayList<Class>();
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + "/" + "**/*.class";
Resource[] resources = resourcePatternResolver.getResources(packageSearchPath);
for (Resource resource : resources) {
if (resource.isReadable()) {
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);
if (isCandidate(metadataReader)) {
candidates.add(Class.forName(metadataReader.getClassMetadata().getClassName()));
}
}
}
return candidates;
}
public String resolveBasePackage(String basePackage) {
return ClassUtils.convertClassNameToResourcePath(SystemPropertyUtils.resolvePlaceholders(basePackage));
}
#SuppressWarnings({ "rawtypes", "unchecked" })
public boolean isCandidate(MetadataReader metadataReader) throws ClassNotFoundException
{
try {
Class c = Class.forName(metadataReader.getClassMetadata().getClassName());
if (!c.isInterface() && c.getAnnotation(Controller.class) != null) {
return true;
}
}
catch(Throwable e){
}
return false;
}
}
and this is the actual class which i am investigating:
package com.hexgen.api.facade;
`// removed imports to post question here`
import com.hexgen.datauploader.ETLServiceProvider;
import com.hexgen.ro.response.UserDetailsResponse;
/**
* Hexagon Global IT Services (ALL RIGHTS RESERVED) Created with IntelliJ IDEA.
* User: mayankk Date: 23/11/12 Time: 10:27 AM To change this template use File
* | Settings | File Templates.
*/
#Controller
#Transactional
public class HexgenWebAPI {
#Resource(name = "facadeDbFuncs")
private DbFuncs dbFuncs;
#Resource(name = "gatekeeper")
private IGateKeeper gateKeeper;
#Resource(name = "userContext")
private UserContext userContext;
#Resource(name = "costCalc")
private FinancialCalculator financialCalculator;
#Resource(name = "ytmCalc")
private YTMCalculator ytmCalc;
#Resource(name = "etlService")
private ETLServiceProvider etlService;
#Resource(name = "biManager")
private IBIManager biManager;
private String tmpFileName;
Logger logger = LoggerFactory.getLogger(HexgenWebAPI.class);
private Pattern c4Pattern;
public HexgenWebAPI() {
String cmdPattern = "([bsBS])[ ]+(\\w+)[ ]+(\\d+)[ ]*#[ ]*(\\d+\\.?\\d*)";
c4Pattern = Pattern.compile(cmdPattern);
}
#RequestMapping(method = RequestMethod.GET, value = "/user/details")
public #ResponseBody
UserDetailsResponse getLoggedinUserDetails() {
HexGenUser details = (HexGenUser) SecurityContextHolder.getContext()
.getAuthentication().getPrincipal();
populateImplementationDetails(response);
return response;
}
private void populateImplementationDetails(UserDetailsResponse response) {
logger.debug("Finding revision details");
try {
CodeSource codeSource = this.getClass().getProtectionDomain()
.getCodeSource();
if (codeSource != null) {
JarInputStream jarStream = new JarInputStream(codeSource
.getLocation().openStream());
Manifest manifest = jarStream.getManifest();
logger.debug("Manifest not found!");
if (manifest != null) {
}
}
} catch (Throwable e) {
logger.debug(e.getMessage());
}
logger.debug("Could not find revision details, seems like development environment.");
}
#PreAuthorize("isAuthenticated() and hasPermission(#request, 'CREATE_REQUISITION')")
#RequestMapping(method = RequestMethod.POST, value = "/trade/createrequisition")
public #ResponseBody
void createRequisition(#RequestBody CreateRequisitionRO[] request,
#RequestHeader("validateOnly") boolean validateOnly) {
logger.debug("Starting createRequisition()...");
for (int i = 0; i < request.length; i++) {
CreateRequisitionRO requisitionRequest = request[i];
{
logger.debug("Record is for update ? {}", mr.isUpdate());
logger.debug("attrs are {}", mr.getChangedRecord());
}
gateKeeper.route(request);
}
#PreAuthorize("isAuthenticated() and hasPermission(#request, 'CREATE_ORDER')")
#RequestMapping(method = RequestMethod.POST, value = "/trade/createorder")
public #ResponseBody
void createOrder(#RequestBody CreateOrderRO request,
#RequestHeader("validateOnly") boolean validateOnly) {
TradeDtl orderRow = dbFuncs.references.tradeDtl.findByTransId(request
.getTransRef());
d
logger.debug("Starting createOrder()...");
gateKeeper.route(request);
}
#RequestMapping(method = RequestMethod.POST, value = "/trade/confirmorder")
public #ResponseBody
void confirmOrder(#RequestBody ConfirmOrderRO request,
#RequestHeader("validateOnly") boolean validateOnly) {
logger.debug("Starting confirmOrder()...");
gateKeeper.route(request);
}
#RequestMapping(method = RequestMethod.PUT, value = "/trade/review/approve")
public #ResponseBody
void approveReview(#RequestBody ApproveReviewRO request,
#RequestHeader("validateOnly") boolean validateOnly) {
logger.trace("approveReview({},{})", request, validateOnly);
gateKeeper.route(request);
}
#RequestMapping(method = RequestMethod.PUT, value = "/trade/review/reject")
public #ResponseBody
void rejectReview(#RequestBody RejectReviewRO request,
#RequestHeader("validateOnly") boolean validateOnly) {
logger.trace("HexgenWebAPI.rejectReview({},{})", request, validateOnly);
gateKeeper.route(request);
}
#RequestMapping(method = RequestMethod.PUT, value = "/upload/overwrite/approve")
public #ResponseBody
void approveUpload(#RequestBody ApproveReviewRO request,
#RequestHeader("validateOnly") boolean validateOnly) {
logger.trace("approveUpload({},{})", request, validateOnly);
UploadJobMaster uploadJobMaster = dbFuncs.references.uploadJobMaster.findOne(request.getId());
AbstractUploadOverwriteRO uploadAcceptRO = null;
Class<?> loaderRO = null;
try {
String className = etlService.getOverwriteAcceptEventName(uploadJobMaster.getUploadGenericType());
loaderRO = Class.forName(className);
uploadAcceptRO = (AbstractUploadOverwriteRO) loaderRO.newInstance();
uploadAcceptRO.setUploadID(uploadJobMaster.getUploadId());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
gateKeeper.route((IRO) uploadAcceptRO);
}
#RequestMapping(method = RequestMethod.PUT, value = "/upload/overwrite/reject")
public #ResponseBody
void rejectUpload(#RequestBody RejectReviewRO request,
#RequestHeader("validateOnly") boolean validateOnly) {
try {
String className = etlService.getOverwriteRejectEventName(uploadJobMaster.getUploadGenericType());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
gateKeeper.route((IRO) uploadRejectRO);
}
#RequestMapping(method = RequestMethod.POST, value = "/upload/file")
public #ResponseBody
FileUploadResponse upload(#RequestParam("file") MultipartFile file) {
FileUploadResponse fileUploadResponse = new FileUploadResponse();
try {
file.transferTo(tmpFile);
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
fileUploadResponse.setStatusMessage("passed");
return fileUploadResponse;
}
#RequestMapping(method = RequestMethod.POST, value = "/upload/form/{uploadType}/{uploadName}")
public #ResponseBody
void uploadForm(#PathVariable String uploadType,
#PathVariable String uploadName) {
FileReceivedForUploadRO requisitionRequest = new FileReceivedForUploadRO(
gateKeeper.route(requisitionRequest);
}
//Reports
#PostFilter("isAuthenticated() and hasPermission(null, 'REPG' + filterObject.groupId)")
#RequestMapping(method = RequestMethod.GET, value = "/reports/groups")
public #ResponseBody
List<ReportsGroups> RetrieveReportGroups() {
UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return biManager.getReportGroups();
}
#PostFilter("isAuthenticated() and hasPermission(null, 'REPN' + filterObject.reportId)")
#RequestMapping(method = RequestMethod.GET, value = "/reports/list")
public #ResponseBody
List<ReportNames> RetrieveReports(#RequestParam("groupId") BigDecimal groupId) {
return biManager.getReportNames(groupId);
}
#PreAuthorize("isAuthenticated() and hasPermission(null, 'REPN' + #reportId)")
#RequestMapping(method = RequestMethod.GET, value = "/reports/fields")
public #ResponseBody
List<FilterParameters> RetrieveReportFields(#RequestParam("reportId") BigDecimal reportId) {
ReportGroupMapping report = dbFuncs.references.reportGroupMapping.findOne(reportId);
return biManager.getFilterParameters(report.getReportName());
}
#PreAuthorize("isAuthenticated() and hasPermission(null, 'REPN' + #request.reportId)")
#RequestMapping(method = RequestMethod.POST, value = "/reports/generateurl")
public #ResponseBody
GenerateURLResponse generateURL(#RequestBody GenerateURLRO request) {
ReportGroupMapping report = dbFuncs.references.reportGroupMapping.findOne(request.getReportId());
try {
return new GenerateURLResponse(biManager.generateURL(report.getReportName(), request.getReportParameters()));
} catch(BOValidationException e) {
throw new ValidationException(e.getViolations());
}
}
// TODO throw away code
#RequestMapping(method = RequestMethod.POST, value = "/upload/eodprocess")
public #ResponseBody
void dayChange() {
DayChangeRO dayChangeRO = new DayChangeRO();
gateKeeper.route(dayChangeRO);
}
#RequestMapping(method = RequestMethod.GET, value = "/overview/holdings")
public #ResponseBody
List<HoldingsRO> generateHoldingsReport() {
List<HoldingsQO> holdingsQO = dbFuncs.references.reportsMgrFinders
.getAllHoldings();
holdingsRO.add(new HoldingsRO(holding.getAssetClass(), holding
.getUnRealTcy(), holding.getUnRealPcy()));
}
return holdingsRO;
}
#RequestMapping(method = RequestMethod.GET, value = "/overview/funds")
public #ResponseBody
List<FundOverviewRO> generatePortfolioTrend() {
List<FundOverviewQO> fundOverviewQO = dbFuncs.references.reportsMgrFinders
.getPortfolioMovement();
List<FundOverviewRO> fundOverviewRO = new ArrayList<FundOverviewRO>();
.getLast30Day()));
}
return fundOverviewRO;
}
#RequestMapping(method = RequestMethod.GET, value = "/fund/holdings/{portfolio}")
public #ResponseBody
List<HoldingsRO> generateHoldingsReport(#PathVariable String portfolio) {
List<HoldingsQO> holdingsQO = dbFuncs.references.reportsMgrFinders
.getFundHoldings(portfolio);
List<HoldingsRO> holdingsRO = new ArrayList<HoldingsRO>();
for (HoldingsQO holding : holdingsQO) {
String securityDescription = holding.getSecurityDescription()
.substring(
0,
Math.min(holding.getSecurityDescription().length(),
20));
holdingsRO.add(new HoldingsRO(holding.getAssetClass(), holding
.getAccrIntTcy(), holding.getAodTcy(), holding
.getUnRealTcy(), holding.getUnRealPcy()));
}
return holdingsRO;
}
#RequestMapping(method = RequestMethod.GET, value = "/fund/concentration/{portfolio}")
public #ResponseBody
ConcentrationRO[] getConcentrationForFund(#PathVariable String portfolio) {
List<ConcentrationRO> concentrations = new ArrayList<ConcentrationRO>();
concentrations
.add(generateConcentrationRO(dbFuncs.references.concentrationFinders
.getAssetGroupExposureFor(userContext.getCompany(),
portfolio)));
concentrations
.add(generateConcentrationRO(dbFuncs.references.concentrationFinders
.getAssetClassExposureFor(userContext.getCompany(),
portfolio)));
concentrations
.add(generateConcentrationRO(dbFuncs.references.concentrationFinders
.getIndustryExposureFor(userContext.getCompany(),
portfolio, "IND")));
return concentrations
.toArray(new ConcentrationRO[concentrations.size()]);
}
#RequestMapping(method = RequestMethod.GET, value = "/overview/concentration")
public #ResponseBody
ConcentrationRO[] getConcentrationForFund() {
List<ConcentrationRO> concentrations = new ArrayList<ConcentrationRO>();
concentrations
.add(generateConcentrationRO(dbFuncs.references.concentrationFinders
.getAssetGroupExposureFor(userContext.getCompany())));
concentrations
.add(generateConcentrationRO(dbFuncs.references.concentrationFinders
.getAssetClassExposureFor(userContext.getCompany())));
concentrations
.add(generateConcentrationRO(dbFuncs.references.concentrationFinders
.getIndustryExposureFor(userContext.getCompany(), "IND")));
return concentrations
.toArray(new ConcentrationRO[concentrations.size()]);
}
public ConcentrationRO generateConcentrationRO(
ConcentrationFinders concentrationFinder) {
ConcentrationRO concentrationRO = new ConcentrationRO();
for (ValueQO valueQO : concentrationFinder.getValues()) {
concentrationRO.addValue(valueQO.getName(), valueQO.getActual(),
valueQO.getGuidance());
}
return concentrationRO;
}
#RequestMapping(method = RequestMethod.POST, value = "/c4/execute")
public #ResponseBody
void executeC4Command(#RequestBody C4CommandRO request) {
logger.debug("Received command for execution : " + request.getCmd());
try {
Matcher matcher = c4Pattern.matcher(request.getCmd());
if (matcher.matches()) {
String parsedTransCode = matcher.group(1);
} else {
logger.debug("Invalid C4 command");
throw new RuntimeException();
}
} catch (Throwable e) {
logger.debug("Ooops !! C4 command execution failed - "
+ e.getMessage());
throw new RuntimeException(e);
}
}
// FIXME C4 throw away code
private void createRequisitionThroughC4(String security, String transCode,
BigDecimal price, BigDecimal quantity) {
logger.debug("Starting createRequisition() through C4...");
try {
Security securityRow = dbFuncs.references.security
.findBySecurity(security);
if (securityRow.getIsIntApplic() || securityRow.getIsDiscounted()) {
createRequisition.setYtm(ytmCalc.computeXIRR(security, price,
userContext.getBusinessDate()));
} else {
createRequisition.setYtm(BigDecimal.ZERO);
}
SystemDefault defaults = dbFuncs.references.systemDefault
.findByParamLevelAndCompanyAndDivisionAndPortfolio(
ParamLevel.PF, userContext.getCompany(),
userContext.getDivision(), portfolio);
OutputValuesFromInvestmentsDO response = financialCalculator
.costSettlementCalculator(input);
createRequisition.setTransSrlNo(BigDecimal.ONE);
if (transCode.equals("BUY")) {
createRequisition.setInflowOutflow(InflowOutflow.I);
} else {
createRequisition.setInflowOutflow(InflowOutflow.O);
}
createRequisition.setFundManager(createRequisition.getUserId());
createRequisition.setCustodianN(defaults.getCustodianN());
gateKeeper.route(createRequisition);
} catch (Throwable e) {
logger.debug("Ooops !! C4 command execution failed - "
+ e.getMessage());
throw new RuntimeException(e);
}
}
}
but the folloing is the out put i get where i see many methods are not present in the class :
1:ajc$get$validator
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
2:ajc$set$validator
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : javax.validation.Validator
3:ajc$get$requestToEventTranslator
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
4:ajc$set$requestToEventTranslator
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : com.hexgen.p0.translator.RequestToEventTranslator
5:ajc$interMethodDispatch2$com_hexgen_api_facade_HexgenWebAPIValidation$validate
Parameter Type : com.hexgen.ro.IRO
6:handleValidationException
Parameter Type : com.hexgen.api.facade.ValidationException
7:createRequisition
Parameter Type : [Lcom.hexgen.ro.request.CreateRequisitionRO;
Parameter Type : boolean
8:getLoggedinUserDetails
9:populateImplementationDetails
Parameter Type : com.hexgen.ro.response.UserDetailsResponse
10:excelMDM
Parameter Type : com.hexgen.ro.request.MdmFromExcelRO
11:createOrder
Parameter Type : com.hexgen.ro.request.CreateOrderRO
Parameter Type : boolean
12:confirmOrder
Parameter Type : com.hexgen.ro.request.ConfirmOrderRO
Parameter Type : boolean
13:approveReview
Parameter Type : com.hexgen.ro.request.ApproveReviewRO
Parameter Type : boolean
14:rejectReview
Parameter Type : com.hexgen.ro.request.RejectReviewRO
Parameter Type : boolean
15:approveUpload
Parameter Type : com.hexgen.ro.request.ApproveReviewRO
Parameter Type : boolean
16:rejectUpload
Parameter Type : com.hexgen.ro.request.RejectReviewRO
Parameter Type : boolean
17:upload
Parameter Type : org.springframework.web.multipart.MultipartFile
18:uploadForm
Parameter Type : java.lang.String
Parameter Type : java.lang.String
19:RetrieveReportGroups
20:RetrieveReports
Parameter Type : java.math.BigDecimal
21:RetrieveReportFields
Parameter Type : java.math.BigDecimal
22:generateURL
Parameter Type : com.hexgen.ro.request.GenerateURLRO
23:dayChange
24:generateHoldingsReport
25:generateHoldingsReport
Parameter Type : java.lang.String
26:generatePortfolioTrend
27:getConcentrationForFund
Parameter Type : java.lang.String
28:getConcentrationForFund
29:generateConcentrationRO
Parameter Type : com.hexgen.core.orm.finders.repositories.ConcentrationFinders
30:executeC4Command
Parameter Type : com.hexgen.ro.request.C4CommandRO
31:createRequisitionThroughC4
Parameter Type : java.lang.String
Parameter Type : java.lang.String
Parameter Type : java.math.BigDecimal
Parameter Type : java.math.BigDecimal
32:createRequisition_aroundBody0
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : [Lcom.hexgen.ro.request.CreateRequisitionRO;
Parameter Type : boolean
33:createRequisition_aroundBody1$advice
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : [Lcom.hexgen.ro.request.CreateRequisitionRO;
Parameter Type : boolean
Parameter Type : com.hexgen.api.facade.HexgenWebAPIValidation
Parameter Type : [Lcom.hexgen.ro.IRO;
Parameter Type : boolean
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : org.aspectj.runtime.internal.AroundClosure
34:createOrder_aroundBody2
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : com.hexgen.ro.request.CreateOrderRO
Parameter Type : boolean
35:createOrder_aroundBody3$advice
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : com.hexgen.ro.request.CreateOrderRO
Parameter Type : boolean
Parameter Type : com.hexgen.api.facade.HexgenWebAPIValidation
Parameter Type : com.hexgen.ro.IRO
Parameter Type : boolean
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : org.aspectj.runtime.internal.AroundClosure
36:confirmOrder_aroundBody4
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : com.hexgen.ro.request.ConfirmOrderRO
Parameter Type : boolean
37:confirmOrder_aroundBody5$advice
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : com.hexgen.ro.request.ConfirmOrderRO
Parameter Type : boolean
Parameter Type : com.hexgen.api.facade.HexgenWebAPIValidation
Parameter Type : com.hexgen.ro.IRO
Parameter Type : boolean
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : org.aspectj.runtime.internal.AroundClosure
38:approveReview_aroundBody6
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : com.hexgen.ro.request.ApproveReviewRO
Parameter Type : boolean
39:approveReview_aroundBody7$advice
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : com.hexgen.ro.request.ApproveReviewRO
Parameter Type : boolean
Parameter Type : com.hexgen.api.facade.HexgenWebAPIValidation
Parameter Type : com.hexgen.ro.IRO
Parameter Type : boolean
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : org.aspectj.runtime.internal.AroundClosure
40:rejectReview_aroundBody8
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : com.hexgen.ro.request.RejectReviewRO
Parameter Type : boolean
41:rejectReview_aroundBody9$advice
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : com.hexgen.ro.request.RejectReviewRO
Parameter Type : boolean
Parameter Type : com.hexgen.api.facade.HexgenWebAPIValidation
Parameter Type : com.hexgen.ro.IRO
Parameter Type : boolean
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : org.aspectj.runtime.internal.AroundClosure
42:approveUpload_aroundBody10
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : com.hexgen.ro.request.ApproveReviewRO
Parameter Type : boolean
43:approveUpload_aroundBody11$advice
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : com.hexgen.ro.request.ApproveReviewRO
Parameter Type : boolean
Parameter Type : com.hexgen.api.facade.HexgenWebAPIValidation
Parameter Type : com.hexgen.ro.IRO
Parameter Type : boolean
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : org.aspectj.runtime.internal.AroundClosure
44:rejectUpload_aroundBody12
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : com.hexgen.ro.request.RejectReviewRO
Parameter Type : boolean
45:rejectUpload_aroundBody13$advice
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : com.hexgen.ro.request.RejectReviewRO
Parameter Type : boolean
Parameter Type : com.hexgen.api.facade.HexgenWebAPIValidation
Parameter Type : com.hexgen.ro.IRO
Parameter Type : boolean
Parameter Type : com.hexgen.api.facade.HexgenWebAPI
Parameter Type : org.aspectj.runtime.internal.AroundClosure
46:ajc$preClinit
Different parts of the Spring frame-work perform instrumentation at run-time to, to augment classes and provide additional functionality. Spring uses three different kinds of instrumentation:
DynamicProxies - this is a feature of J2SE, and allows generating an interface "on-the-fly" by specifying "method handlers" - a method that gets called to handle method invocations. The handler will look at the method signature and arguments to decide what to do. Typically this will involve adding dome functionality before or after calling a the corresponding method on a concrete target class that implements the same interface. (Hence the name 'proxy'). Dynamic Proxies are the default when a class is backed by an interface.
Byte-code-engineering (BCEL). This involves overriding the class-loader method that loads a class the first time it is required. The overridden method returns a sub-class that is generated at runtime, and includes extra functionality. The library that Spring uses this is 'cglib' which is built on top of 'asm'. . . These libraries prioritize performance over ease-of-use. . . (ease of use not being a concern, since the Spring user doesn't do any byte-code engineering for themselves - just uses the instrumented classes).
AspectJ weaving. This involves using either compile-time weaving or runtime weaving. In the case of the latter a special Java Agent is used (cmd-line argument to the JVM) instead of intercepting the classloader.
Examples of instrumentation are annotation-based transactions, security annotations, validation, etc.
You are observing the second type of instrumentation (a runtime generated sub-class), which is the default for concrete classes. . . (AspectJ can be used in more complex situations, such as providing dependency injection on classes outside of the Spring container).
I've written a bean class containing a HashMultiMap (from the Guava library). I would like to XML encode the bean using the JRE's XMLEncoder. Using a custom PersistenceDelegate I've successfully written the bean to file. However, when I attempt to deserialize the XML I get the exception:
java.lang.NoSuchMethodException: <unbound>=HashMultimap.put("pz1", "pz2")
What am I doing wrong?
// create the bean
SomeBean sb = new SomeBean();
// add some data
HashMultimap<String, String> stateMap = HashMultimap.create();
stateMap.put("pz1", "pz2");
stateMap.put("pz3", "pz4");
sb.setStateMap(stateMap);
// encode as xml
FileOutputStream os = new FileOutputStream("myXMLFile.xml");
XMLEncoder encoder = new XMLEncoder(os);
encoder.setPersistenceDelegate(HashMultimap.class, new CustomPersistenceDelegate());
encoder.writeObject(sb);
// decode the xml
FileInputStream is = new FileInputStream("myXMLFile.xml");
XMLDecoder decoder = new XMLDecoder(is);
Object deSerializedObject = decoder.readObject();
class CustomPersistenceDelegate extends DefaultPersistenceDelegate
{
protected Expression instantiate(Object oldInstance, Encoder out)
{
return new Expression(oldInstance, oldInstance.getClass(), "create", null);
}
protected void initialize(Class<?> type, Object oldInstance, Object newInstance,
Encoder out)
{
super.initialize(type, oldInstance, newInstance, out);
com.google.common.collect.HashMultimap<String, String> m =
(com.google.common.collect.HashMultimap) oldInstance;
for (Map.Entry<String, String> entry : m.entries())
{
out.writeStatement(new Statement(oldInstance, "put",
new Object[] { entry.getKey(), entry.getValue() }));
}
}
}
public class SomeBean
{
private HashMultimap<String, String> stateMap;
public HashMultimap<String, String> getStateMap()
{
return stateMap;
}
public void setStateMap(HashMultimap<String, String> stateMap)
{
this.stateMap = stateMap;
}
}
I don't have a solution (yet). But here is something which at least clarifies the problem. It seems that some change made in Java 7 build 15 and higher has broken the method look up that your Statement requires. If you add an ExceptionListener to the XmlEncoder, it gives you a better idea of how this is failing:
encoder.setExceptionListener(new ExceptionListener() {
#Override
public void exceptionThrown(Exception e) {
System.out.println("got exception. e=" + e);
e.printStackTrace();
}
});
You will see a full stacktrace then:
java.lang.Exception: Encoder: discarding statement HashMultimap.put(Object, Object);
at java.beans.Encoder.writeStatement(Encoder.java:306)
at java.beans.XMLEncoder.writeStatement(XMLEncoder.java:400)
at test2.XmlEncoderTest$CustomPersistenceDelegate.initialize(XmlEncoderTest.java:83)
at java.beans.PersistenceDelegate.writeObject(PersistenceDelegate.java:118)
at java.beans.Encoder.writeObject(Encoder.java:74)
at java.beans.XMLEncoder.writeObject(XMLEncoder.java:327)
at java.beans.Encoder.writeExpression(Encoder.java:330)
at java.beans.XMLEncoder.writeExpression(XMLEncoder.java:454)
at java.beans.PersistenceDelegate.writeObject(PersistenceDelegate.java:115)
at java.beans.Encoder.writeObject(Encoder.java:74)
at java.beans.XMLEncoder.writeObject(XMLEncoder.java:327)
at java.beans.Encoder.writeExpression(Encoder.java:330)
at java.beans.XMLEncoder.writeExpression(XMLEncoder.java:454)
at java.beans.DefaultPersistenceDelegate.doProperty(DefaultPersistenceDelegate.java:194)
at java.beans.DefaultPersistenceDelegate.initBean(DefaultPersistenceDelegate.java:253)
at java.beans.DefaultPersistenceDelegate.initialize(DefaultPersistenceDelegate.java:400)
at java.beans.PersistenceDelegate.writeObject(PersistenceDelegate.java:118)
at java.beans.Encoder.writeObject(Encoder.java:74)
at java.beans.XMLEncoder.writeObject(XMLEncoder.java:327)
at java.beans.Encoder.writeExpression(Encoder.java:330)
at java.beans.XMLEncoder.writeExpression(XMLEncoder.java:454)
at java.beans.PersistenceDelegate.writeObject(PersistenceDelegate.java:115)
at java.beans.Encoder.writeObject(Encoder.java:74)
at java.beans.XMLEncoder.writeObject(XMLEncoder.java:327)
at java.beans.Encoder.writeObject1(Encoder.java:258)
at java.beans.Encoder.cloneStatement(Encoder.java:271)
at java.beans.Encoder.writeStatement(Encoder.java:301)
at java.beans.XMLEncoder.writeStatement(XMLEncoder.java:400)
at java.beans.XMLEncoder.writeObject(XMLEncoder.java:330)
...
Caused by: java.lang.NoSuchMethodException: HashMultimap.put(Object, Object);
at java.beans.Statement.invokeInternal(Statement.java:313)
at java.beans.Statement.access$000(Statement.java:58)
at java.beans.Statement$2.run(Statement.java:185)
at java.security.AccessController.doPrivileged(Native Method)
at java.beans.Statement.invoke(Statement.java:182)
at java.beans.Statement.execute(Statement.java:173)
at java.beans.Encoder.writeStatement(Encoder.java:304)
... 51 more
The Caused by section shows that it failed to locate the put method. It looks to me like this happens because it can't match the method signature properly any more. It fails in the java beans MethodFinder, but since the source code is not included in JDK, I couldn't track it down well enough.
If I can find exact cause, I will update this. Just wanted to provide you with more information in the meantime.
UPDATE
I think it's a bug in these later versions. Here is a unit test which exposes the bug (or unexpected behavior) more directly. The failure below is exactly what is happening in your code:
#Test
public void testMethodFinder() throws Exception {
Method m0 = MethodFinder.findMethod(this.getClass(), "setUp", new Class<?>[0]);
assertNotNull(m0);
// this is okay, because method is declared in the type referenced
Method m = MethodFinder.findMethod(Multimap.class, "put", new Class<?>[] { Object.class, Object.class });
assertNotNull(m);
try {
// this fails, apparently because method is not declared in this subclass (is inherited from parent class)
Method m2 = MethodFinder.findMethod(HashMultimap.class, "put", new Class<?>[] { Object.class, Object.class });
assertNotNull(m2);
} catch (Exception e) {
System.out.println("got exception. e=" + e);
}
}
I am using TomCat 5.5 with MyFaces 1.1 and am trying to implement a custom regex validation tag.
My RegExValidator class looks like this:
public class RegExValidator implements Validator, StateHolder {
private String regex;
private boolean transientValue = false;
public RegExValidator() {
super();
}
public RegExValidator(String regex) {
this();
this.regex = regex;
}
public void validate(FacesContext context, UIComponent component, Object toValidate) throws ValidatorException {
if ((context == null) || (component == null)) {
throw new NullPointerException();
}
if (!(component instanceof UIInput)) {
return;
}
if (null == regex || null == toValidate) {
return;
}
String val = (String) toValidate;
if (!val.matches(regex)) {
FacesMessage errMsg = MessageFactory.createFacesMessage(context, Constants.FORMAT_INVALID_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, (new Object[]{regex}));
throw new ValidatorException(errMsg);
}
}
public Object saveState(FacesContext context) {
Object[] values = new Object[1];
values[0] = regex;
return (values);
}
public void restoreState(FacesContext context, Object state) {
Object[] values = (Object[]) state;
regex = (String) values[0];
}
public String getRegex() {
return regex;
}
public void setRegex(String regex) {
this.regex = regex;
}
public boolean isTransient() {
return transientValue;
}
public void setTransient(boolean transientValue) {
this.transientValue = transientValue;
}
}
My RegExValidatorTag class looks like this:
#SuppressWarnings("serial")
public class RegExValidatorTag extends ValidatorELTag {
private static String validatorID = null;
protected ValueExpression regex = null;
public RegExValidatorTag() {
super();
if (validatorID == null) {
validatorID = "RegExValidator";
}
}
public Validator createValidator() throws JspException {
FacesContext facesContext = FacesContext.getCurrentInstance();
RegExValidator result = null;
if (validatorID != null) {
result = (RegExValidator) facesContext.getApplication().createValidator(validatorID);
}
String patterns = null;
if (regex != null) {
if (!regex.isLiteralText()) {
patterns = (String) regex.getValue(facesContext.getELContext());
} else {
patterns = regex.getExpressionString();
}
}
result.setRegex(patterns);
return result;
}
public void setValidatorID(String validatorID) {
RegExValidatorTag.validatorID = validatorID;
}
/**
* #param regex
* the regex to set
*/
public void setRegex(ValueExpression regex) {
this.regex = regex;
}
}
My Taglibrary Descriptor looks like this:
<tag>
<name>regexValidator</name>
<tag-class>com.company.components.taglib.RegExValidatorTag</tag-class>
<attribute>
<name>regex</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
My face-common-config.xml has a Validator tag like this:
<validator>
<description>
Validate an input string value against a regular
expression specified by the "regex" attribute.
</description>
<validator-id>RegExValidator</validator-id>
<validator-class>com.company.components.validators.RegExValidator</validator-class>
<attribute>
<description>
The regular expression to test the value against
</description>
<attribute-name>regex</attribute-name>
<attribute-class>java.lang.String</attribute-class>
</attribute>
</validator>
And later on it is supposed to be used in a jsp file like this:
<tc:in value="${dataBean.currentBean.field}">
<a:regexValidator regex="${dataBean.currentBean.validationRegEx}" />
</tc:in>
When calling the page, the following error comes up:
javax.servlet.ServletException: javax.servlet.jsp.JspException: org.apache.jasper.JasperException: Unable to convert string "[\d{4}]" to class "javax.el.ValueExpression" for attribute "regex": Property Editor not registered with the PropertyEditorManager
Caused by:
org.apache.jasper.JasperException - Unable to convert string "[\d{4}]" to class "javax.el.ValueExpression" for attribute "regex": Property Editor not registered with the PropertyEditorManager
I hope I provided enough details for someone to help me out on this...
I seem to have a similar problem like yours, I'm trying to find the solution but seems that the problem is when using Tomcat or the application server(WebSphere Application Server 7.0) JSF libraries, my problem is that the new application server has new JSF libraries (1.2) instead of the 1.1 libraries that my old application server had. (Version 6.1)
To be more specific. my problem is described here. http://www-01.ibm.com/support/docview.wss?uid=swg21318801