HTTP Basic Authentication in Restlet with a JAXRS Application? - rest

I'm trying to authenticate access to all resources on my server via HTTP Basic authentication. Currently, my setup looks like this when starting the server:
this.component = new Component();
this.server = this.component.getServers().add(Protocol.HTTP, 8118);
JaxRsApplication application = new JaxRsApplication(component.getContext()
.createChildContext());
application.add(new RestletApplication());
ChallengeAuthenticator authenticator = new ChallengeAuthenticator(
this.component.getContext(),
ChallengeScheme.HTTP_BASIC, "test");
authenticator.setVerifier(new ApplicationVerifier());
this.component.getDefaultHost().attachDefault(authenticator);
this.component.getDefaultHost().attach(application);
this.component.start();
Here's my RestletApplication:
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
public class RestletApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(TestResource.class);
return classes;
}
}
Here's my ApplicationVerifier:
import java.util.HashMap;
import java.util.Map;
import org.restlet.security.LocalVerifier;
public class ApplicationVerifier extends LocalVerifier {
private Map<String, char[]> localSecrets = new HashMap<String, char[]>();
public ApplicationVerifier() {
this.localSecrets.put("username", "password".toCharArray());
}
#Override
public char[] getLocalSecret(String key) {
if (this.localSecrets.containsKey(key))
return this.localSecrets.get(key);
return null;
}
}
Finally, here's my TestResource:
import java.util.*;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
#Path("test")
public class TestResource {
#GET
#Path("list")
public TestList getTestList() {
return makeTestList();
}
}
However, I'm not seeing any prompt or requirement for authentication when I try to access the resource. What am I doing wrong? I'm not having any issues with marshalling and unmarshalling items and I'm sure that my resource is getting hit with requests. What am I not doing right?

According to the JavaDocs for JaxRsApplication, an authenticator can be set using the following code before starting things up:
((JaxRsApplication)application).setGuard((Authenticator)authenticator);
Do that, and all requests will fly through your authenticator :)

Related

how avoid to access to other data users. Spring boot + MongoDB

I'm developing a web application with Spring Boot and MongoDB. I'm following the MVC model.
I have a view which shows a list of stored data, but the app ignores the logged user and shows every objects.
https://i.stack.imgur.com/zl7TC.png
Here, the first row was added by another user, but it's showed anyway.
How could I get only the object allowed to the authenticated user?.
The only way I can see is checking the user Id after each query and get only the object of the given user. I think that there should be a better way to do this.
The code is the following:
Entity
import java.io.Serializable;
import java.util.Collection;
import java.util.Set;
import org.springframework.data.mongodb.core.index.IndexDirection;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.DBRef;
import org.springframework.data.mongodb.core.mapping.Document;
#Document(collection = "trackings")
public class Tracking extends Entity implements Serializable {
private static final long serialVersionUID = -1249902722123443448L;
#Indexed(unique = true, direction = IndexDirection.DESCENDING)
private String trackingName;
private String SoftwareName;
#DBRef
private Set<Alarm> alarms;
public String getTrackingName() {
return trackingName;
}
public void setTrackingName(String trackingName) {
this.trackingName = trackingName;
}
public String getSoftwareName() {
return SoftwareName;
}
public void setSoftwareName(String softwareName) {
SoftwareName = softwareName;
}
public Collection<Alarm> getAlarms() {
return alarms;
}
public void setAlarms(Set<Alarm> alarms) {
this.alarms = alarms;
}
}
Repository
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
import us.etsii.fvt.domains.Tracking;
#Repository
public interface TrackingRepository extends MongoRepository<Tracking, String>{
Tracking findByTrackingName(String name);
}
Controller
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import us.etsii.fvt.domains.Alarm;
import us.etsii.fvt.domains.Tracking;
import us.etsii.fvt.domains.User;
import us.etsii.fvt.services.TrackingService;
import us.etsii.fvt.services.UserService;
#Controller
public class TrackingController {
#Autowired
private UserService userService;
#Autowired
private TrackingService trackingService;
#RequestMapping(value = { "/tracking" }, method = RequestMethod.GET)
public ModelAndView tracking() {
ModelAndView modelAndView = new ModelAndView();
// AƱadimos el usuario al modelo
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
User user = userService.findUserByEmail(auth.getName());
modelAndView.addObject("currentUser", user);
modelAndView.addObject("fullName", user.getFullname());
// AƱadimos la lista de trackings al modelo
List<Tracking> trackings = trackingService.findAll();
modelAndView.addObject("trackings", trackings);
// Devolvemos el modelo
modelAndView.setViewName("tracking");
return modelAndView;
}
...
}
Service
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import us.etsii.fvt.domains.Tracking;
import us.etsii.fvt.repositories.TrackingRepository;
#Service
public class TrackingService {
#Autowired
private TrackingRepository trackingRepository;
public Tracking findTrackingByName(String name) {
return trackingRepository.findByTrackingName(name);
}
public void saveTracking(Tracking tracking) {
trackingRepository.save(tracking);
}
public List<Tracking> findAll() {
return trackingRepository.findAll();
}
public Tracking findById(String id) {
Optional<Tracking> t = trackingRepository.findById(id);
if(!t.isPresent()) {
return null;
}
return t.get();
}
public void remove(String id) {
trackingRepository.deleteById(id);
}
}
There are ambiguous points in your question but assuming you have an User Entity:
You should get the logged in user from Spring Security
You should include a relation of User Entity to Tracking Entity (include User ID information in Tracking records)
Then you should query the mongo db Tracking Entity with the given user id.
You can use standard query by field functionality of Spring Repository.

