How to create WADL document for spring based JAX WS service? - web-services

I have created a Spring Restful API based Web service.
Please suggest how can I create a WADL document for this service.
I access the Web Service through eclipse by :
http://localhost:8080/SampleSpringService/mcxService/getMCX
Service Name : mcxService,
Function name : getMCX
Java File code which is being called as Web Service:
#RestController
#RequestMapping(value = "/mcxService")
#PropertySource(value = "classpath:FileProperty.properties")
public class MCXController {
#Autowired
private MessageSource messageSource;
#Value("${jsonFile.path}")
private String jsonFilePath;
#RequestMapping(value = "/getMCX", method = RequestMethod.GET, produces = "application/json")
public String getMCXData(HttpServletRequest request) throws JsonParseException, JsonMappingException, IOException {
System.out.println(messageSource.getMessage("jsonFile.path", null, null));
// read Form data to String
String data = request.getParameter("firstname");
System.out.println("data = " + data);
if(data == null){return "Data is NULL !!!!" ;}
saveUserList(data);
return "Data (" + data + ") is saved to File : D:/test.txt" ;
}

Related

wso2 identity server custom handler reading from properties file

public class UserRegistrationCustomEventHandler extends AbstractEventHandler {
JSONObject jsonObject = null;
private static final Log log = LogFactory.getLog(UserRegistrationCustomEventHandler.class);
#Override
public String getName() {
return "customClaimUpdate";
}
if (IdentityEventConstants.Event.POST_SET_USER_CLAIMS.equals(event.getEventName())) {
String tenantDomain = (String) event.getEventProperties()
.get(IdentityEventConstants.EventProperty.TENANT_DOMAIN);
String userName = (String) event.getEventProperties().get(IdentityEventConstants.EventProperty.USER_NAME);
Map<String, Object> eventProperties = event.getEventProperties();
String eventName = event.getEventName();
UserStoreManager userStoreManager = (UserStoreManager) eventProperties.get(IdentityEventConstants.EventProperty.USER_STORE_MANAGER);
// String userStoreDomain = UserCoreUtil.getDomainName(userStoreManager.getRealmConfiguration());
#SuppressWarnings("unchecked")
Map<String, String> claimValues = (Map<String, String>) eventProperties.get(IdentityEventConstants.EventProperty
.USER_CLAIMS);
String emailId = claimValues.get("http://wso2.org/claims/emailaddress");
userName = "USERS/"+userName;
JSONObject json = new JSONObject();
json.put("userName",userName );
json.put("emailId",emailId );
log.info("JSON:::::::"+json);
// Sample API
//String apiValue = "http://192.168.1.X:8080/SomeService/user/updateUserEmail?email=sujith#gmail.com&userName=USERS/sujith";
try {
URL url = new URL(cityAppUrl) ;
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setConnectTimeout(5000);
con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
con.setDoOutput(true);
con.setDoInput(true);
con.setRequestMethod("POST");
log.info("CONN:::::::::::::"+con);
OutputStream os = con.getOutputStream();
os.write(cityAppUrl.toString().getBytes("UTF-8"));
os.close();
InputStream in = new BufferedInputStream(con.getInputStream());
String result = org.apache.commons.io.IOUtils.toString(in, "UTF-8");
jsonObject = new JSONObject(result);
log.info("JSON OBJECT:::::::::"+jsonObject);
}
catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void init(InitConfig configuration) throws IdentityRuntimeException {
super.init(configuration);
}
#Override
public int getPriority(MessageContext messageContext) {
return 250;
}
}
I'm using wso2 identity server 5.10.0 and have to push the updated claim value to an API so I'm using a custom handler and have subscribed to POST_SET_USER_CLAIMS, i have to read the API value from deployment.toml file in jave code of the custom handler. So can any one please help here to read the value from deployment file
I can fetch the updated claim value in logs but im not able to get the API value. So can anyone help me here to read the value from deployment file.
Since the API path is required inside your custom event handler, let's define the API path value as one of the properties of the event handler.
Add the deployment.toml config as follows.
[[event_handler]]
name= "UserRegistrationCustomEventHandler"
subscriptions =["POST_SET_USER_CLAIMS"]
properties.apiPath = "http://192.168.1.X:8080/SomeService/user/updateUserEmail"
Once you restart the server identity-event.properties file populates the given configs.
In your custom event handler java code needs to read the config from identity-event.properties file. The file reading is done at the server startup and every config is loaded to the memory.
By adding this to your java code, you can load to configured value in the property.
configs.getModuleProperties().getProperty("UserRegistrationCustomEventHandler.apiPath")
NOTE: property name needs to be defined as <event_handler_name>.<property_name>
Here is a reference to such event hanlder's property loading code snippet https://github.com/wso2-extensions/identity-governance/blob/68e3f2d5e246b6a75f48e314ee1019230c662b55/components/org.wso2.carbon.identity.password.policy/src/main/java/org/wso2/carbon/identity/password/policy/handler/PasswordPolicyValidationHandler.java#L128-L133

Integrating ASP.NET Web Api and Android Volley

I'm developing an ASP.NET Web Api project with Entity Framework and other project with Android and the Volley lib.
The idea is the project in ASP.NET to be the server and the Android app the client.
Both projects already work. The ASP.NET project is already connected to SQL Server and returns values in json format from one database, and the client also parses json from an online server that I used for testing when I was following one tutorial.
ASP.NET Web Api Controller:
public class StoreController : ApiController
{
// GET: api/Store
public IEnumerable<bo> Get()
{
using (EGLA_PHCEntities services = new EGLA_PHCEntities())
{
return services.bo.Where(e => e.nmdos == "Ficha Servico 30").Where(e => e.fechada == false).ToList();
}
}
...
}
Android:
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jsonArray = response.getJSONArray(null);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject employee = jsonArray.getJSONObject(i);
String firstName = employee.getString("fieldA");
String mail = employee.getString("fieldB");
mTextViewResult.append(firstName + ", " + mail + "\n\n");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
The problem is that my project in ASP.NET does not return a name for the array of objects, and Android is waiting for a name.
The solution can be applied in one side or another. It can go through the ASP.NET project to return a name, or the project in Android to parse the json with an empty array name.
Modified because the list of fields is very extense:
[
{
"fieldA":"Something",
"fieldB":"Store 30",
},
{
"fieldA":"Something 2",
"fieldB":"Store 30 2",
}
]
The error that is returned in the Android app is "org.json.JSONException: No value for null". If I change
JSONArray jsonArray = response.getJSONArray(null);
to:
JSONArray jsonArray = response.getJSONArray("services");
The error returned is: "org.json.JSONException: No value for services"

Apache CXF + SpringBoot: Can I publish multiple endpoints for one SOAP web-service?

I have implemented a SOAP Webservice using Apache CXF + SpringBoot.
In my Endpoint Configuration class, I have
#Bean
public Endpoint endpoint()
{
EndpointImpl endpoint = new EndpointImpl(cxfBus, new ServiceImpl());
endpoint.publish("/myservice");
return endpoint;
}
This creates a web-service endpoint as https://host:port/myService
To this service I need to expose multiple endpoints - something like -
https://host:port/tenant1/myService
https://host:port/tenant2/myService
https://host:port/tenant3/myService
This is kind of REST endpoint -- i.e, I am trying to pass the tenantId variable in the service endpoint.
Is this possible in Apache CXF + Springboot ?
I tried this -
#Bean
public Endpoint endpoint()
{
EndpointImpl endpoint = new EndpointImpl(cxfBus, new ServiceImpl());
String[] pathArray = {"tenant1", "tenant2", "tenant3"};
for (int i = 0; i < pathArray.length; i++)
{
endpoint.publish("/" + pathArray[i] + "/myservice");
}
return endpoint;
}
But it does not work.
I would really appreciate any inputs/suggestions. Thanks!
No you can not have same endpoint mapped to multiple urls, One Endpoint is create for a wsdl file which that would be generated to single class. From the urls I assume you want to host same service on multiple url based on tenant. In that case you have to create endpoints for each tenant.
#Bean
public Endpoint endpoint1()
{
EndpointImpl endpoint = new EndpointImpl(cxfBus, new ServiceImpl());
endpoint.publish("/tenant1/" + pathArray[i] + "/myservice");
return endpoint;
}
#Bean
public Endpoint endpoint2()
{
EndpointImpl endpoint = new EndpointImpl(cxfBus, new ServiceImpl());
endpoint.publish("/tenant1/" + pathArray[i] + "/myservice");
return endpoint;
}
OR
#Configuration
public class CxfConfiguration implements BeanFactoryPostProcessor {
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException {
Arrays.stream(new String[] { "tenant1", "tenant2" }).forEach(str -> {
Bus bus = factory.getBean(Bus.class);
JaxWsServerFactoryBean bean = new JaxWsServerFactoryBean();
bean.setAddress("/" + str + "/myService");
bean.setBus(bus);
bean.setServiceClass(HelloWorld.class);
factory.registerSingleton(str, bean.create());
});
}
}
BTW: May be better way use REST?

How to access protected OData resources from c# application using Microsofts OData v4 Client T4 Code Generator

I have a website which exposes an ODatas $metadata but to do anything further requires the request to be authenticated (using a cookie).
I want to access this from a console app, not a browser.
I am using Microsofts Odata V4 client code generator.
1) Create a wrapper around the provided Container created by the OData client code generator.
2) Log in and get the cookie you need for authentication
3) Add a hook to the request builder, so you can apply cookies at request time. For my app, I specifically needed the cookie with the name .AspNet.ApplicationCookie
Here is a full working example. You can instantiate this container with the user and password needed as defined at the bottom. This MUST match whatever the controller at the Login API is expecting.
using Nito.AsyncEx;
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
namespace MyAppOdataOdataService.Default
{
public class MyAppOdataContainer : Container
{
public Cookie[] _MyAppOdataAuthcookie;
public string cookieAuthName = ".AspNet.ApplicationCookie";
private string baseurl = "https://TheAppwWebsite.co.jp/";
public MyAppOdataContainer(MyAppOdataLoginInfo logininfo ) :
base(new Uri("https://TheAppwWebsite.co.jp/odata/"))
{
// init authorization
_MyAppOdataAuthcookie = AsyncContext.Run(() => AuthenticateUser(logininfo));
if (_MyAppOdataAuthcookie == null) throw new UnauthorizedAccessException();
this.BuildingRequest += AddCookie;
}
private void AddCookie(object sender, Microsoft.OData.Client.BuildingRequestEventArgs e)
{
e.Headers.Add("Cookie", cookieAuthName+"=" + _MyAppOdataAuthcookie.First(c=>c.Name == cookieAuthName).Value);
}
private async Task<Cookie[]> AuthenticateUser(MyAppOdataLoginInfo logininfo)
{
CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;
HttpClient client = new HttpClient(handler);
client.BaseAddress = new Uri(baseurl);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Uri uri = new Uri(baseurl + "/Login/Login");
HttpResponseMessage response = await client.PostAsJsonAsync(uri, logininfo);
response.EnsureSuccessStatusCode();
// Return the URI of the created resource.
return cookies.GetCookies(uri).Cast<Cookie>().ToArray();
}
}
public class MyAppOdataLoginInfo
{
public string Username { get; set; }
public string Password { get; set; }
}
}
Thanks:
How to apply the cookie:
Creating the client code:
CookieContainer explaination:
Post operation idea here - for authorizing - having to use PostAsJsonAsync

