How to inject dependencies into resources with Jersey? - rest

I'm having the following code:
#Path("stores")
class StoreResources {
private ServerConfig config;
#GET
public String getAll() {
//do some stuff with ServerConfig
}
}
And I need the ServerConfig object to be injected into this class from outside and use it inside the getAll() method.
What are the possible ways to achieve it? Should I use a DI framework like Guice or Spring?

This is a good blog about Spring injection under Jersey http://javaswamy.blogspot.com/2010/01/making-jersey-work-with-spring.html
The upshot is you use annotations to flag fields that are to be injected, an example resource being
package com.km.services;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.sun.jersey.spi.inject.Inject;
import com.km.spring.SimpleBean;
#Path("/hello")
#Component
#Scope("request")
public class HelloResource {
#Inject private SimpleBean simpleBean;
#GET
#Produces("text/plain")
public String getMessage() {
return simpleBean.sayHello();
}
}
For my purposes the configuration was excessively difficult so I used a static spring resolver factory to resolve the bean. eg.
private SimpleBean simpleBean = SpringBeanFactory.getBean("mySimpleBean");

You don't need Spring or Guice to inject a ServletConfig. Jersey does through its own injection mechanism. Refer to the simple-servlet example that comes with Jersey samples distribution. Here is the sample code that injects a HttpServletRequest and a ServletConfig onto a resource:
#Path("/resource1")
public class ResourceBean1 {
#Context
HttpServletRequest servletRequest;
#Context
ServletConfig servletConfig;
#GET
#Produces("text/plain")
public String describe() {
return "Hello World from resource 1 in servlet: '" +
servletConfig.getServletName() +
"', path: '" +
servletRequest.getServletPath() +
"'";
}
}
When deploying an JAX-RS application using Servlet then ServletConfig, ServletContext, HttpServletRequest and HttpServletResponse are available for injection using #Context.

Related

Wildfly throws "Unable to find a constructor that takes a String param or a valueOf() or fromString() method for javax.ws.rs.QueryParam" error

Im using wildfly 9.0 to deploy my war file. I have java LocalDateTime, Java Money types defined in my REST GET endpoints.
When i deploy my war file, i get following error[1]. Based on this answer [2] I have written "ParamConverterProvider" implementations for both types.
It was working fine( I haven't seen same issue again till now) and now i get same issue.
Any clue?
[1]
Caused by: java.lang.RuntimeException: Unable to find a constructor that takes a String param or a valueOf() or fromString() method for javax.ws.rs.QueryParam(\"totalMoneyVolumeForPeriod\") on public javax.ws.rs.core.Response com.test.rest.StockEndpoint.getItems(java.lang.Integer,java.lang.Integer,java.lang.String,java.lang.String,java.lang.Long,org.javamoney.moneta.Money,java.util.Set,java.lang.String) for basetype: org.javamoney.moneta.Money"}}}}
[2]
jaxrs could not find my custom (de)serializers for joda.money type
Sample code
package com.test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import javax.money.Monetary;
import javax.ws.rs.ext.ParamConverter;
import javax.ws.rs.ext.ParamConverterProvider;
import javax.ws.rs.ext.Provider;
import org.javamoney.moneta.Money;
#Provider
public class MoneyConverterProvider implements ParamConverterProvider {
private final MoneyConverter converter = new MoneyConverter();
#Override
public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
if (!rawType.equals(Money.class)) return null;
return (ParamConverter<T>) converter;
}
public class MoneyConverter implements ParamConverter<Money> {
public Money fromString(String value) {
if (value == null ||value.isEmpty()) return null; // change this for production
return Money.of(new BigDecimal(value), Monetary.getCurrency("AUD"));
}
public String toString(Money value) {
if (value == null) return "";
return value.toString(); // change this for production
}
}
}
Application claas
package com.test;
import javax.ws.rs.core.Application;
import com.test.autogen*;
import io.swagger.jaxrs.config.BeanConfig;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
#ApplicationPath("/rest")
public class RestApplication extends Application {
public RestApplication() {
BeanConfig beanConfig = new BeanConfig();
//beanConfig.setVersion("1.0");
beanConfig.setSchemes(new String[] { "http" });
beanConfig.setTitle("My API");
beanConfig.setBasePath("/rest");
beanConfig.setResourcePackage("com.test.autogen");
beanConfig.setScan(true);
}
#Override
public Set<Class<?>> getClasses() {
HashSet<Class<?>> set = new HashSet<Class<?>>();
set.add(EmailEndpoint.class);
set.add(StockEndpoint.class);
set.add(io.swagger.jaxrs.listing.ApiListingResource.class);
set.add(io.swagger.jaxrs.listing.SwaggerSerializers.class);
return set;
}
}
When you are using classpath scanning, JAX-RS components annotated with #Path or #Provider will get picked up and registered. There are a couple way to use classpath scanning. The most common way is to just have an empty Application class annotated with #ApplicationPath
#ApplicationPath("/api")
public class MyApplication extends Application {}
This is enough for a JAX-RS application to be loaded, and to have the application's classpath scanned to components to register.
But, per the specification, once we override any of the Set<Object> getSingletons or Set<Class> getClasses methods of the Application class, and return a non-empty set, this automatically disables classpath scanning, as it is assumed we want to register everything ourselves.
So in previous cases, you were probably just using classpath scanning. In this case, you need to explicitly add the provider to the set of classes in your getClasses method, since you overrode the method to add other component classes.

