Swagger grails Integration - rest

I am new to swagger and I want to integrate swagger to Restful API project using grails framework. Please help if anybody have any idea what i am doing wrong?
my grails specification as below:
| Grails Version: 3.0.7
| Groovy Version: 2.4.4
| JVM Version: 1.8.0_71
Did some settings for swagger as below:
in build.gradle:
dependencies {
...
compile "io.swagger:swagger-core:1.5.3"
compile "io.swagger:swagger-jaxrs:1.5.3"
...
}
in resources.groovy
import io.swagger.jaxrs.config.BeanConfig
beans = {
swaggerConfig(BeanConfig) {
def serverUrl = "http://localhost:8080/"
def hostName = "localhost:8080"
resourcePackage = "grails.rest.example"
host = hostName
basePath = "/api"
version = 'v0' // Default "1".
title = 'Core Registration API, Version V0'
description = 'API for Accessing secured resources'
contact = 'testtest#mailinator.com'
license = ''
licenseUrl = ''
}
corsFilter(CorsFilter)
}
Added a Controller ApiDocController.groovy:
package grails.rest.example.apidoc
import grails.web.mapping.LinkGenerator
class ApiDocController {
LinkGenerator grailsLinkGenerator
def apiDocService
def index = {
String basePath = grailsLinkGenerator.serverBaseURL
render(view: 'index', model: [apiDocsPath: "${basePath}/api/swagger-json"])
//render(view: 'index', model: [apiDocsPath: "localhost:8080/api/swagger-json"])
//render(view: 'index', model: [apiDocsPath: "localhost:8080/dist/index.html"])
}
def swaggerJson = {
render apiDocService.generateJSON()
}
}
Added a URLMapping for controller:
"/api/info"(controller: 'ApiDoc')
"/"(controller: 'Index')
"500"(controller: 'InternalServerError')
"404"(controller: 'NotFound')
Added a service ApiDocService.groovy:
//package com.care.apidoc
package grails.rest.example.apidoc
import io.swagger.jaxrs.config.BeanConfig
import grails.transaction.Transactional
import io.swagger.util.Json
#Transactional
class ApiDocService {
def swaggerConfig
/*
* generates SWAGGer JSON
*/
def generateJSON() {
String[] schemes = ["http"] as String[]
swaggerConfig.setSchemes(schemes)
swaggerConfig.setScan(true)
def swagger = swaggerConfig.getSwagger()
Json.mapper().writeValueAsString(swagger);
}
}
added Swagger-ui in src/main/webapp/dist folder
with a working customised API URL "http://localhost:8080/api/orders" in index.html
added CorsFilter setting in src/main/groovy/CorsFilter.groovy
import org.springframework.web.filter.OncePerRequestFilter
import javax.annotation.Priority
import javax.servlet.FilterChain
import javax.servlet.ServletException
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
#Priority(Integer.MIN_VALUE)
public class CorsFilter extends OncePerRequestFilter {
public CorsFilter() { }
#Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse resp, FilterChain chain)
throws ServletException, IOException {
String origin = req.getHeader("Origin");
boolean options = "OPTIONS".equals(req.getMethod());
resp.addHeader("Access-Control-Allow-Headers", "origin, authorization, accept, content-type, x-requested-with");
resp.addHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS");
resp.addHeader("Access-Control-Max-Age", "3600");
resp.addHeader("Access-Control-Allow-Origin", origin == null ? "*" : origin);
resp.addHeader("Access-Control-Allow-Credentials", "true");
if (!options) chain.doFilter(req, resp);
}
}
On starting the server.
API for orders is working correctly, however, when I try to load the API in Swagger UI index file. it shows.
No operations defined in spec!
as attached in a pics.

Have you looked at springfox?
Here is a sample Grails Application hosted in Heroku that demonstrates the capabilities of springfox integrating with it to produce the service description in the Open API specification 2.0 (fka swagger). The source code for the demo is available here.
You can see this demo running live here demonstrating the Open API specification generated by the grails application and rendered using swagger-ui.
The library that makes this possible is springfox-grails-integration library. It is about to be released and probably needs a little bit of work to make it a grails plugin. There is some preliminary documentation of how to configure this the library repository.
NOTE: This only works with grails 3.x
Also it was a notable library showcased in the SHOW US YOUR GRAILS contest. Feedback to improve this library is much appreciated.

Related

Calling External WCF Service (using generated client) from CRM sandboxed plugin OnPremise is failing