Facing HTTP 415 Unsupported Media Type from JAX-RS client when using MessageBodyReader

I am new to RESTFul wit JAX-RS and learning. I am facing problem only when i request from JAX-RS client application. Its working fine from post plugin. But when i am changing the #Consumes("myformat/xml") with "application/xml" then its working. Below is the code.
MessageBodyReader:
package com.memorynotfound.jaxrs.chunked;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import javax.ws.rs.Consumes;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.Provider;
#Provider
#Consumes("myformat/xml")
public class UserMessageBodyReader implements MessageBodyReader<User> {
public boolean isReadable(Class<?> arg0, Type arg1, Annotation[] arg2, MediaType arg3) {
if (arg0.equals(User.class))
return true;
else
return false;
}
public User readFrom(Class<User> arg0, Type arg1, Annotation[] arg2, MediaType arg3,
MultivaluedMap<String, String> arg4, InputStream arg5) throws IOException, WebApplicationException {
return new User(1, "Jphn Doe");
}
}
Resource:
package com.memorynotfound.jaxrs.chunked;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
#Path("/users")
public class UserResource {
#POST
#Consumes("myformat/xml")
public User getUser(User user) {
return user;
}
}
Client code:
package com.restfulexample.client.messagebodyreader;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
public class MessageBodyReader {
public static void main(String[] args) {
Client client = ClientBuilder.newClient();
User user = new User(1, "Jphn Doe");
User postedUser = client.target("http://localhost:9090/message-body-reader/api/users").request("myformat/xml")
.post(Entity.xml(user), User.class);
System.out.println(postedUser.getId() + " " + postedUser.getName());
}
}
Found the solution with the below code...
Client client = ClientBuilder.newClient().register(UserMessageBodyReader.class)
.register(UserMessageBodyWriter.class);
We have to register both MessageBodyReader and Writer with the client.

Spring Security 403 http status

