I am using local entry to register the parameters and not to leave fixed in the artifacts, I do not know if it is better solution.
Everything works when I create the local entry in ESB Config, but when I create in the project registry resource I can not read correctly.
I am using code below to read local entry and write to a property:
<Property description = "SetPPSUserName" expression = "get-property ('registry', 'conf: /local-entries/PPS_Username.xml')" name = "SetPPSUserName" scope = "default" type = "STRING" />
Problem, is that it loads the entire xml contents of the local entry and not only the content, example as the property:
SetPPSUserName = "<localEntry key="PPS_Username" xmlns="http://ws.apache.org/ns/synapse"><![CDATA [content test blablab]]></ localEntry>"
Correct would be:
SetPPSUserName = "content test blablab"
NOTE: When I upload the CAR to the site, the local entry of the project registry resource does not appear in the local entry list of the management console.
Message translated from Portuguese to English with google translator
Try this:
Set type = OM in property instead of STRING.
<Property description = "SetPPSUserName" expression = "get-property ('registry', 'conf: /local-entries/PPS_Username.xml')" name = "SetPPSUserName" scope = "default" type = "OM" />
<log level="custom">
<property name="call_testProp" expression="$ctx:SetPPSUserName" type="STRING"/>
</log>
UPDATE 1:
My localEntry inside registry:
<localEntry key="PPS_Usernamelocal" xmlns="http://ws.apache.org/ns/synapse">
<a>
<b>TEST</b>
</a>
</localEntry>
My property and log mediator inside an esb proxy:
<property name="PPS_Username"
expression="get-property('registry','conf:/localentries/PPS_Username.xml')"
scope="default"
type="OM"/>
<log level="custom">
<property name="PPS_UsernameB" expression="$ctx:PPS_Username//syn:a/syn:b" xmlns:syn="http://ws.apache.org/ns/synapse"/>
</log>
My ESB response:
[2017-02-22 16:21:42,680] INFO - LogMediator PPS_UsernameB = TEST
Not sure if I got it right.
If you want to access a registry resource within a proxy you have to execute the following steps.
1.) create "Registry Resource Project"
2.) add a "Registry Resource" to that project. Because I faced some problems in the past with creating resources directly in dev studio, I always create a test/XML file with the content on my local disk and select "Import from file system" wen creating the resource
3.) create a CAR for the "Registry Resource Project"
4.) Open the pom.xml from the CAR project and change the "Server role" to "EnterpriseServiceBus" otherwise it won't get deployed to the ESB.
5.) Export the CAR and deploy it to the Server
Then you're able to access it inside the Proxy like this.
<property name="registryValue" expression="get-property('registry','gov:/path/property1.txt')"/>
Hope that helps.
Related
I am trying to transform json to xml using datamapper and i am getting the empty xml structure but not getting any values in wso2. I have created data mapper dependencies and loaded both input and out structures and used AI to map json -> xml and they mapped correctly.
I tried on eclipse oxygen(esb-6.2.0) and integration studio(v8) also and deployed in EI(6.5.0) but still the behavior is same empty response structure. I kept a log in the in-sequence and it is logging the json request but not the xml response. I am not getting why the issue is happening.
Please provide your thoughts and attached the code to this post. Please do needful
The issue is with the API. In the API we need to specify the input and the output data type. In your case since the transformation is from JSON to XML, the input type needs to be JSON while the output type needs to be XML. But you have defined both as xml which resulted in this issue. Modify the input type to JSON and you will get the expected results
<api xmlns="http://ws.apache.org/ns/synapse" name="DataMapper" context="/data">
<resource methods="POST" url-mapping="/mapper">
<inSequence>
<log separator="/">
<property name="payload" expression="json-eval($.body)"/>
</log>
<datamapper config="gov:datamapper/Wso2DataMapper.dmc" inputSchema="gov:datamapper/Wso2DataMapper_inputSchema.json" outputSchema="gov:datamapper/Wso2DataMapper_outputSchema.json" xsltStyleSheet="gov:datamapper/Wso2DataMapper_xsltStyleSheet.xml" inputType="JSON" outputType="XML"/>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
input
{
"studNo":"Sample studNo",
"studName":"Sample studName",
"StudGroup":"Sample StudGroup",
"studAddress":{
"addrLine1":"Sample addrLine1",
"AddrLine2":"Sample AddrLine2",
"Mandal":"Sample Mandal",
"District":"Sample District",
"State":"Sample State",
"Country":"Sample Country",
"Zip":"Sample Zip"
}
}
output
<Student xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<studentNo>Sample studNo</studentNo>
<studentName>Sample studName</studentName>
<studentGroup>Sample StudGroup</studentGroup>
<studentAddress>
<AddressLine1>Sample AddrLine2</AddressLine1>
<AddressLine2>Sample addrLine1</AddressLine2>
<Mandal>Sample Mandal</Mandal>
<District>Sample District</District>
<State>Sample State</State>
<Country>Sample Country</Country>
<ZIP>Sample Zip</ZIP>
</studentAddress>
</Student>
In order to test this function, I chosed Abnormal Request Count option, which is in Alert Management menu of Api Store, and added a restful api. Then I called this api for many times by Postman.
The carbon.log, which is in <API-M_ANALYTICS_HOME>/wso2/worker/logs, recorded the following error message:
[2020-10-19 11:03:36,094] ERROR {org.wso2.siddhi.core.stream.output.sink.Sink} - Error on 'APIM_ALERT_EMAIL_NOTIFICATION'. Dropping event at Sink 'email' at 'EmailNotificationStream' as its still trying to reconnect!, events dropped '<strong>Message:</strong>A request from a new IP (10.9.16.77) detected by user:admin#carbon.super using application:devMap owned by admin#carbon.super. <br><br> <strong>Type:</strong>UnusualIPAccess <br><br> <strong>AlertTimestamp:</strong>2020-10-19 11:03:35'
[2020-10-19 11:06:10,307] ERROR {org.wso2.siddhi.core.stream.output.sink.Sink} - Error on 'APIM_ALERT_EMAIL_NOTIFICATION'. Dropping event at Sink 'email' at 'EmailNotificationStream' as its still trying to reconnect!, events dropped '<strong>Message:</strong>Abnormal request count detected during last minute using application devMap owned by admin#carbon.super for api :全球风向查询, abnormal request count:9. <br><br> <strong>Type:</strong>AbnormalRequestsPerMin <br><br> <strong>AlertTimestamp:</strong>2020-10-19 11:06:10'
About detailed configuration, I referred the following links:
Configuring Alerts:
https://docs.wso2.com/display/AM260/Configuring+Alerts#ConfiguringAlerts-ConfiguringalertsviatheStore
Enabling Notifications:
https://docs.wso2.com/display/AM260/Enabling+Notifications
According to these documents, I did the following things:
1.Open the <API-M_ANALYTICS_HOME>/conf/worker/deployment.yaml file to configure the sender email address. The sample code is shown below:
siddhi:
extensions:
...
-
extension:
name: email
namespace: sink
properties:
username: abcd#163.com
address: abcd#163.com
password: xxxx
...
2.Go to the <API-M_ANALYTICS_HOME>/resources/apim-analytics/ directory. Copy the APIM_ALERT_EMAIL_NOTIFICATION.siddhi file and paste it in the <API-M_ANALYTICS_HOME>/wso2/worker/deployment/siddhi-files directory.
3.Set the email server configurations in the <API-M_HOME>/repository/conf/output-event-adapters.xml file under the section.
<adapterConfig type="email">
<!-- Comment mail.smtp.user and mail.smtp.password properties to support connecting SMTP servers which use trust
based authentication rather username/password authentication -->
<property key="mail.smtp.from">abcd#163.com</property>
<property key="mail.smtp.user">abcd</property>
<property key="mail.smtp.password">xxxx</property>
<property key="mail.smtp.host">smtp.163.com</property>
<property key="mail.smtp.port">25</property>
<property key="mail.smtp.starttls.enable">true</property>
<property key="mail.smtp.auth">true</property>
<!-- Thread Pool Related Properties -->
<property key="minThread">8</property>
<property key="maxThread">100</property>
<property key="keepAliveTimeInMillis">20000</property>
<property key="jobQueueSize">10000</property>
</adapterConfig>
4.Log in to the Management Console and click Main > Resource > Browse. Browse to the /_system/config/apimgt/applicationdata/tenant-conf.json file and click Edit as Text.Set the NotificationsEnabled property to true as shown below:
"NotificationsEnabled":"true",
"Notifications":[{
"Type":"new_api_version",
"Notifiers" :[{
"Class":"org.wso2.carbon.apimgt.impl.notification.NewAPIVersionEmailNotifier",
"ClaimsRetrieverImplClass":"org.wso2.carbon.apimgt.impl.token.DefaultClaimsRetriever",
"Title": "Version $2 of $1 Released",
"Template": " <html> <body> <h3 style=\"color:Black;\">We’re happy to announce the arrival of the next major version $2 of $1 API which is now available in Our API Store.</h3>Click here to Visit WSO2 API Store</body></html>"
}]
}
]
I've also checked APIM_ALERT_EMAIL_NOTIFICATION.siddhi:
#App:name("APIM_ALERT_EMAIL_NOTIFICATION")
#App:description('Send email to all the subscribers of a particular alert')
#source(type="inMemory", topic="APIM_EMAIL_NOTIFICATION", #map(type='passThrough'))
define stream EmailAlertStream (
type string,
message string,
alertTimestamp string,
emails string);
#sink(type='email', content.type="text/html", #map(type ='text', #payload('<strong>Message:</strong>{{message}} <br><br> <strong>Type:</strong>{{type}} <br><br> <strong>AlertTimestamp:</strong>{{alertTimestamp}}')),subject='Alerts from WSO2 APIM Analytics',to='{{emails}}')
define stream EmailNotificationStream (
type string,
message string,
alertTimestamp string,
emails string);
from EmailAlertStream
select *
insert into EmailNotificationStream;
As you can see, there is nothing special.
Have I missed anything to do? I don't know what the problem is, please help me.
As per the exceptions you received. Looks like there are issues with connecting to the SMTP server. Can you please check the configurations and check there are any restrictions to use your email.
ex: in Gmail, you have to enable 'untrusted applications' to access Gmail.
I've found the reason of this problem.
By reading the source code (EmailSink.java), I know the information of SMTP Server should be configured in APIM_ALERT_EMAIL_NOTIFICATION.siddhi, otherwise the analytic server is going to use smtp.gmail.com by default.
I'm writing some power query against the Graph API and when I try to pull OData from the applications resource I get the error:
DataSource.Error: OData: The property 'resourceSpecificApplicationPermissions' does not exist on type 'microsoft.graph.apiApplication'. Make sure to only use property names that are defined by the type.
Details:
DataSourceKind=OData
DataSourcePath=https://graph.microsoft.com/beta/applications
Source = OData.Feed(AppsURL,[#"Content-Type"="application/json", Authorization = AccessTokenHeader])
If I do the same but as a REST API request I get the JSON but then I need to take care of paging and transformation.
Source = Json.Document(Web.Contents(AppsURL,
[
Headers = [#"Content-Type"="application/json",
Authorization = AccessTokenHeader
]
]))
If I do the same against https://graph.microsoft.com/beta/servicePrincipals the OData.Feed method works like a charm.
Any possible work around or do I need to wait for the API to be fixed before consuming that resource?
After doing some tracing I found the schema is verified at: https://graph.microsoft.com/beta/$metadata and it is missing one definition.
To original response:
<ComplexType Name="apiApplication">
<Property Name="acceptMappedClaims" Type="Edm.Boolean"/>
<Property Name="knownClientApplications" Type="Collection(Edm.Guid)"/>
<Property Name="preAuthorizedApplications" Type="Collection(microsoft.graph.preAuthorizedApplication)"/>
<Property Name="requestedAccessTokenVersion" Type="Edm.Int32"/>
<Property Name="oauth2PermissionScopes" Type="Collection(microsoft.graph.permissionScope)" Nullable="false" />
</ComplexType>
Is missing:
<Property Name="resourceSpecificApplicationPermissions" Type="Collection(microsoft.graph.resourceSpecificPermission)" Nullable="false"/>
As a workaround I added a rule to Fidller:
if (oSession.HostnameIs("graph.microsoft.com") && oSession.oResponse.headers.ExistsAndContains("Content-Type","application/xml;charset=utf-8") && oSession.PathAndQuery == '/beta/$metadata' ){
oSession.utilDecodeResponse();
oSession.utilReplaceInResponse('<Property Name="oauth2PermissionScopes" Type="Collection(microsoft.graph.permissionScope)" Nullable="false" />','<Property Name="oauth2PermissionScopes" Type="Collection(microsoft.graph.permissionScope)" Nullable="false" /><Property Name="resourceSpecificApplicationPermissions" Type="Collection(microsoft.graph.resourceSpecificPermission)" Nullable="false"/>');
}
Does wso2 api manager v1.10.0 permit transforming the HTTP method of the request to the backend through custom in sequence?
I created an api with http GET resource through publisher web console. But since the endpoint support POST method only, i tried changing the HTTP Method by creating custom in sequence with property mediator :
<property name="HTTP_METHOD" value="POST" scope="axis2"/>
but the response showed a fault message :
{
"fault": {
"code": 403,
"type": "Status report",
"message": "Fault Call",
"description": "No matching resource found in the API for the given request"
}
}
The log files only showed these lines :
==> /opt/wso2am-gateway/repository/logs/wso2carbon.log <==
[2016-04-08 10:30:16,868] INFO - STATUS = Executing default 'fault' sequence, ERROR_CODE = 403, ERROR_MESSAGE = No matching resource found in the API for the given request {org.apache.synapse.mediators.builtin.LogMediator}
If i remove the property mediator, the request pass through and reach the backend.
Does anyone know how to solve this problem?
You can use the following custom inFlow mediation sequence to convert the HTTP_METHOD into POST from GET.
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="CustomIn" xmlns="http://ws.apache.org/ns/synapse">
<property action="remove" name="HTTP_METHOD" scope="axis2"/>
<property name="HTTP_METHOD" scope="axis2" type="STRING" value="POST"/>
</sequence>
Here, the request is the GET request from the client-side.
But, the above solution will be possible only when you are defining the GET and the POST resources similarly on your API (Although you don't use one of the both).
Otherwise, you will get the following error messages while you are invoking the API.
No matching resource found for given API Request
Method not allowed for given API resource
No matching resource found in the API for the given request
You need to also define POST resource on your API (although you don't use it)
I have the WSDL file for the SOAP webservice that i need to invoke over http. Using cxf wsdl2java plugin i have created the stub methods.
I have created the webservice client using jaxws. The webservice has basic authentication enabled. I am trying to configure http conduit
my application.properties
--------------------------
webservices.http.auth.username=username
webservices.http.auth.password=password
fold.webservices.http.auth.authtype=Basic
webservices.http.conduit.property.name=https://fixed_deposits-test.co.in/fold-webservices/services.*
fold.updateservice.soap.address=https://fixed_deposits-test.co.in/fold-webservices/services/UpdateService
----------------------------
My Spring Context...
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"
xmlns:sec="http://cxf.apache.org/configuration/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd
http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<bean id="properties" class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
<property name="locations">
<util:list>
<value>file:${config.dir}/application.properties</value>
</util:list>
</property>
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
</bean>
<jaxws:client id="updateServiceClient" serviceClass="com.fold.facade.v1.UpdateService" address="${fold.updateservice.soap.address}" >
<jaxws:inInterceptors>
<bean id="loggingInInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor" >
<property name="prettyLogging" value="true" />
</bean>
</jaxws:inInterceptors>
<jaxws:outInterceptors>
<bean id="loggingOutInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor" >
<property name="prettyLogging" value="true" />
</bean>
</jaxws:outInterceptors>
</jaxws:client>
<http-conf:conduit name="***?????????***">
<http-conf:authorization>
<sec:UserName>${fold.webservices.http.auth.username}</sec:UserName>
<sec:Password>${fold.webservices.http.auth.password}</sec:Password>
<sec:AuthorizationType>${fold.webservices.http.auth.authtype}</sec:AuthorizationType>
</http-conf:authorization>
</http-conf:conduit>
I have done a lot of searching online so as to what should be the valid value for name attribute..
accouring to CXF documentation it should be...
{WSDL_endpoint_target_namespace}PortName.http-conduit
my WSDL File has..
...
targetNamespace="http://facade.fold.com/" and
...
<wsdl:port binding="tns:UpdateServiceImplServiceSoapBinding"
name="UpdateServiceImplPort">
<soap:address
location="https://fixed_deposits-test.co.in/fold-webservices/services/UpdateService" />
</wsdl:port>
so i tried with these..
<http-conf:conduit name="{http://facade.fold.com/}UpdateServiceImplPort.http_conduit">
or
<http-conf:conduit name="*UpdateServiceImplPort.http_conduit">
or
<http-conf:conduit name="{http://facade.fold.com/}*.http_conduit">
But none of them work as i get 401 unauthorized exception..
org.apache.cxf.transport.http.HTTPException: HTTP response '401: Unauthorized' when communicating with https://fixed_deposits-test.co.in/fold-webservices/services/UpdateService
THERE ARE COUPLE OF WAYS I GOT IT TO WORK
a) <http-conf:conduit name="*.http_conduit">
but i really don't want to do it this way...
b) <http-conf:conduit name="https://fixed_deposits-test.co.in/fold-webservices/services/UpdateService">
this is hardcoding the SOAP service URL... which i don't want as i am looking for externalizing URL as my SOAP URL's are different for different environment..(dev /test /prod etc)
Below is my best shot at externalization, but it failed with 401 Unauthorized Exception...
properties were replaced in all other instances in my spring context, but not for http-conf:conduit name attribute :(
<http-conf:conduit name="${webservices.http.conduit.property.name}">
As a workaround i am currently using the regex approach which works..
<http-conf:conduit name="*.*/fold-webservices/services/UpdateService">
But i really want to figure out if it possible to externalize it and read from properties file. And i want to do it the Spring
configuration way. Please help me !!!
We had the same issue with JBoss Fuse 6.1 (Camel CXF 2.12.0).
You can see what the http-conf:conduit name is set to by enabling DEBUG log level and looking at your log, there should be a log line such as:
DEBUG 10:40:41,437 [Camel (cnpms-as-mnp-ctx) thread #0 - JmsConsumer[cnpms-queue]] org.apache.cxf.transport.http.HTTPConduit.setTlsClientParameters(HTTPConduit.java:901) - Conduit '{http://acme.com/manageporting/v1}ManageportingPortPort.http-conduit' has been (re)configured for plain http.
So in this case you would set the name as:
<http-conf:conduit name="{http://acme.com/manageporting/v1}ManageportingPortPort.http-conduit"
But the Web Service (WS) Interface Class is defined as:
#WebService(targetNamespace = "http://acme.com/manageporting/v1", name = "ManageportingPort")
#SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface ManageportingPort {
Generated from WSDL:
<wsdl:portType name="ManageportingPort">
Note that by following the CXF documentation you would expect the port name component to be "ManageportingPort" NOT "ManageportingPortPort" i.e. with "Port" appended to it.
However looking at how the portQName is resolved in org.apache.cxf.jaxws.support.JaxWsImplementorInfo.getEndpointName(), if the port name is not set in the WS Interface Class, and the name is not null or blank, it sets the port name to portName = name + "Port" otherwise it sets it to portName = implementorClass.getSimpleName() + "Port".
I had the same problem...
In my case the following 2 changes helped:
1) add "Port" postfix to the port name, despite it is not defined in the wsdl this was
e.g wsdl:
<wsdl:port name="XXXSoap">
will be "XXXSoapPort" in the conduit definition
2) remove the "\" at the end of the target namespace name
==> therefore try
<http-conf:conduit name="{http://facade.fold.com}UpdateServiceImplPort.http_conduit">
or
<http-conf:conduit name="{http://facade.fold.com}UpdateServiceImplPortPort.http_conduit">
I came across the same challenge and found no existing solution. Spring doesn't seem to resolve placeholders in bean names (make lots of sense). However, this is a valid case unless cxf allows conduit matching using another attribute.
There are a few ways to solve this problem:
Define conduit beans programmatically (lose the neat of xml declaration)
Find a way to resolve the bean names which contains placeholders
I prefer option 1 and this is the implementation which I'm happy with. Please note that PropertyPlaceholderResolver is our own utility which uses the same defined resolver bean.
public class NameWithPlaceholderBeanFactoryPostProcessor implements BeanFactoryPostProcessor
{
#Override
public void postProcessBeanFactory(final ConfigurableListableBeanFactory beanFactory) throws BeansException
{
if (!(beanFactory instanceof DefaultListableBeanFactory))
return;
DefaultListableBeanFactory bf = (DefaultListableBeanFactory) beanFactory;
String[] names = bf.getBeanDefinitionNames();
for (String name : names)
{
if (name.indexOf('$') < 0)
continue;
BeanDefinition bd = bf.getBeanDefinition(name);
bf.removeBeanDefinition(name);
bf.registerBeanDefinition(PropertyPlaceholderResolver.resolvePlaceHolders(name), bd);
}
}
}
The final step is to define this as a spring bean.