How to call HTTPS WCF web service in Plugin, plugin assembly is registered in sandbox mode. I am getting System.Security.SecurityException exception, Can somebody please provide the way to all https web service. My code is below :
BasicHttpBinding myBinding = new BasicHttpBinding();
myBinding.MaxReceivedMessageSize = Int32.MaxValue;
myBinding.Name = “basicHttpBinding”;
if (EndPoint.ToLower().Contains(“https://”))
{
//Throwing exception here – System.Security.SecurityException exception,
ServicePointManager.ServerCertificateValidationCallback += (sendr, cert, chain, sslPolicyErrors) => true;
ServicePointManager.SecurityProtocol = (SecurityProtocolType)768 | (SecurityProtocolType)3072 | (SecurityProtocolType)192;
myBinding.Security.Mode = BasicHttpSecurityMode.Transport;
}
else
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
myBinding.Security.Mode = BasicHttpSecurityMode.None;
}
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
myBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
myBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
EndpointAddress endPointAddress = new EndpointAddress(EndPoint);
WebIALClient myClient = new WebIALClient(myBinding, endPointAddress)
Since you are in on-premise version, you can register the plugin assembly in non-sandbox mode. ie Isolation mode = none to overcome such errors.
In case you wanted to use sandbox mode, try using WebClient class for invoking WCF service call. Read more
using (WebClient client = new WebClient())
{
byte[] responseBytes = client.DownloadData(webAddress);
string response = Encoding.UTF8.GetString(responseBytes);
tracingService.Trace(response);
// For demonstration purposes, throw an exception so that the response
// is shown in the trace dialog of the Microsoft Dynamics CRM user interface.
throw new InvalidPluginExecutionException("WebClientPlugin completed successfully.");
}
Can you try and also include: using System.Web.Http.Cors;
[EnableCors(origins: "*", headers: "*", methods: "*")]
[Route("api/ConvertUpload/{env}/{id}")]
public string Get(string env, string id)
{
return "hi";
}
You may have to use WebClient as #Arun has mentioned.

Consume Rest-Webservice in java 1.6 version

Need to consume post method in Rest webservice using java 1.6 version,I have used Jersey jar to connect web services but getting connect rest error when iam running it in JAVA 1.6 Version , But its working fine using java 1.7 and 1.8.
Can some one help me to achive this using JAVA 1.6 version because i need to deploy in server which runs on java 1.6.
Iam Connecting to URL :https:// (secured url)
Code Below:
import java.util.ArrayList;
import javax.ws.rs.client.Client;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import com.sun.jersey.api.client.WebResource;
import com.thortech.util.logging.Logger;
public class MFARestClientService {
public static void main(String[] args) {
MFARestClientService mfa1=new MFARestClientService();
ArrayList userList = new ArrayList();
userList.add("test1");
userList.add("Test2");
mfa1.postMFAUser(userList);
}
Logger logger = Logger.getLogger("RestClientService");
//Method To post data to AsureCloud
public void postUser(ArrayList<String> userList)
{
JSONObject obj = new JSONObject();
String url = "https://***.azurew.net/********************************/*****";
this.logger.info("Reached RestClientService");
this.logger.info("Get UserDetails from OIM usr table and creating json value");
obj.put("group", "ABC-99");
obj.put("userid", userList);
String jsondata=obj.toJSONString();
System.out.println("JSONDATA :"+jsondata);
{
try {
this.logger.info(jsondata);
Client restClient = Client.create();
WebResource webResource = restClient.resource(url);
ClientResponse response = webResource.accept("application/json").post(ClientResponse.class,jsondata);
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : " + response.getStatus());
}
String output = response.getEntity(String.class);
System.out.println("Output from Server .... \n");
this.logger.info("Output from Server .... \n");
this.logger.info(output);
System.out.println(output);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Error:
Connection reset
But this code work fine in java 1.7 and 1.8
Need help to consume this using java 1.6 version
Thanks
Midhun M S
I see that your URL is using https protocol. If it works in java 1.7 and doesn't work in java 1.6 means most probably is a handshake issue between the client and server. java 1.6 only supports TLS 1.0 where as java 1.7 or 1.8 supports TLS 1.0, TLS 1.1, TLS 1.2. You might have to used third party API's such as Bouncy Castle to for TLS 1.2 support. I would strongly recommend you to upgrade to higher version of java. Good luck

WebSocket- "Error during WebSocket handshake: Unexpected response code: 404" when added external jar to the project

I am building simple chatting application using WebSocket using Eclipse and apache 7.x .However I am not able to compile my code cause it shows import javax.websocket cannot be resolved. After Googling a lot i found Link that shows external jar in application. I added a jar in my library section. It removed my current error but gave another. Now it showing WebSocket connection to 'ws://localhost:8080/WebSocket/socket' failed: Error during WebSocket handshake: Unexpected response code: 404
I'v tried a lot like adding servlet-api.jar to build path from apache lib. And also find some information like It provides also the javax.websocket-api-1.0.jar library so this is not needed in you application. You might need it at compile time but the server will provide it at runtime
Now I got stuck like in recursion. when I remove my jar got first error and when I add external jar then got second error. please help me in this issue cause we are developing mini project for real time collaborative editor and we are suppose to use websocket in it.
Now here is my code for websocket(not using maven):
WebSocket.java
package com.psl.service;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
#ServerEndpoint("/socket")
public class WebSocket {
Set<Session> sessionSet = Collections.synchronizedSet(new HashSet<>());
#OnOpen
public void onOpen(Session webSession) {
System.out.println("Opened");
sessionSet.add(webSession);
}
#OnMessage
public void onMessage(String message, Session webSession) throws IOException {
System.out.println("Got message "+message);
String username = (String)webSession.getUserProperties().get("username");
if(username==null) {
webSession.getUserProperties().put("username", message);
webSession.getBasicRemote().sendText(buildJSON(username, message));
}
else {
for(Session s : sessionSet) {
s.getBasicRemote().sendText(buildJSON(username, message));
}
}
}
private String buildJSON(String string, String string2) {
String jsonData="";
JSONObject obj=new JSONObject();
try {
obj.put("message",string + ":" + string2);
StringWriter out = new StringWriter();
JSONWriter jwriter = new JSONWriter(out);
jwriter.key(string).value(string2);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#OnClose
public void onClose() {
System.out.println("CLosed");
sessionSet.remove(sessionSet);
}
}
chat.html
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
<script type="text/javascript">
var websocket = new WebSocket("ws://localhost:8080/WebSocketDemo/socket");
websocket.onmessage = function onMessage(message) {
var jsonData = JSON.parse(message.data);
if(jsonData.message != null) {
messageTextArea.value += jsonData.message + "\n";
}
}
function sendMessage() {
websocket.send(sendText.value);
sendText.value = "";
}
</script>
</head>
<body>
<textarea rows="30" cols="70" id="messageTextArea" ></textarea><br /><br />
<input id="sendText">
<input type="button" value="Send" onclick="sendMessage()">
</body>
</html>
I got answer for this query. This is because the added jar overrides my internal jars in apache tomcat. And I am using older tomcat that have not websocket-api.jar
So My solution for this problem is either use glashfish 4.x or else use apache tomcat 8.x that gives us required jar to run websocket. No need to add any extra websocket api jar.

When does Play load application.conf?

Is application.conf already loaded when the code in Global.scala is executed? I'm asking because I've tried to read some configuration items from Global.scala and I always get None. Is there any workaround?
In Java it's available beforeStart(Application app) already
public class Global extends GlobalSettings {
public void beforeStart(Application app) {
String secret = Play.application().configuration().getString("application.secret");
play.Logger.debug("Before start secret is: " + secret);
super.beforeStart(app);
}
}
As it's required to i.e. configuring DB connection, most probably Scala works the same way (can't check)
Here below is how to read the configuration just after it has been loaded but before the application actually starts:
import play.api.{Configuration, Mode}
import play.api.GlobalSettings
import java.io.File
import utils.apidocs.InfoHelper
object Global extends GlobalSettings {
override def onLoadConfig(
config: Configuration,
path: File, classloader:
ClassLoader,
mode: Mode.Mode): Configuration = {
InfoHelper.loadApiInfo(config)
config
}
}
And here below, just for your info, is the source of InfoHelper.loadApiInfo – it just loads API info for Swagger UI:
package utils.apidocs
import play.api.Configuration
import com.wordnik.swagger.config._
import com.wordnik.swagger.model._
object InfoHelper {
def loadApiInfo(config: Configuration) = {
config.getString("application.name").map { appName =>
config.getString("application.domain").map { appDomain =>
config.getString("application.emails.apiteam").map { contact =>
val apiInfo = ApiInfo(
title = s"$appName API",
description = s"""
Fantastic application that makes you smile. You can find our
more about $appName at $appDomain.
""",
termsOfServiceUrl = s"//$appDomain/terms",
contact = contact,
license = s"$appName Subscription and Services Agreement",
licenseUrl = s"//$appDomain/license"
)
ConfigFactory.config.info = Some(apiInfo)
}}}
}
}
I hope it helps.

Scalate ResourceNotFoundException in Scalatra

I'm trying the following based on scalatra-sbt.g8:
class FooWeb extends ScalatraServlet with ScalateSupport {
beforeAll { contentType = "text/html" }
get("/") {
templateEngine.layout("/WEB-INF/scalate/templates/hello-scalate.jade")
}
}
but I'm getting the following exception (even though the file exists) - any clues?
Could not load resource: [/WEB-INF/scalate/templates/hello-scalate.jade]; are you sure it's within [null]?
org.fusesource.scalate.util.ResourceNotFoundException: Could not load resource: [/WEB-INF/scalate/templates/hello-scalate.jade]; are you sure it's within [null]?
FWIW, the innermost exception is coming from org.mortbay.jetty.handler.ContextHandler.getResource line 1142: _baseResource==null.
Got an answer from the scalatra mailing list. The problem was that I was starting the Jetty server with:
import org.mortbay.jetty.Server
import org.mortbay.jetty.servlet.{Context,ServletHolder}
val server = new Server(8080)
val root = new Context(server, "/", Context.SESSIONS)
root.addServlet(new ServletHolder(new FooWeb()), "/*")
server.start()
I needed to insert this before start():
root.setResourceBase("src/main/webapp")