Swagger documentation for BeanParam - cxf

I'm trying to document one of my java APIs (implemented in Apache CXF) using Swagger, that receives it's parameters using a Bean Param. Something like:
#GET
#Produces({SemanticMediaType.JSON_LD, MediaType.APPLICATION_JSON_VALUE})
#ApiOperation(value = "Retrieves Themes", position = 0)
#ApiResponses(value = {#ApiResponse(code = 200,
message = "Retrieval was successful"), #ApiResponse(code = 403,
message = "Missing or invalid x-business-group-id header"), #ApiResponse(code = 500,
message = "Internal server error")})
public Response get(#QueryParam(URI_PARAM_NAME) String uri,
final #ApiParam #Valid #BeanParam ThemeParams themeParams) { ... }
I read that Swagger already implements support for BeanParams, but when I try to run it, in swagger-ui, I only see one parameter called "body" and a text field, nothing related to the contents of my BeanParam.
Can somebody provide some assistance with this?

This is a bit old, but for those who are having the same issues, here is what I found helped.
If you are using the DefaultJaxrsConfig, change it to JerseyJaxrsConfig.
If you are linking to swagger-jersey-jaxrs_..., change it to swagger-jersey2-jxsrs_...

You can refer to.
#POST
#Path("/users")
#ApiOperation(value = "vdc", position = 1, notes = "vdc")
#ApiResponses(value = {
#ApiResponse(code = 200, message = "OK",response=UserCreateResponse.class),
#ApiResponse(code = 30601, message = "'httpcode': 400 'Errormsg': Request Params Not Valid"),
#ApiResponse(code = 30602, message = "'httpcode':404 'Errormsg': Data Required Not Found"),
#ApiResponse(code = 30603, message = "'httpcode':405 'Errormsg': Method Not Allowed"),
#ApiResponse(code = 30604, message = "'httpcode':408 'Errormsg': Request Time Expires Timeout"),
#ApiResponse(code = 30605, message = "'httpcode':500 'Errormsg': Internal Server Error") })
public Response createUsersWithArrayInput(
#ApiParam(value = "ID", name = "platform_id", required = true) #QueryParam(value = "platform_id") String platformId,
#ApiParam(value="body",name="user",required=true)UserCreate userCreate) {}
UserCreate.java
#ApiModel("UserCreate")
public class UserCreate {
#ApiModelProperty(value="VDC Id",required=false)
#JsonStringSchema(optional=true,description="VDC Id")
private String vdcId;
#ApiModelProperty(value="description",required=true)
private String name;
#ApiModelProperty(value="description",required=false)
private String password;
}

Related

"Try it out" does not work in springdoc-openapi-ui?

I use springdoc-openapi-ui:1.6.9 to generate documentation, and I have this controller:
#Operation(summary = "Get a file meta by its ID")
#ApiResponses({
#ApiResponse(responseCode = "200", content = {
#Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = #Schema(implementation = FileMetaResponse.class))
}),
#ApiResponse(responseCode = "404", description = "Not found", content = {
#Content(mediaType = MediaType.TEXT_PLAIN_VALUE,
schema = #Schema(implementation = String.class))
})
})
#RequestMapping(value = "/files/meta", method = RequestMethod.GET)
public ResponseEntity<Object> getFileMate(#RequestParam final #NotEmpty String id) {
OssFile ossFIle = fileService.findFileById(UUID.fromString(id));
if (ossFIle == null) {
return new ResponseEntity<>("File not found", HttpStatus.NOT_FOUND);
}
FileMetaResponse body = new FileMetaResponse();
BeanUtils.copyProperties(ossFIle, body);
return new ResponseEntity<>(body, HttpStatus.OK);
}
But, I always got code 200 and no response body When I execute a request to this API with any id. By debugging code, I found that this request didn't arrive to backend. ui shows:
enter image description here
However, it works normally when I delete response mediatype definition, as follows:
/**
* Get a file meta by given a file ID.
*
* #param id file uuid
* #return a found OssFile meta if successful
*/
#Operation(summary = "Get a file meta by its ID")
#ApiResponses({
#ApiResponse(responseCode = "200", content = {
#Content(
schema = #Schema(implementation = FileMetaResponse.class))
}),
#ApiResponse(responseCode = "404", description = "Not found", content = {
#Content(
schema = #Schema(implementation = String.class))
})
})
#RequestMapping(value = "/files/meta", method = RequestMethod.GET)
public ResponseEntity<Object> getFileMate(#RequestParam final #NotEmpty String id) {
OssFile ossFIle = fileService.findFileById(UUID.fromString(id));
if (ossFIle == null) {
return new ResponseEntity<>("File not found", HttpStatus.NOT_FOUND);
}
FileMetaResponse body = new FileMetaResponse();
BeanUtils.copyProperties(ossFIle, body);
return new ResponseEntity<>(body, HttpStatus.OK);
}
By comparing the two requests, the Accept field of request header is different: the accept is application/json when media type is defined, otherwise the accept is */*.
If I want to define response media type and execute request on swagger-ui web, How should I do?

Exception in Service NOW attachment API invocation-- Premature end of chunk coded message body: closing chunk expected

I am using HttpClient to send POST multipart request, using the below code
String apiUrl = API_URL_DEV;
String name = API_USER_DEV;
String password = API_PASSWORD_DEV;
String authString = name + ":" + password;
String encoding = Base64.getEncoder().encodeToString(authString.getBytes());
apiUrl = "https://<servicenow host>/api/now/attachment/upload";
try {
Header header = new BasicHeader(HttpHeaders.CONTENT_TYPE, "multipart/form-data");
Header header2 = new BasicHeader(HttpHeaders.ACCEPT, "application/json");
Header header3 = new BasicHeader(HttpHeaders.AUTHORIZATION, "Basic " + encoding);
List<Header> headers = new ArrayList<Header>();
headers.add(header);
headers.add(header2);
headers.add(header3);
HttpHost proxy = new HttpHost("xxxx", 8080, "http");
CloseableHttpClient client = HttpClientBuilder.create()
.setDefaultHeaders(headers)
.setProxy(proxy)
.build();
HttpPost post = new HttpPost(apiUrl);
String textFileName = "C:/Heena_Code/Test.xlsx";
File file = new File(textFileName);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
FileBody fileBody = new FileBody(file, ContentType.DEFAULT_BINARY);
StringBody stringBody1 = new StringBody("change_request", ContentType.MULTIPART_FORM_DATA);
StringBody stringBody2 = new StringBody("a81c6a1ddb2948d04af824f4059619a9", ContentType.MULTIPART_FORM_DATA);
builder.addPart("table_name", stringBody1);
builder.addPart("table_sys_id", stringBody2);
builder.addPart("uploadFile", fileBody);
HttpEntity entity = builder.build();
post.setEntity(entity);
// Execute HTTP Post Request
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String responseBody = client.execute(post, responseHandler); -----> exception here
System.out.println(responseBody);
Getting exception
Severe: org.apache.http.ConnectionClosedException: Premature end of chunk coded message body: closing chunk expected
at org.apache.http.impl.io.ChunkedInputStream.getChunkSize(ChunkedInputStream.java:263)
at org.apache.http.impl.io.ChunkedInputStream.nextChunk(ChunkedInputStream.java:222)
at org.apache.http.impl.io.ChunkedInputStream.read(ChunkedInputStream.java:183)
at org.apache.http.impl.io.ChunkedInputStream.read(ChunkedInputStream.java:210)
at org.apache.http.impl.io.ChunkedInputStream.close(ChunkedInputStream.java:312)
at org.apache.http.impl.execchain.ResponseEntityProxy.streamClosed(ResponseEntityProxy.java:142)
at org.apache.http.conn.EofSensorInputStream.checkClose(EofSensorInputStream.java:228)
at org.apache.http.conn.EofSensorInputStream.close(EofSensorInputStream.java:172)
at org.apache.http.client.entity.LazyDecompressingInputStream.close(LazyDecompressingInputStream.java:97)
at org.apache.http.util.EntityUtils.consume(EntityUtils.java:90)
at org.apache.http.impl.client.AbstractResponseHandler.handleResponse(AbstractResponseHandler.java:69)
at org.apache.http.impl.client.BasicResponseHandler.handleResponse(BasicResponseHandler.java:66)
at org.apache.http.impl.client.BasicResponseHandler.handleResponse(BasicResponseHandler.java:52)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:223)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:165)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:140)
I changed my approach and used a MultiPartUtility class to fire request through HTTPUrlConnection passing two form fields in text/plain format and the file in application/octetstream format and binary encoding

500 Error - Unable to select and perform a post action

I am not good with Web API. Here is my problem. I send an Json serialized object from my Windows Form Application. The object is an Entity table. When I do a get response it returns a 500 server error. Basically I plan to have multiple post methods in one controller which I may not be doing right. So I need you guys to guide me on what I have been doing wrong.
Here is my Controller:
[ResponseType(typeof(HttpWebResponse)), HttpPost, ActionName("MerchandiseApi")]
public HttpResponseMessage PostMain(IList<IMF_Main> mainFromConsolidator)
{
if (!ModelState.IsValid)
return Request.CreateResponse(HttpStatusCode.BadRequest, 2);
using (var anthill = new AnthillConsolidatorEntities())
{
var main = new IMF_Main();
foreach (var item in mainFromConsolidator)
{
main.BrandID = item.BrandID;
main.ItemID = item.ItemID;
main.CategoryID = item.CategoryID;
main.SubCategoryID = item.SubCategoryID;
main.ClassID = item.ClassID;
main.GenderID = item.GenderID;
main.CoaID = item.CoaID;
main.SubCoaID = item.SubCoaID;
main.First_SRP = item.First_SRP;
main.Current_SRP = item.Current_SRP;
main.Previous_SRP = item.Previous_SRP;
main.isSenior = item.isSenior;
main.isActive = item.isActive;
main.DateCreated = item.DateCreated;
anthill.IMF_Main.Add(main);
anthill.SaveChanges();
}
}
return Request.CreateResponse(HttpStatusCode.OK, 1);
}
Here's my WebApiConfig:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "MerchandiseApi",
routeTemplate: "api/{controller}/{action}"
);
}
Here is where the Uri gets built: I have 2 more tables to send but I will start with this. This goes to my first Post method to the server
var jsonMain = JsonConvert.SerializeObject(consolidatorEntities.IMF_Main, Formatting.None);
HttpPost("http://localhost:50826/api/Merchandise/PostMain", jsonMain) == 1.ToString()
public string HttpPost(string uri, string json)
{
string content = "";
try
{
var request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.Accept = "application/json";
request.ContentType = "application/json";
byte[] bodyBytes = Encoding.UTF8.GetBytes(json);
request.GetRequestStream().Write(bodyBytes, 0, bodyBytes.Length);
request.GetRequestStream().Close();
var response = (HttpWebResponse)request.GetResponse();
var sr = new StreamReader(response.GetResponseStream(), Encoding.GetEncod
ing("UTF-8"));
content = sr.ReadToEnd();
sr.Close();
}
catch (Exception ex)
{
MessageBox.Show("Error sending data to Anthill \nException: " + ex, "Monytron - Consolidator", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return content;
}
Problem
The main problem is with your routing. Routes will check in order so when you post a request to http://localhost:50826/api/Merchandise/PostMain and you have these routes in order:
"api/{controller}/{id}"
"api/{controller}/{action}"
So the first route will match:
If your PostMain method is the only action with [HttpPost], then mainFromConsolidator will be null in your foreach loop you will receive a NullReferenceException that result in a 500 error.
If you have multiple method decorated with [HttpPost], then the call is ambiguous between those actions and you will receive an InvalidOperationExpception with "Multiple actions were found that match the request" message that result in a 500 error.
The other problem is you are using an ActionName("MerchandiseApi") but didn't post to that action.
Solution
You can use multiple solutions. As an option you can define only one route:
"api/{controller}/{action}/{id}"
This way you can create a controller that contains actions like these:
public class SomeController
{
// matches GET /api/some/action1
[HttpGet]
public HttpResponseMessage Action1()
// matches GET /api/some/action2/5
[HttpGet]
public HttpResponseMessage Action2(int id)
// matches POST /api/some/action3
[HttpPost]
public HttpResponseMessage Action3(SomeType someParameter)
// matches POST /api/some/action4
[HttpPost]
public HttpResponseMessage Action4(SomeType someParameter)
}
Anyway if you decide to define multiple routes, pay attention that routes will match in order and also if you used ActionName attribute, then use that name in url to call that action.

GMAIL API sending email with attachment in c#

I need help with sending email w/attachment using Gmail Api in c#.
I have read Google website on sending emails with attachment but the example is in java.
Its too late for the answer, but posting it in case anyone needs it:)
Need MimeKit library for this: can be installed from NuGet.
Code:
public void SendHTMLmessage()
{
//Create Message
MailMessage mail = new MailMessage();
mail.Subject = "Subject!";
mail.Body = "This is <b><i>body</i></b> of message";
mail.From = new MailAddress("fromemailaddress#gmail.com");
mail.IsBodyHtml = true;
string attImg = "C:\\Documents\\Images\\Tulips.jpg OR Any Path to attachment";
mail.Attachments.Add(new Attachment(attImg));
mail.To.Add(new MailAddress("toemailaddress.com.au"));
MimeKit.MimeMessage mimeMessage = MimeKit.MimeMessage.CreateFromMailMessage(mail);
Message message = new Message();
message.Raw = Base64UrlEncode(mimeMessage.ToString());
//Gmail API credentials
UserCredential credential;
using (var stream =
new FileStream("client_secret.json", FileMode.Open, FileAccess.Read))
{
string credPath = System.Environment.GetFolderPath(
System.Environment.SpecialFolder.Personal);
credPath = Path.Combine(credPath, ".credentials/gmail-dotnet-quickstart2.json");
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scope,
"user",
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
Console.WriteLine("Credential file saved to: " + credPath);
}
// Create Gmail API service.
var service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
//Send Email
var result = service.Users.Messages.Send(message, "me/OR UserId/EmailAddress").Execute();
}
Scope can be:
GmailSend or GmailModify
static string[] Scope = { GmailService.Scope.GmailSend };
static string[] Scope = { GmailService.Scope.GmailModify };
Base64UrlEncode function:
private string Base64UrlEncode(string input)
{
var inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
return Convert.ToBase64String(inputBytes)
.Replace('+', '-')
.Replace('/', '_')
.Replace("=", "");
}
I have an example in VB.net. GMail API Emails Bouncing.
Google page provides examples in Java and Python only. The objects being used in the Java example are not available in .Net version of API. It is not possible to translate those examples.
Fortunately, it is quite easy to do the same in C#/VB. Just use plain old Net.Mail.MailMessage to create a message including attachments, then use MimeKit (NuGet it) to convert the message into string and pass the string (after encoding Base64) to "Raw" field of message.send of Gmail API.
There's nothing particular to sending an attachment with the Gmail API. Either way the Gmail API message.send() takes a full RFC822 email message in the message.raw field (urlsafe base64 encoded). The main trick is building up such an RFC822 email message string in your language. I imagine there are some MIME message librarys in C# and that's the main issue is finding those libraries. I don't do C# but javax.internet.mail.MimeMessage works well in java and the 'email' module is good for python.
This other post seems relevant:
How to send multi-part MIME messages in c#?
string[] Scopes = { GmailService.Scope.GmailSend };
string ApplicationName = "Gmail API App";
public GmailForm()
{
InitializeComponent();
SendHTMLmessage();
}
string Base64UrlEncode(string input)
{
var data = Encoding.UTF8.GetBytes(input);
return Convert.ToBase64String(data).Replace("+", "-").Replace("/", "_").Replace("=", "");
}
public void SendHTMLmessage()
{
//Create Message
MailMessage mail = new MailMessage();
mail.Subject = "Subject!";
mail.Body = "This is <b><i>body</i></b> of message";
mail.From = new MailAddress("youremail#gmail.com");
mail.IsBodyHtml = true;
string attImg = "C:\\attachment.pdf";
mail.Attachments.Add(new Attachment(attImg));
mail.To.Add(new MailAddress("receiver#mail.com"));
MimeKit.MimeMessage mimeMessage = MimeKit.MimeMessage.CreateFromMailMessage(mail);
var msg = new Google.Apis.Gmail.v1.Data.Message();
msg.Raw = Base64UrlEncode(mimeMessage.ToString());
//Gmail API credentials
UserCredential credential;
using (var stream =new FileStream(Application.StartupPath + #"/credentials.json", FileMode.Open, FileAccess.Read))
{
string credPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
credPath = Path.Combine(credPath, ".credentials/gmail-dotnet-quickstart2.json");
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets,Scopes,"user",CancellationToken.None,new FileDataStore(credPath, true)).Result;
Console.WriteLine("Credential file saved to: " + credPath);
}
// Create Gmail API service.
var service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
//Send Email
var result = service.Users.Messages.Send(msg, "me").Execute();
MessageBox.Show("Your email has been successfully sent !", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
}

Error: Compile Error: Method does not exist or incorrect signature: ConnectApi.BinaryInput

i write a code in apex for setting the chatter photo of a user . i write a function
public PageReference setPhoto() {
Http h = new Http();
HttpRequest req = new HttpRequest();
string firstImageURL = 'https://ap1.salesforce.com/resource/1377118388000/sample_pic';
firstImageURL = firstImageURL.replace(' ', '%20');
req.setEndpoint(firstImageURL);
req.setMethod('GET');
req.setHeader('Content-Type', 'image/jpeg');
req.setCompressed(true);
req.setTimeout(60000);
HttpResponse res = null;
res = h.send(req);
blob image = res.getBodyAsBlob();
ConnectApi.BinaryInput bb = ConnectApi.BinaryInput(image, 'image/png', 'myfile');
System.debug('user is' + ConnectApi.ChatterUsers.setPhoto(null, '00590000001jFln', bb));
return null;
}
when i try to save it it is giving me error
Error: Compile Error: Method does not exist or incorrect signature: ConnectApi.BinaryInput(Blob, String, String) at line 28 column 27
and i am following this http://www.salesforce.com/us/developer/docs/apexcode/Content/connectAPI_inputs.htm#capi_binary_input
can you please guideline whether this documentation is wrong or right ?? and how to get ConnectApi.BinaryInput instance
You'are trying to use the instance method as a static. Create an instance of ConnectApi.BinaryInput
ConnectApi.BinaryInput binaryInput = new ConnectApi.BinaryInput(fileBlob, null, filename);

Resources