I'm new to java code generation from WADL, I used cxf-wadl2java-plugin and it works fine, the problem is that the generated code contains the resource code but no implementation as such:
/**
* Created by Apache CXF WadlToJava code generator
**/
package wadl.client;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import wadl.Response;
#Path("/path")
public class PathResource {
#GET
#Produces({"application/xml", "application/json" })
public Response get(#QueryParam("q") String q, #QueryParam("attr") String attr) {
//TODO: implement
return null;
}
}
Is there any mean to get an implementation when the code generation is done?
How do I us this class (injection??)?
How do I set the data return type? (json, xml, Response object?)
Thanks for your help
According to the Wikipedia Page:
WADL models the resources provided by a service and the relationships
between them
It however, does not state anything on the logic behind such resources.
Long story short, the WADL should explain/point out what resources must your system expose, however it does not explain how are these resources implemented, which is usually ideal since Web Services are usually used to simply expose a set of functionalities.
Related
I am rewriting an old REST service written in an in-house framework to use Spring. I have a Controller with a POST method which takes a parameter either as a POST or as x-www-form-urlencoded body. Following multiple StackOverflow answers, I used #ModelAttribute annotation and created a model.
My problem is that the old REST API is using a property name in snake case - say some_property. I want my Java code to follow the Java naming conventions so in my model the field is called someProperty. I tried using the #JsonProperty annotation as I do in my DTO objects but this time this didn't work. I only managed to make the code work if the field in the model was named some_property. Here is my example code:
import com.fasterxml.jackson.annotation.JsonProperty;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
#RestController
#RequestMapping("/my/api/root")
public class SomethingController {
#PostMapping("/my/api/suffix")
public Mono<Object> getSomething(
#RequestParam(name = "some_property", required = false) String someProperty,
#ModelAttribute("some_property") Model somePropertyModel) {
// calling my service here
}
public class Model {
#JsonProperty("some_property")
private String someProperty;
private String some_property;
// Getters and setters here
}
}
I am searching for annotation or any other elegant way to keep the Java naming style in the code but use the legacy property name from the REST API.
The #JsonProperty annotation can only work with the JSON format, but you're using x-www-form-urlencoded.
If you can't change your POST type, you have to write your own Jackson ObjectMapper:
#JsonProperty not working for Content-Type : application/x-www-form-urlencoded
I also met a similar case you,
Please replace #ModelAttribute("some_property") with #RequestBody.
Hope to help you!
I followed the guide here to create a new Jersey HTTP server from Maven Archetype. Everything is fine, the resource returns the string as expected, here is the resource:
package com.example;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("myresource")
public class MyResource {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getIt() {
return "Hello from my Server";
}
}
I followed the guide here to use the downloaded ArcGIS Runtime SDK. I created the following simple Java class to determine whether a Point in inside a Geometry (Circle, Rectangle, Polygon, ...) or not:
package geoC;
import com.esri.arcgisruntime.geometry.Geometry;
import com.esri.arcgisruntime.geometry.GeometryEngine;
import com.esri.arcgisruntime.geometry.Point;
import com.esri.arcgisruntime.geometry.SpatialReferences;
public class checkInside {
public static void main(String[] args) {
Point pt = new Point( -0.04473405456542423, 39.98776978688296, SpatialReferences.getWgs84());
String rectangleJson = "{\"xmin\":-0.05225854142896743,\"ymin\":39.98251082423102,\"xmax\":-0.02856927140946811,\"ymax\":39.993164240959295,\"spatialReference\":{\"wkid\":4326}}";
Geometry rectangle = (Geometry) Geometry.fromJson(rectangleJson);
//check if the point is inside the rectangle or not
boolean decision = GeometryEngine.contains( rectangle, pt );
System.out.println(decision);
}
}
This class works fine, producing "true" or "false" depending on the location input.
The problem arises when I tried to combine the first and the second piece of code, I put the content of the 2nd piece of code in the first piece of code:
package com.example;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.esri.arcgisruntime.geometry.Geometry;
import com.esri.arcgisruntime.geometry.GeometryEngine;
import com.esri.arcgisruntime.geometry.Point;
import com.esri.arcgisruntime.geometry.SpatialReferences;
#Path("myresource")
public class MyResource {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getIt() {
Point pt = new Point( -0.04473405456542423, 39.98776978688296, SpatialReferences.getWgs84());
String rectangleJson = "{\"xmin\":-0.05225854142896743,\"ymin\":39.98251082423102,\"xmax\":-0.02856927140946811,\"ymax\":39.993164240959295,\"spatialReference\":{\"wkid\":4326}}";
Geometry rectangle = (Geometry) Geometry.fromJson(rectangleJson);
boolean decision = GeometryEngine.contains( rectangle, pt );
System.out.println(decision);
return "Hello from my Server";
}
}
mvn compile ---> BUILD SUCCESS
mvn exec:java ---> BUILD FAILURE
The error is: Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.2.1:java (default-cli) on project TestArcGISJersey: An exception occured while executing the Java class. null: InvocationTargetException: com/esri/arcgisruntime/geometry/Geometry: com.esri.arcgisruntime.geometry.Geometry -> [Help 1]
Furthermore, if I comment the 2 lines (boolean decision = ... + System.out.println(...) ) then mvn exec:java executes succesfully, but when I send a GET request to the resource, request failed instead of getting the expected String.
Anyone has any ideas here? Thank you very much.
Seems that you have not gotten any licence yet, remember that all ArcGIS products need to have a licence, does not matter if you pay or not.
I kindly suggest you to follow this steps from ArcGIS Developers (ArcGIS runtime for JAVA 100.0.0) "License your app"
There you can see that you need a line like this:
https://developers.arcgis.com/java/latest/guide/license-your-app.htm
// license with a license key
ArcGISRuntimeEnvironment.setLicense("runtimelite,1000,rud#########,day-month-year,####################");
I am not sure about using ArcGIS runtime on a Jersey HTTP server from Maven Archetype. you will need additional tests and always look to the server log.
ArcGIS Runtime SDK for Java is not a good candidate as an API to use in a server environment. While some APIs may work, this use case is not supported. The API was not designed for use in server containers.
However, for your use case you've described, you may want to look at the Java Geometry API open source project found here: https://github.com/Esri/geometry-api-java.
Still, having stated the reality of this, I do feel it is natural to assume it would be a viable solution for server development. So great question!
I have been deconstructing someone's project which retrieves a response from a 3rd party API and prints it to a Vaadin web GUI.
My version is supposed to retrieve an API response from an anime website, parse this automatically (??) into an object and then print the object attribute to my screen mainly so I can see if it bloody works.
I converted a sample XML file to XSD then used JAXB to generate a class from it (and a builder but I'm not quite sure how that is used yet) in order to store my response from the API.
I have a getservice java class that performs the get request. This worked previously when all I was doing was printing the result of the request to a string and before I tried to put it into an object.
Lastly I have a main JavaApplication4 class that was apparently necessary to create an instance of the request (I'm pretty new to OO programming but it sort of makes sense maybe).
The application runs however I now get an error message:
Exception in thread "main" java.lang.NullPointerException
at javaapplication4.getservice.fetchMovie(getservice.java:36)
at javaapplication4.JavaApplication4.main(JavaApplication4.java:17)
Java Result: 1
BUILD SUCCESSFUL (total time: 0 seconds)
This points me to the line
return target.queryParam("anime", "4658")
.request(MediaType.TEXT_HTML)
.header("Content-type", "text/html")//application_json or text_html or xml
.get(Ann.class);
I used a breakpoint and found that my client and target remain as null both here and on the above lines:
#PostConstruct
protected void init() {
client = ClientBuilder.newClient();
//target = client.target("http://www.omdbapi.com");
target = client.target("http://cdn.animenewsnetwork.com/encyclopedia/api.xml");
}
Looking back at the original guy's project, I think the problem is because I am using annotations like #PostConstruct but do not have an #Inject annotation. I tried to add an #Inject to my Main/JavaApplication4 file but it either doesn't do anything (and looks completely wrong) or it tells me its not applicable where I put it.
I would totally appreciate someone to have a quick look and see if its those annotations causing the problem... I don't understand how to use them in any context yet and it is so hard to find examples that do things in a particular way, I am just left trying to reposition bits and pieces for hours and obviously that doesn't work XD
The full code of the project, MINUS the Ann.java class (which should store the API response in the form of anime , title, name, etc etc) and the ObjectFactory.java class which was generated alongside it (and im not sure what it does yet but thats another step):
Ann.java
(getters and setters and xml stuff i think)
ObjectFactory.java
JavaApplication4.java
package javaapplication4;
import generated.Ann;
import javax.inject.Inject;
public class JavaApplication4 {
//#Inject
//getservice gt;
public static void main(String[] args) {
//#Inject
getservice gt = new getservice();
String output = gt.fetchMovie().getAnime().getName();
System.out.println(output);
}
}
getservice.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package javaapplication4;
import generated.Ann;
import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
/**
*
* #author J
*/
#ApplicationScoped
public class getservice {
private Client client;
private WebTarget target;
#PostConstruct
protected void init() {
client = ClientBuilder.newClient();
//target = client.target("http://www.omdbapi.com");
target = client.target("http://cdn.animenewsnetwork.com/encyclopedia/api.xml");
}
// these apparently stay null when i run JavaAppliation4
// do i need an #Inject somewhere or something completely similar or different?
public Ann fetchMovie() {
//return target.queryParam("anime", "4658")
return target.queryParam("anime", "4658")
.request(MediaType.TEXT_HTML)
.header("Content-type", "text/html")//application_json or text_html or xml
.get(Ann.class);
}
}
Thankyou. Its just one of those parts where "i'm stuck so i'll keep trying" doesn't look like its going to get me very far...idk... :)
#Inject and #Postconstruct relates to "managed beans", CDI. All Java EE servers provide CDI by default. If you wish to use it with plain Java SE environment, you need a CDI implementation like Weld. See this blog entry how that can be done.
Hi I am new to Jersy restful web service. I simply created one restful web service with pojo class. I did not mention where ever in my code for xml format but I got output as xml format in browsr.
Please HELP ME reason of output showing XML format... I give my code below.
Class Order:
package shopping.cart.om;
public class Order
{
public Map<String, Order> getModel(){
return contentProvider;
}
}
Class OrdersService:
package shopping.cart.service;
import java.util.ArrayList;
import java.util.List;
import shopping.cart.dao.OrderDao;
import shopping.cart.om.Order;
}
}
<id>1</id>
</order>
</orders>
The reason is that XML is the default format of the output, most likely. Check this question: How to set to default to json instead of xml in jersey?
The question is what type of data you expect after hitting restful endpoint , if XML then you have to tell it in method level , f JSON or other you can also define this in your method , example
package com.hello.demo;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("/hello")
public class Hello {
#POST
#Path("/test")
#Consumes(MediaType.TEXT_XML)
#Produces(MediaType.TEXT_XML)
public String consumeTest (String requestMessage) {
return requestMessage;
}
}
Suppose you want simple text as output then
use :
#Produces(MediaType.TEXT_PLAIN)
in method level .
For detail please visit : Jersey
Apart from it if you are interested about different media type supported by jersey you may visit : media types
I have a few utility methods that I wrote in Java, for test data creation against a service. A couple of my colleagues who have the same use case thought it would be cool if they could re-use it, but they are writing their tests in Perl and Python respectively. So I am thinking of standing up a JSON REST service that would expose these methods.
I have limited experience writing web-apps. What would be the fastest way to stand up and deploy my service?
I am thinking of using eclipse/spring to do it and ant to deploy on a Jetty container. But I would like to hear your experiences about this. Also it seems some IDEs/Plugins have better support for some technologies than others. So I would like to hear what IDE/Plugins + J2EE Technology stack + Server(If that matters) is a good combination for my usecase and why. I would like to stick to open source software.
I believe using Maven gets you up as fast as one can. Here's how you can do it.
It uses the RESTEasy implementation of JAX-RS (the Java API for RESTful Web Services, an official part of Java EE 6).
This is a java war maven project with the bare minimum structure. These are the files:
-pom.xml
-src
|
--main
|
--java
|
--rest
|
--HelloResource.java
--JaxRsActivator.java
I called it simpleRest as seen below. All the archives are exactly as shown:
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>simpleRest</groupId>
<artifactId>simpleRest</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>2.3.1.GA</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<!-- So maven doesn't require web.xml -->
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
HelloResource.java
package rest;
import java.util.Date;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
#Path("/hello")
public class HelloResource {
#GET
#Produces("text/plain")
public String helloResource() {
return "Hello! It's "+new Date();
}
}
JaxRsActivator.java:
package rest;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("/rest")
public class JaxRsActivator extends Application {
}
This generates a simpleRest.war (through mvn clean package). You can deploy it to a freshly installed JBoss AS 7.1.1.Final (just throw the war file in the deploy folder) or a Tomcat.
After that, the URL is available as expected:
http://127.0.0.1:8080/simpleRest/rest/hello
How quick is that?
Here's the shortest way I could think of to a fully functional REST API requiring only Java, Gradle, and a text editor. Create two files in a clean project directory as follows:
build.gradle
buildscript {
repositories { mavenCentral() }
dependencies {
classpath 'org.gradle.api.plugins:gradle-tomcat-plugin:0.9.8'
}
}
apply plugin: 'tomcat'
repositories { mavenCentral() }
dependencies {
compile(
'com.sun.jersey:jersey-core:1.17',
'com.sun.jersey:jersey-server:1.17',
'com.sun.jersey:jersey-servlet:1.17',
'com.sun.jersey:jersey-json:1.17',
)
tomcat(
'org.apache.tomcat:tomcat-catalina:7.0.40',
'org.apache.tomcat:tomcat-coyote:7.0.40',
'org.apache.tomcat:tomcat-jasper:7.0.40',
)
}
src/main/java/org/example/TheApplication.java
package org.example;
import com.sun.jersey.api.core.ClassNamesResourceConfig;
import javax.ws.rs.*;
import javax.ws.rs.core.Response;
import javax.xml.bind.annotation.XmlRootElement;
#Path("/")
#ApplicationPath("/")
public class TheApplication extends ClassNamesResourceConfig {
public TheApplication() { super(TheApplication.class); }
static Foo foo = new Foo();
#GET #Produces("application/json")
public Foo getFoo() {
return foo;
}
#POST #Consumes("application/json")
public Response setFoo(Foo foo) {
TheApplication.foo = foo;
return Response.ok().entity("Stored it!").build();
}
#XmlRootElement
static class Foo {
private String message = "Hello World";
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
}
}
Once those two files are in place, gradle tomcatRunWar will start your REST API, and navigating to http://localhost:8080/fastest-web-service/ in a browser will get you the "Hello World" JSON message. If you then POST similar JSON, like {"message": "something else"} to that same URL with something like curl or Poster specifying a Content-Type of "application/json", that new object will be stored and returned on successive GET requests. It's just a very bare-bones example but covers a lot of the basics of a JSON API.
IDEs: You could further develop this easily with any common Java IDE. The Community Edition of IntelliJ IDEA and Eclipse are both popular and free IDEs. <opinion>IDEA is far superior and the Ultimate Edition is 110% worth the cost of a personal license for a regular Java developer.</opinion>
Technology Stack: JAX-RS is a leading way of writing REST APIs in Java. Pick any implementation. This example uses Jersey, the reference implementation. Spring may be overkill if you just need a simple API to expose already-written logic. It brings along more complexity than it sounds like you need. On the other hand, if you need a more flexible and capable framework that has more built-in support for virtually everything in the world, Spring may be just the ticket.
Server: Jetty or Tomcat supporting Servlet 3.0. There's not likely a reason for anything more or less.
Well I'm going to toss the NetBeans IDE bundled with GlassFish 3.x in to the ring.
Download that bundle, install it, and JAX-RS serving up services is a right-click wizard away. One download, one install, completely comprehensive. Lots of documentation, wizards, and samples.
It's really the shortest path, and it's a complete toolkit.
What we are going for in my company is an Apache TomEE server, using JAX-RS to expose our API as REST services. It is easy to set up and easy to work with.
I have good experience with Jersey, which is the reference implementation of jax-ws. It has support for jax-ws annotations, and it's easy to use.
As a consultant, I get paid for solving problems. I found that Espresso Logic is the fastest way for me to deliver JSON/REST API. It runs on a Tomcat foundation and can easily be deployed locally, on Elastic Beanstalk, or Microsoft Azure. It connects to all the major SQL databases and gives me an instant REST API for all tables, views, stored-procedures, and relationships (which are used to build more complex document style resources). It has both an HTML Studio and a Node.JS command line for administration. The best feature is the declarative logic (like a spreadsheet) for formula, derivations, and validations. The logic can be extended using both JavaScript and Java plugin libraries. I spend my time writing JavaScript solutions and letting Espresso do the heavy lifting of REST pagination, optimistic locking, SQL query optimization, and multi-table transaction logic. Full disclosure - I have known them for 25 years and this is the best game-changing technology I have seen. Check it out: www.espressologic.com
To speed up using the Jersey framework along the lines of https://stackoverflow.com/a/3891380/1497139
we (BITPlan - my company) have created the following open source projects:
https://github.com/BITPlan/com.bitplan.simplerest
https://github.com/BITPlan/com.bitplan.simplerest-api
https://github.com/BITPlan/com.bitplan.simplerest-example
See the code samples below how to setup:
a server
some application content to be used (User)
some Resource exposing the content (UserResource)
a test case showing that things work
Test for Example
package com.bitplan.simplerest.example;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import com.bitplan.rest.RestServer;
import com.bitplan.rest.test.TestRestServer;
/**
* test the example Server
* #author wf
*
*/
public class TestExampleServer extends TestRestServer {
boolean debug=true;
#Before
public void initServer() throws Exception {
startServer();
}
#Override
public RestServer createServer() throws Exception {
RestServer result = new ExampleServer();
return result;
}
#Test
public void testExampleServer() throws Exception {
String userXml=getResponseString("application/xml", "/example/user");
if (debug)
System.out.println(userXml);
String expected="<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><user><name>Doe</name><firstname>John</firstname><email>john#doe.org</email></user>";
assertEquals(expected,userXml);
String userJson=getResponseString("application/json", "/example/user");
if (debug)
System.out.println(userJson);
String expectedJson="{\"name\":\"Doe\",\"firstname\":\"John\",\"email\":\"john#doe.org\"}";
assertEquals(expectedJson,userJson);
}
}
ExampleServer
package com.bitplan.simplerest.example;
import com.bitplan.rest.RestServerImpl;
/**
* an Example Server
* #author wf
*
*/
public class ExampleServer extends RestServerImpl {
/**
* construct Example Server
* setting defaults
* #throws Exception
*/
public ExampleServer() throws Exception {
// listen to whole network
settings.setHost("0.0.0.0");
// listen on given port
settings.setPort(8111);
// add the default path
settings.setContextPath("/example");
// add a static handler
settings.addClassPathHandler("/", "/static/");
// setup resources from the given packages
String packages="com.bitplan.simplerest.example.resources;";
settings.setPackages(packages);
}
/**
* start Server
*
* #param args
* #throws Exception
*/
public static void main(String[] args) throws Exception {
ExampleServer rs=new ExampleServer();
rs.settings.parseArguments(args);
rs.startWebServer();
} // main
}
User
package com.bitplan.simplerest.example;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
/**
* example class
*/
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class User {
public String name;
public String firstname;
public String email;
}
User Resource
package com.bitplan.simplerest.example.resources;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import com.bitplan.simplerest.example.User;
#Path("/user")
public class UserResource {
#GET
public User getUser() {
User user=new User();
user.name="Doe";
user.firstname="John";
user.email="john#doe.org";
return user;
}
}
I would like to suggest the following approach to write REST-based Web Services. The follow "script" will guide you to create a very simple, and lightweight, web project using Kikaha and Undertow. The bellow approach is quite similar to the JAXRS-based example provided by Ryan Stewart, but with higher performance and low footprint due to Undertow's architecture (Undertow is really fast).
Use the Kikaha's command line tool to create a stub project:
kikaha project create 2.0 --name=my-app
Although the above command brings you a couple REST API classes out-of-box, you can create your own entity class that represents your business rule as shown bellow.
User.java
import lombok.*;
#Getter
#Setter
public class User {
#NonNull Long id;
#NonNull String name;
}
Create a route class. It will expose methods as REST endpoints.
UserResource.java
import lombok.*;
import kikaha.urouting.api.*;
import javax.inject.*;
#Singleton
#Path("user")
#Consumes( Mimes.JSON )
#Produces( Mimes.JSON )
public class UserResource {
User savedUser;
#POST
public Response saveUser( User user ){
if ( user.getName().isEmpty() )
return DefaultResponses.preconditionFailed()
.entity("Name is blank");
savedUser = user;
return DefaultResponses.ok();
}
#GET
public User getUser(){
return savedUser;
}
}
Run your 5Mb project through the command line:
kikaha run-app
Disclaimer: I was involved with Kikaha's development and have implanted many Undertow projects since its first version.
All the answers apply to using Java locally with a local container. If you're considering cloud environments that support Java (and Java-like extensions), you might be able to do this with just one like.
The Raimme platform offers a convenient #Rest annotation. All you need to do is set the URL, and your REST service will be exposed automatically:
#Rest(url = "customer/list")
#ResponseBody
public String getCustomer()
{
return "[]";
}
This whole feature is described in more detail here: http://raimme.com/devcenter?questionId=1cg000000000g