"404 Not Found" when viewing swagger api-docs when using swagger-springmvc (now springfox)

I am trying to configure swagger in my spring project, but hitting Hitting "http://localhost:8080/api-docs" says "404 Not Found".
Maven Dependency
<dependency>
<groupId>com.mangofactory</groupId>
<artifactId>swagger-springmvc</artifactId>
<version>0.8.2</version>
</dependency>
SwaggerConfig.java File
package com.ucap.swagger;
import com.mangofactory.swagger.configuration.JacksonScalaSupport;
import com.mangofactory.swagger.configuration.SpringSwaggerConfig;
import com.mangofactory.swagger.configuration.SpringSwaggerModelConfig;
import com.mangofactory.swagger.configuration.SwaggerGlobalSettings;
import com.mangofactory.swagger.core.DefaultSwaggerPathProvider;
import com.mangofactory.swagger.core.SwaggerApiResourceListing;
import com.mangofactory.swagger.core.SwaggerPathProvider;
import com.mangofactory.swagger.scanners.ApiListingReferenceScanner;
import com.wordnik.swagger.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static com.google.common.collect.Lists.newArrayList;
#Configuration
#ComponentScan(basePackages = "com.mangofactory.swagger")
public class SwaggerConfig {
public static final List<String> DEFAULT_INCLUDE_PATTERNS = Arrays.asList("/news/.*");
public static final String SWAGGER_GROUP = "mobile-api";
#Value("${app.docs}")
private String docsLocation;
#Autowired
private SpringSwaggerConfig springSwaggerConfig;
#Autowired
private SpringSwaggerModelConfig springSwaggerModelConfig;
/**
* Adds the jackson scala module to the MappingJackson2HttpMessageConverter registered with spring
* Swagger core models are scala so we need to be able to convert to JSON
* Also registers some custom serializers needed to transform swagger models to swagger-ui required json format
*/
#Bean
public JacksonScalaSupport jacksonScalaSupport() {
JacksonScalaSupport jacksonScalaSupport = new JacksonScalaSupport();
//Set to false to disable
jacksonScalaSupport.setRegisterScalaModule(true);
return jacksonScalaSupport;
}
/**
* Global swagger settings
*/
#Bean
public SwaggerGlobalSettings swaggerGlobalSettings() {
SwaggerGlobalSettings swaggerGlobalSettings = new SwaggerGlobalSettings();
swaggerGlobalSettings.setGlobalResponseMessages(springSwaggerConfig.defaultResponseMessages());
swaggerGlobalSettings.setIgnorableParameterTypes(springSwaggerConfig.defaultIgnorableParameterTypes());
swaggerGlobalSettings.setParameterDataTypes(springSwaggerModelConfig.defaultParameterDataTypes());
return swaggerGlobalSettings;
}
/**
* API Info as it appears on the swagger-ui page
*/
private ApiInfo apiInfo() {
ApiInfo apiInfo = new ApiInfo(
"News API",
"Mobile applications and beyond!",
"https://helloreverb.com/terms/",
"matt#raibledesigns.com",
"Apache 2.0",
"http://www.apache.org/licenses/LICENSE-2.0.html"
);
return apiInfo;
}
/**
* Configure a SwaggerApiResourceListing for each swagger instance within your app. e.g. 1. private 2. external apis
* Required to be a spring bean as spring will call the postConstruct method to bootstrap swagger scanning.
*
* #return
*/
#Bean
public SwaggerApiResourceListing swaggerApiResourceListing() {
//The group name is important and should match the group set on ApiListingReferenceScanner
//Note that swaggerCache() is by DefaultSwaggerController to serve the swagger json
SwaggerApiResourceListing swaggerApiResourceListing = new SwaggerApiResourceListing(springSwaggerConfig.swaggerCache(), SWAGGER_GROUP);
//Set the required swagger settings
swaggerApiResourceListing.setSwaggerGlobalSettings(swaggerGlobalSettings());
//Use a custom path provider or springSwaggerConfig.defaultSwaggerPathProvider()
swaggerApiResourceListing.setSwaggerPathProvider(apiPathProvider());
//Supply the API Info as it should appear on swagger-ui web page
swaggerApiResourceListing.setApiInfo(apiInfo());
//Global authorization - see the swagger documentation
swaggerApiResourceListing.setAuthorizationTypes(authorizationTypes());
//Every SwaggerApiResourceListing needs an ApiListingReferenceScanner to scan the spring request mappings
swaggerApiResourceListing.setApiListingReferenceScanner(apiListingReferenceScanner());
return swaggerApiResourceListing;
}
#Bean
/**
* The ApiListingReferenceScanner does most of the work.
* Scans the appropriate spring RequestMappingHandlerMappings
* Applies the correct absolute paths to the generated swagger resources
*/
public ApiListingReferenceScanner apiListingReferenceScanner() {
ApiListingReferenceScanner apiListingReferenceScanner = new ApiListingReferenceScanner();
//Picks up all of the registered spring RequestMappingHandlerMappings for scanning
apiListingReferenceScanner.setRequestMappingHandlerMapping(springSwaggerConfig.swaggerRequestMappingHandlerMappings());
//Excludes any controllers with the supplied annotations
apiListingReferenceScanner.setExcludeAnnotations(springSwaggerConfig.defaultExcludeAnnotations());
//
apiListingReferenceScanner.setResourceGroupingStrategy(springSwaggerConfig.defaultResourceGroupingStrategy());
//Path provider used to generate the appropriate uri's
apiListingReferenceScanner.setSwaggerPathProvider(apiPathProvider());
//Must match the swagger group set on the SwaggerApiResourceListing
apiListingReferenceScanner.setSwaggerGroup(SWAGGER_GROUP);
//Only include paths that match the supplied regular expressions
apiListingReferenceScanner.setIncludePatterns(DEFAULT_INCLUDE_PATTERNS);
return apiListingReferenceScanner;
}
/**
* Example of a custom path provider
*/
#Bean
public ApiPathProvider apiPathProvider() {
ApiPathProvider apiPathProvider = new ApiPathProvider(docsLocation);
apiPathProvider.setDefaultSwaggerPathProvider(springSwaggerConfig.defaultSwaggerPathProvider());
return apiPathProvider;
}
private List<AuthorizationType> authorizationTypes() {
ArrayList<AuthorizationType> authorizationTypes = new ArrayList<>();
List<AuthorizationScope> authorizationScopeList = newArrayList();
authorizationScopeList.add(new AuthorizationScope("global", "access all"));
List<GrantType> grantTypes = newArrayList();
LoginEndpoint loginEndpoint = new LoginEndpoint(apiPathProvider().getAppBasePath() + "/user/authenticate");
grantTypes.add(new ImplicitGrant(loginEndpoint, "access_token"));
return authorizationTypes;
}
#Bean
public SwaggerPathProvider relativeSwaggerPathProvider() {
return new ApiRelativeSwaggerPathProvider();
}
private class ApiRelativeSwaggerPathProvider extends DefaultSwaggerPathProvider {
#Override
public String getAppBasePath() {
return "/";
}
#Override
public String getSwaggerDocumentationBasePath() {
return "/api-docs";
}
}
}
ApiPathProvider.java file
package com.ucap.swagger;
import com.mangofactory.swagger.core.SwaggerPathProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.util.UriComponentsBuilder;
import javax.servlet.ServletContext;
public class ApiPathProvider implements SwaggerPathProvider {
private SwaggerPathProvider defaultSwaggerPathProvider;
#Autowired
private ServletContext servletContext;
private String docsLocation;
public ApiPathProvider(String docsLocation) {
this.docsLocation = docsLocation;
}
#Override
public String getApiResourcePrefix() {
return defaultSwaggerPathProvider.getApiResourcePrefix();
}
public String getAppBasePath() {
return UriComponentsBuilder
.fromHttpUrl(docsLocation)
.path(servletContext.getContextPath())
.build()
.toString();
}
#Override
public String getSwaggerDocumentationBasePath() {
return UriComponentsBuilder
.fromHttpUrl(getAppBasePath())
.pathSegment("api-docs/")
.build()
.toString();
}
#Override
public String getRequestMappingEndpoint(String requestMappingPattern) {
return defaultSwaggerPathProvider.getRequestMappingEndpoint(requestMappingPattern);
}
public void setDefaultSwaggerPathProvider(SwaggerPathProvider defaultSwaggerPathProvider) {
this.defaultSwaggerPathProvider = defaultSwaggerPathProvider;
}
}
Also, there is a property file in resources folder which contains:
app.docs=http://localhost:8080
When I am hitting "http://localhost:8080/api-docs" it neither gives any result nor any error, On google Rest the response code is 404.
Please help me on this.
The version that you're using (0.8.2) is a very old version of springfox. You should try and move to the latest released version, which is 2.0.
To answer your questions specifically.
Move to the most recent pre-2.0 version. Change the version of swagger-spingmvc in your pom to 1.0.2
The swagger configuration is vastly simplified in later releases. Change your SwaggerConfig to look like this.
#Configuration
//Hard to tell without seeing all your configuration, but optionally,
//add EnableWebMvc annotation in case its not working
#EnableWebMvc
#EnableSwagger
//Assuming your controllers are in this package
#ComponentScan(basePackages = "com.ucap.swagger")
public class SwaggerConfig {
public static final List<String> DEFAULT_INCLUDE_PATTERNS
= Arrays.asList("/news/.*");
//Unless you specifically want this group, I would recommend ignoring this
public static final String SWAGGER_GROUP = "mobile-api";
#Autowired
private SpringSwaggerConfig springSwaggerConfig;
#Bean
public SwaggerSpringMvcPlugin customImplementation(){
return new SwaggerSpringMvcPlugin(this.springSwaggerConfig)
.includePatterns(DEFAULT_INCLUDE_PATTERNS);
}
}
You don't need your path provider any more.
You no longer need the property file

