Does anyone know how to test the below #MultipartForm RestEasy Webservice? I'm unsure of how to setup the request to the below service, any ideas?
#POST
#Path("/upload")
#Consumes("multipart/form-data")
public Response create(#MultipartForm FileUploadForm form) {
System.out.println("test");
return null;
}
public class FileUploadForm {
private byte[] filedata;
public FileUploadForm() {}
public byte[] getFileData() {
return filedata;
}
#FormParam("filedata")
#PartType("application/octet-stream")
public void setFileData(final byte[] filedata) {
this.filedata = filedata;
}
}
Please see the following blog. Maybe this is what you are looking for: http://ankiewsky.blogspot.com/2008/07/resteasy-tips-part-1.html
This appears to be a duplicate of:
RestEasy client framework file upload
I just posted an answer with some general guidelines on how I just got this working over there.
Related
I am preparing a ReSTful service which I would like to have documented using RAML (and perhaps Swagger as well), but it seems that I cannot implement both JAX-RS and RAML in the same application at the same time.
I have created an Application class for JAX-RS as follows:
public class Application extends javax.ws.rs.core.Application {
#Override
public Set<Class<?>> getClasses() {
// Use the reflections library to scan the current package tree for
// classes annotated with javax.ws.rs.Path and add them to the JAX-RS
// application
Reflections reflections = new Reflections(this.getClass().getPackage().getName());
return reflections.getTypesAnnotatedWith(Path.class);
}
}
I attach the JAX-RS Application object as follows:
Component component = new Component();
Server server = new Server(Protocol.HTTP, PORT);
component.getServers().add(server);
JaxRsApplication jaxRsApplication = new JaxRsApplication(component.getContext().createChildContext());
jaxRsApplication.add(new Application());
jaxRsApplication.setObjectFactory(objectFactory);
component.getDefaultHost().attach("/rest", jaxRsApplication);
And I would also like to implement the RAML extension, but it looks like it is tied to the Restlet Router and having it's own Application class. Is there a way to combine the two?
Indeed the RAML extension of Restlet isn't designed to be used within JAXRS application. That said you can define a resource that provide the RAML content based on classes ApplicationIntrospector of Restlet and RamlEmitter of RAML parser, as described below:
public class RamlResource {
private Definition definition;
#Path("/raml")
#GET
public String getRaml() {
return new RamlEmitter().dump(RamlTranslator
.getRaml(getDefinition()));
}
private synchronized Definition getDefinition() {
if (definition == null) {
synchronized (RamlResource.class) {
definition = ApplicationIntrospector.getDefinition(
Application.getCurrent(),
new Reference("/"), null, false);
}
}
return definition;
}
}
It's the way the RAML extension of Restlet works. You could also use such an approach for Swagger but be careful since Swagger 1.2 requires several resources (a main and several sub ones with each categories). It's not the case anymore for Swagger 2.
You can notice that there is a JAX-RS support for Swagger in the extension org.restlet.ext.swagger.
----- Edited
Perhaps can you make a try with this class that corresponds to a port of the class JaxRsApplicationSwaggerSpecificationRestlet to RAML. It's based on the class JaxRsIntrospector which seems relevant for JAX-RS application:
public class JaxRsApplicationRamlSpecificationRestlet extends Restlet {
private Application application;
private String basePath;
private Reference baseRef;
private Definition definition;
public JaxRsApplicationRamlSpecificationRestlet(Application application) {
this(null, application);
}
public JaxRsApplicationRamlSpecificationRestlet(Context context, Application application) {
super(context);
this.application = application;
}
public void attach(Router router) {
attach(router, "/api-docs");
}
public void attach(Router router, String path) {
router.attach(path, this);
router.attach(path + "/{resource}", this);
}
public Representation getApiDeclaration() {
Raml raml = RamlTranslator.getRaml(
getDefinition());
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
try {
return new StringRepresentation(
mapper.writeValueAsString(raml),
MediaType.APPLICATION_YAML);
} catch (Exception ex) {
return new StringRepresentation("error");
}
}
public String getBasePath() {
return basePath;
}
private synchronized Definition getDefinition() {
if (definition == null) {
synchronized (JaxRsApplicationRamlSpecificationRestlet.class) {
definition = JaxRsIntrospector.getDefinition(application,
baseRef, false);
}
}
return definition;
}
#Override
public void handle(Request request, Response response) {
super.handle(request, response);
if (Method.GET.equals(request.getMethod())) {
response.setEntity(getApiDeclaration());
} else {
response.setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED);
}
}
public void setApiInboundRoot(Application application) {
this.application = application;
}
public void setApplication(Application application) {
this.application = application;
}
public void setBasePath(String basePath) {
this.basePath = basePath;
// Process basepath and check validity
this.baseRef = basePath != null ? new Reference(basePath) : null;
}
}
You can use this class like this:
JaxRsApplication application
= new JaxRsApplication(component.getContext());
MyApplication app = new MyApplication();
application.add(app);
new JaxRsApplicationRamlSpecificationRestlet(app);
(...)
There is no need for a dedicated resource. Please note that this code is a bit experimental ;-) I could propose it back for a contribution for the extension raml in Restlet...
Hope it helps you,
Thierry
How can I add a custom section to WSDL that's directly under wsdl:definitions? Something like this:
I've tried stuff like using custom attributes that implement IWsdlExportExtension, but I havent gotten even close to the result I need and I'm not sure if that's the right way to do this.
Is that even possible or should I just paste that section into file and specify externalMetadataLocation in web.config?
The wsdl from your question has been genereted from asmx. If you want to do the same you should use IVIS library and decorate your class with ISService attrubute. For WCF you should do next:
[CustomAttribute]
public class Service1 : IService1
{
public void DoWork()
{
}
}
public class CustomAttribute:Attribute, System.ServiceModel.Description.IWsdlExportExtension, System.ServiceModel.Description.IWsdlImportExtension, IContractBehavior
{
public void ExportContract(System.ServiceModel.Description.WsdlExporter exporter, System.ServiceModel.Description.WsdlContractConversionContext context)
{
BeforeImport(exporter.GeneratedWsdlDocuments, exporter.GeneratedXmlSchemas, new List<XmlElement>());
}
public void BeforeImport(System.Web.Services.Description.ServiceDescriptionCollection wsdlDocuments, System.Xml.Schema.XmlSchemaSet xmlSchemas, ICollection<XmlElement> policy)
{
//throw new NotImplementedException();
var xdoc = new XmlDocument();
var element = xdoc.CreateElement("ivis","WebServiceInfo", "ivis");
var node = xdoc.CreateNode(XmlNodeType.Element, "Identifier", "ivis");
node.InnerText = "URN:IVIS:100001:ISS-IeM";
element.AppendChild(node);
/// and so on :)
wsdlDocuments[0].Extensions.Add(element);
}
}
Body of all others methods for implemented interfaces can be empty.
This is in first approach.
I don't want to read the whole thing, than put it in a file and than stream that. I wonder can I stream the datareader somehow to the client using WCF and Streaming on?
You can achieve this by using MessageContracts.
When I was trying to figure this out myself for the first time, I came across this article, which really helped a lot: http://www.codeproject.com/Articles/166763/WCF-Streaming-Upload-Download-Files-Over-HTTP
Here is a very basic example of setting up your Contract:
[MessageContract]
public class MyFileInfo : IDisposable
{
[MessageHeader(MustUnderstand = true)]
public string FileName;
[MessageHeader(MustUnderstand = true)]
public long Length;
[MessageHeader]
public string FileHash;
[MessageHeader]
public string Status;
[MessageBodyMember]
public Stream FileData;
public void Dispose()
{
if (FileData != null)
{
FileData.Close();
FileData = null;
}
}
}
[MessageContract]
public class FileRequest
{
[MessageHeader]
public string fileName;
}
When I was first learning WCF I hated how verbose the default application config files were, so after some google searches / research I wrote a blog post w/ Code Examples on how to setup WCF Client proxy without a huge application config file: http://justindonohoo.blogspot.com/2012/08/generic-wcf-client-library-code.html
I want a HttpHandler or HttpModule that redirect the WCF-a Request to another WCF say WCF-b.
below code not working.
public class Router : IHttpModule
{
public void Init(System.Web.HttpApplication Appl)
{
Appl.Context.RewritePath(#"~/WCFGateWayKid.svc");
}
public void Dispose()
{ }
}
Please help.
Thanks
Finally got a solution. System.ServiceModel.Routing.RoutingService is one of the new feature in .Net 4.0 Please refer to: this link
(specifically RESTeasy)
It would be nice (for a single file) to have a method signature like:
public void upload(#FormParam("name") ..., #FormParam("file") file: InputStream)
...
doable? or am I dreaming? doesn't seem to be that simple.
The key is to leverage the #MultipartForm annotations that comes with RESTEasy. This enables you to define a POJO that contains all the parts of the form and bind it easily.
Take for example the following POJO:
public class FileUploadForm {
private byte[] filedata;
public FileUploadForm() {}
public byte[] getFileData() {
return filedata;
}
#FormParam("filedata")
#PartType("application/octet-stream")
public void setFileData(final byte[] filedata) {
this.filedata = filedata;
}
}
Now all you need to do is use this POJO in the entity which would look something like this:
#POST
#Path("/upload")
#Consumes("multipart/form-data")
public Response create(#MultipartForm FileUploadForm form)
{
// Do something with your filedata here
}