Using Web Service to authenticate on LDAP

Since it' apparently not possible to authenticate with LDAP on my BlackBerry App, I'm trying to use a kind of workaround. Instead of authenticate directly on the LDAP Server, I want to use a Web Service in between. So it looks like this
App --calls--> Web Service --calls--> LDAP Server
So the Web Service should take the username and password given from the Application and send it to the LDAP Server. If its possible to sign in, the Web Service gets a TRUE as response and forward it to the App.
That's how it should work. But at the moment, when I call the Web Service from the App, I get following error:
SoapFault - faultcode: 'S:Server' faultstring:
'java.lang.NullPointerException' faultactor: 'null' detail:
org.kxml2.kdom.Node#21e05a11
Seems like a Server problem but I don't know where :(
Well, that's the Web Service I'm using:
import javax.ejb.Stateless;
import javax.jws.WebService;
import com.novell.ldap.LDAPConnection;
import com.novell.ldap.LDAPException;
#Stateless
#WebService()
public class ldapServiceBean implements ldapService {
#Override
public String error() {
// TODO Auto-generated method stub
return null;
}
#Override
public boolean ldapLogin(String username, String password) {
int ldapPort = LDAPConnection.DEFAULT_PORT;
int ldapVersion = LDAPConnection.LDAP_V3;
String ldapHost = "dc1.somehost ";
String loginDN =
"CN="+username+",OU=employee,OU=user,DC=somehost";
byte[] passwordBytes = password.getBytes();
LDAPConnection lc = new LDAPConnection();
try {
// connect to the server
lc.connect( ldapHost, ldapPort );
// authenticate to the server
lc.bind( ldapVersion, loginDN, passwordBytes );
System.out.println("Bind successful");
return true;
}
catch( LDAPException e ) {
if ( e.getResultCode() == LDAPException.NO_SUCH_OBJECT ) {
System.err.println( "Error: No such entry" );
} else if ( e.getResultCode() ==
LDAPException.NO_SUCH_ATTRIBUTE ) {
System.err.println( "Error: No such attribute" );
} else {
System.err.println( "Error: " + e.toString() );
}
}
return false;
}
And that's the method calling the Web Service
private static final String SOAP_ACTION = "";
private static final String METHOD_NAME = "ldapLogin";
private static final String NAMESPACE = "http://ldapproxy.somehost/";
private static final String URL = "http://myIP:8080/LDAPProxy/ldapServiceBeanService";
...
public boolean login(String username, String password) {
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
//SoapObject
request.addProperty("username", username);
request.addProperty("password", password);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
//envelope.dotNet = true;
//envelope.bodyOut = request;
envelope.setOutputSoapObject(request);
HttpTransport httpTransport = new HttpTransport(URL);
try
{
httpTransport.call(SOAP_ACTION, envelope);
System.out.println("request: " + httpTransport.requestDump);
resultsRequestSOAP = (SoapObject) envelope.getResponse();
return true;
}catch(SoapFault sF){
String error = sF.toString();
Dialog.alert(error);
}
catch (Exception aE)
{
Dialog.alert("Connection failed");
aE.printStackTrace ();
}
return false;
}
What I found out so far:
It seems that the webservice don't receives the username and password property. As I print them I get:
`CN=null, OU=employee, OU=...`
Like I've read at this post Web service recieves null parameters from application using ksoap method it seems ksoap have a problem with colons. I changed my NAMESPACE but without any success. Maybe I need to change my URL too. But how would I do this while I still need to use localhost ?
As always when doing LDAP bind testing this way, recall that the standard requires that a bind of a username, no password, is a successful Anonymous bind, so therefore you MUST validate for this case (empty password) on login attempts.