Returning JSON from RESTful Java server code?

I've inherited a web project that a contractor started. I and my coworkers are unfamiliar with the technology used, and have a number of questions. From what we can tell, this appears to be some sort of RESTful Java server code, but my understanding is there are lots of different types of Java RESTful services. Which one is this? Specific questions:
1) Where can we read more (particularly introductory information) about this specific service?
2) The code creates and returns a JSON through some kind of "magic"... I merely return a model class (code below) that has getter and setter methods for its fields, and it's automagically converted into a JSON. I'd like to learn more about how this is done automagically.
3) We already have some code that creates a JSON. We need to return this using this framework. If I already have a JSON, how do I return that? I tried something like this:
String testJSON = "{\"menu\": {\"id\": \"file\", \"value\": \"Hello there\"}}";
return testJSON;
instead of returning a model object with getters/setters, but this returns a literal text string, not a JSON. Is there a way to return an actual JSON that's already a JSON string, and have it be sent as a JSON?
You don't have to be able to answer all of the questions above. Any/all pointers in a helpful direction appreciated!
CODE
First, the view controller that returns the JSON:
package com.aimcloud.server;
import com.aimcloud.util.MySqlConnection;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.FormParam;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.aimcloud.models.SubscriptionTierModel;
#Path("subscription_tier")
public class SubscriptionTierController
{
// this method will return a list of subscription_tier table entries that are currently active
#GET
#Produces({ MediaType.APPLICATION_JSON })
public String/*ArrayList<SubscriptionTierModel>*/ getSubscriptionTiers(#QueryParam("includeActiveOnly") Boolean includeActiveOnly)
{
MySqlConnection mysql = MySqlConnection.getConnection();
ArrayList<SubscriptionTierModel> subscriptionTierArray = new ArrayList<SubscriptionTierModel>();
String queryString;
if (includeActiveOnly)
queryString = "SELECT * FROM subscription_tier WHERE active=1";
else
queryString = "SELECT * FROM subscription_tier";
List<Map<String, Object>> resultList = mysql.query(queryString, null);
for (Map<String, Object> subscriptionRow : resultList)
subscriptionTierArray.add( new SubscriptionTierModel(subscriptionRow) );
// String testJSON = "{\"menu\": {\"id\": \"file\", \"value\": \"Hello there\"}}";
// return testJSON;
return subscriptionTierArray;
}
}
Next, the model the code above returns:
package com.aimcloud.models;
// NOTE this does NOT import Globals
import java.sql.Types;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.json.JSONObject;
import com.aimcloud.util.LoggingUtils;
public class SubscriptionTierModel extends ModelPrototype
{
private String name;
private Integer num_studies;
private Integer cost_viewing;
private Integer cost_processing;
private Integer active;
protected void setupFields()
{
this.fields.add("name");
this.fields.add("num_studies");
this.fields.add("cost_viewing");
this.fields.add("cost_processing");
this.fields.add("active");
}
public SubscriptionTierModel()
{
super("subscription");
this.setupFields();
}
public SubscriptionTierModel(Map<String, Object> map)
{
super("subscription");
this.setupFields();
this.initFromMap(map);
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setNum_Studies(Integer num_studies) {
this.num_studies = num_studies;
}
public Integer getNum_studies() {
return this.num_studies;
}
public void setCost_viewing(Integer cost_viewing) {
this.cost_viewing = cost_viewing;
}
public Integer getCost_viewing() {
return this.cost_viewing;
}
public void setCost_processing(Integer cost_processing) {
this.cost_processing = cost_processing;
}
public Integer getCost_processing() {
return this.cost_processing;
}
public void setActive(Integer active) {
this.active = active;
}
public Integer getActive() {
return this.active;
}
}
public abstract class ModelPrototype {
protected MySqlConnection mysql;
protected ArrayList<String> fields;
protected String table;
protected Integer id = null;
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
abstract protected void setupFields();
public ModelPrototype() {
mysql = MySqlConnection.getConnection();
this.fields = new ArrayList<String>();
this.fields.add("id");
}
public void initFromDbResult(List<Map<String, Object>> result) {
if (result.size() >= 1)
{
Map<String, Object> userRow = result.get(0);
this.initFromMap(userRow);
if (result.size() > 1)
{
Thread.dumpStack();
}
}
else
{
throw new WebApplicationException(ServerUtils.generateResponse(Response.Status.NOT_FOUND, "resource not found"));
}
}
protected void initFromMap(Map<String, Object> map) {
for (Map.Entry<String, Object> entry : map.entrySet()) {
Object value = entry.getValue();
// LoggingUtils.log(entry.getKey() + " " + entry.getValue().toString());
if (value != null && this.fields.contains(entry.getKey())) {
this.setField(entry.getKey(), value);
}
}
}
....
1) Where can we read more (particularly introductory information)
about this specific service?
This is a RESTful service that uses basic jax-rs annotations to build the service. I suggest looking at a tutorial like "REST using jersey" or "REST using CXF".
2) The code creates and returns a JSON through some kind of "magic"...
The restful framework used usually takes care of this. #Produces({ MediaType.APPLICATION_JSON }) annotation indicates the framework to do this conversion.This will be defined somewhere in the configuration. Check the spring config files if you are using spring to define the beans. Usually a mapper or a provider will be defined that converts the object to json.
3) We already have some code that creates a JSON. We need to return this using this framework. If I already have a JSON, how do I return that? I tried something like this:
If you already have a json just return that json from the method. Remember to still have the #Produces({ MediaType.APPLICATION_JSON }) annotation on the method.
but this returns a literal text string, not a JSON
A json is a string. That is what you will see in the response, unless you deserialize it back to an object.
I suggest you read up on JAX-RS, the Java specification for RESTful web services. All of the "javax.ws.rs.*" classes/annotations come from JAX-RS
As JAX-RS, is just a specification, there needs to be something that implements the spec. There is probably a third-party, JAX-RS component that is used to run this service. Jersey in one popular implementation. Apache CXF is another.
Now back to JAX-RS. When you read up on this, you will see that the annotations on your class determine the REST characteristics of your service. For example,
#Path("subscription_tier")
defines your class as the resource with URI BASE_PATH/subscription_tier, where BASE_PATH is propbably defined in a configuration file for your web service framework.
As for how the objects are "automagically" converted into a JSON response: that is the role of the web service framework as well. It probably uses some kind of standard object-to-JSON mapping to accomplish this. (I have worked with CXF and XML resources. In that case JAXB was the mapping mechanism). This is a good thing, as the web service developer does not have to worry about this mapping, and can focus on coding just the implementation of service itself.