I am implementing Spring Security on a Spring Boot 2.0.1 project.
I have some web services that used to work fine before Spring Security implementation. But now, they don't.
This is the error message displayed in REST client.
{
"timestamp": "2018-07-27T11:14:40.080+0000",
"status": 403,
"error": "Forbidden",
"message": "Access Denied",
"path": "/lsm/notification/getCurrentUserNotifications"
}
and the same error on google chrome :
Below is the controller listing the services:
package com.sap.lsm.web;
import java.util.List;
import java.util.Random;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.sap.lsm.dao.NotifiedUserRepository;
import com.sap.lsm.dao.UserNotificationRepository;
import com.sap.lsm.entities.NotifiedUser;
import com.sap.lsm.entities.UserNotification;
import com.sap.lsm.service.UserNotificationService;
#RestController
public class UserNotificationController {
#Autowired
private UserNotificationService userNotificationService;
#Autowired
private UserNotificationRepository userNotificationRepository;
#RequestMapping(value="/notification/getCurrentUserNotifications", method=RequestMethod.GET)
public List<UserNotification> getCurrentUserNotifs() {
return userNotificationService.getCurrentUserAllNotifications();
}
#RequestMapping(value="/notification/getCurrentUserNotSeenNotifications", method=RequestMethod.GET)
public List<UserNotification> getCurrentUserNotSeenNotifs() {
return userNotificationService.getCurrentUserNotSeenNotifications();
}
#RequestMapping(value="/notification/deleteNotification/{id}", method=RequestMethod.DELETE)
public void deleteNotification(#PathVariable("id") Long id){
userNotificationService.deleteNotification(id);
}
#RequestMapping(value="/notification/getNotification/{id}", method=RequestMethod.GET)
public UserNotification getNotification(#PathVariable("id") Long id) {
UserNotification notification = this.userNotificationService.getNotification(id);
if(!notification.equals(null)) {
notification.setStatus("seen");
userNotificationRepository.save(notification);
}
return notification;
}
#RequestMapping(value="/notification/markCurrentUserNotificationsAsSeen", method=RequestMethod.GET)
public void markCurrentUserNotificationsAsSeen() {
userNotificationService.markAllNotificationsAsSeen();
}
}
And this is the Spring Security Config :
package com.sap.lsm.config;
import javax.servlet.Filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.channel.ChannelProcessingFilter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
#EnableGlobalMethodSecurity(prePostEnabled=true)
#EnableWebSecurity
#Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private RequestFilter requestFilter;
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
public SpringSecurityConfig(UserDetailsService userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder) {
this.userDetailsService = userDetailsService;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
public void setUserDetailsService(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
public void setbCryptPasswordEncoder(BCryptPasswordEncoder bCryptPasswordEncoder) {
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.cors()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.logout().deleteCookies("JSESSIONID").invalidateHttpSession(true)
.and()
.authorizeRequests()
.antMatchers("/lsm/listCustomers").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/addCustomer").hasAnyAuthority("CONSULTANT")
.antMatchers("/lsm/getAllCustomers").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/getOldCustomers").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/getCustomers").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/getCustomer/*").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/deleteCustomer/*").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/cancelCustomer/*").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/restoreCustomer/*").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/updateCustomer/*").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/getLSMUsers").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/addLSMUser").hasAnyAuthority("ADMIN")
.antMatchers("/lsm/getLSMUser/*").hasAnyAuthority("ADMIN")
.antMatchers("/lsm/deleteLSMUser/*").hasAnyAuthority("ADMIN")
.antMatchers("/lsm/cancelLSMUser/*").hasAnyAuthority("ADMIN")
.antMatchers("/lsm/restoreLSMUser/*").hasAnyAuthority("ADMIN")
.antMatchers("/lsm/updateLSMUser/*").hasAnyAuthority("ADMIN")
.antMatchers("/lsm/notification/getCurrentUserNotifications/*").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/notification/getCurrentUserNotSeenNotifications/*").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/notification/deleteNotification/*").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/notification/getNotification/*").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/lsm/notification/markCurrentUserNotificationsAsSeen/*").hasAnyAuthority("ADMIN","CONSULTANT")
.antMatchers("/assets/**","/login","/*").permitAll()
.and()
.authorizeRequests().anyRequest().authenticated()
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
.addFilterBefore((Filter) new JWTAuthorizationFilter(),UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(requestFilter, ChannelProcessingFilter.class);
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
}
If you need JWT authentication and authorization filters, i'll post them later on .
Please help me,
Thanks
** update **
The role of the connected user is ADMIN.
The path /lsm is declared as property in the pom.xml as follows:
<m2eclipse.wtp.contextRoot>/lsm</m2eclipse.wtp.contextRoot>
This root path is used to run the application under Jenkins (integration server)

swagger documentation for hybris

I need to generate rest api documentation using swagger for hybris.
I got Kongchan's sample pom.xml, but I couldn't really modify to match with hybris code. Can anyone pls provide me sample pom.xml for hybris or any links or documents.
Find the Wiki for generating Hybris API Documentation with Swagger
Edit:
You can follow spring-xml-swagger example to integrate it with Hybris using XML configuration. Also, this and this posts will help you.
Here is the class I use for OCC (tested on hybris 6.6)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* #author ajaninmanificat Spring configuration for swagger. Only available if spring profile "swagger" is enabled.
*
*/
#Configuration
#EnableSwagger2
#Profile("swagger")
public class SwaggerConfig extends WebMvcConfigurationSupport
{
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry)
{
registry.addResourceHandler("**/swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
#Bean
public Docket api()
{
final ApiInfo apiInfo = new ApiInfoBuilder().title("OCC API documentation")
.description("This document contains the generated API documentation for Omni Commerce Connect v2.")
.version("Version v2").build();
return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.any()).paths(PathSelectors.any())
.build().apiInfo(apiInfo).useDefaultResponseMessages(false).enableUrlTemplating(true);
}
}
To enable Swagger you have to set this property : spring.profiles.active=swagger. The idea is to prevent Swagger from being loaded in production.
To avoid any troubles with BaseSiteMatchingFilter I suggest to create a subclass IgnorableBaseSiteMatchingFilter
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class IgnorableBaseSiteMatchingFilter extends BaseSiteMatchingFilter
{
private String regexpIgnore;
#Override
protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response,
final FilterChain filterChain) throws ServletException, IOException
{
final boolean shouldIgnore = (regexpIgnore != null) && matchesUrl(request, regexpIgnore);
if (shouldIgnore)
{
filterChain.doFilter(request, response);
}
else
{
// Is not ignored, call the real stuff
super.doFilterInternal(request, response, filterChain);
}
}
public void setRegexpIgnore(final String regexpIgnore)
{
this.regexpIgnore = regexpIgnore;
}
}
And the bean declaration looks like this :
<alias alias="baseSiteMatchingFilter" name="myBaseSiteMatchingFilter" />
<bean id="myBaseSiteMatchingFilter" class="mypackage.IgnorableBaseSiteMatchingFilter" parent="defaultBaseSiteMatchingFilter">
<property name="regexpIgnore" value="(swagger|api-docs|info|login|logout|/health/|/css/|/img/|/js/|/font-awesome/|/bootstrap/|/assets/|/node_modules/)" />
</bean>

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.