External #EJB injection return null with RESTeasy and JBoss

I'm developing a RESTful Web Service on JBoss 6 Final with RESTeasy.
I have an external EJB and I want inject EJB on Web Service.
This is the code of EJB
BeanLocalInterface.java
#Local
public interface BeanLocalInterface {
public String sayHello();
}
Bean.java
#Stateless
#LocalBinding(jndiBinding = "BeanLocal")
public class Bean implements BeanLocalInterface {
#Override
public String sayHello() {
return "Hello!";
}
}
In another project I have a WS:
#Path("/ws")
public class HelloWorldResource {
#EJB(mappedName="BeanLocal")
private BeanLocalInterface bean;
#GET
#Path("/hello")
#Produces(MediaType.TEXT_PLAIN)
public String sayHello() {
return bean.sayHello();
}
}
MyRESTApplication.java
public class MyRESTApplication extends Application {
private Set<Object> singletons = new HashSet<Object>();
private Set<Class<?>> empty = new HashSet<Class<?>>();
public MyRESTApplication(){
singletons.add(new HelloWorldResource());
}
#Override
public Set<Class<?>> getClasses() {
return empty;
}
#Override
public Set<Object> getSingletons() {
return singletons;
}
}
bean is alwasy null!
I have tried this solution:
I have put #Stateless on HelloWorldResources
I have create beans.xml in WEB-INF
I have change MyRESTApplication with
#ApplicationPath("wsapp")
public class MyRESTApplication extends Application {
}
Can you help me?
PS: I don't have EAR e I don't want use it
I have managed to solve this. Firstly, remove all settings from web.xml regarding RESTeasy. You only need one adnotation --> #ApplicationPath
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("api")
public class MyRESTApplication extends Application {
//nothing required here, leave this empty
}
This is your session bean interface.
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("MyEJB")
public interface BeanInterface {
#Path("{username}")
#GET
#Produces(MediaType.TEXT_PLAIN)
public String sayHello(#PathParam("username") String username);
}
This is your session bean.
import javax.ejb.Stateless;
#Stateless
public class EJB implements BeanInterface{
#Override
public String sayHello(String username) {
return "Hello, "+username;
}
}
With JBOSS 7.1
Usage: http:// localhost:8080 /YOURAPPNAME/api/MyEJB/Fabio
Output:Hello, Fabio
Hope this helps.

GlassFish exception

Im quite new to all this stuff. I try to launch a webservice via GlassFish. When i try to build this project i get an error.
ant -f /home/philipp/NetBeansProjects/sks3 -DforceRedeploy=false -Ddirectory.deployment.supported=true -Dnb.wait.for.caches=true run
init:
deps-module-jar:
deps-ear-jar:
deps-jar:
check-rest-config-props:
generate-rest-config:
library-inclusion-in-archive:
library-inclusion-in-manifest:
compile:
compile-jsps:
In-place deployment at /home/philipp/NetBeansProjects/sks3/build/web
Initializing...
deploy?DEFAULT=/home/philipp/NetBeansProjects/sks3/build/web&name=sks3&contextroot=/sks3&force=true failed on GlassFish Server 3.1.2
Error occurred during deployment: Exception while deploying the app [sks3] : Invalid TYPE-level #EJB with name() = [] and beanInterface = [class java.lang.Object] in class Webservice.MeasurementResources. Each TYPE-level #EJB must specify both name() and beanInterface().at org.glassfish.apf.AnnotationInfo#3b63118a. Please see server.log for more details.
/home/philipp/NetBeansProjects/sks3/nbproject/build-impl.xml:1028: The module has not been deployed.
See the server log for details.
BUILD FAILED (total time: 6 seconds)
I dont have a clue what is going wrong but according to the message it has to be in the file MeasurementResurces.java ...
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package Webservice;
import Exception.DALException;
import dal.MeasurementDao;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.Path;
import repo.Measurement;
/**
*
* #author philipp
*/
//#Stateless
//#inject
#EJB
//#LocalBean
#Named
#Path("Measurement")
public class MeasurementResources {
#Inject
MeasurementDao mDao;
public void add(Measurement arg) throws DALException{
mDao.save(arg);
}
/* public void getAll(Measurement arg) throws DALException{
mDao.getAll();
}
*/
}
Someone has at least a hint whats the problem?
You are using a Type-Level EJB without declaring name and beanInterface.
/**
*
* #author philipp
*/
//#Stateless
//#inject
#EJB(name="MyEjb", beanInterface=RemoteEjb.class)
//#LocalBean
#Named
#Path("Measurement")
public class MeasurementResources {
#Inject
MeasurementDao mDao;
public void add(Measurement arg) throws DALException{
mDao.save(arg);
}
}
#Remote
public interface RemoteEjb {
public void doSomething();
}
#Stateless
public class MyEjb implements RemoteEjb {
...
}
name is the name of the EJB you trying to inject. beanInterface is the Local or Remote interface. It's not a real injection. It is a way to use annotation as a replacement of deployment descriptor ejb-ref element. You should use a JNDI lookup in order to inject the ejb.
I don't know what are you trying to do but the common way to inject an ejb is the following:
#Named
#Path("Measurement")
public class MeasurementResources {
#EJB
private MyEjb myejb;
#Inject
MeasurementDao mDao;
public void add(Measurement arg) throws DALException{
mDao.save(arg);
}
...
}