I tried working on it. But,not able to figure out the issue since I'm quite new to this. I have attached several screenshots to see the issue I'm facing right now.
#Path("/emp")
public class EmployeeService {
#GET
#Path("/emp/{empID}")
#Produces(MediaType.APPLICATION_XML)
public Employee getEmployee(#PathParam(value = "empID") String empID) {
Employee employee = new Employee();
employee.setEmailId(empID);
employee.setName("Rony John");
employee.setEmailId("rony.java#gmail.com");
return employee;
}
#POST
#Path("/create")
#Consumes(MediaType.APPLICATION_XML)
#Produces(MediaType.APPLICATION_XML)
public Employee createEmployee(Employee employee) {
// Create logic
return employee;
}
#POST
#Path("/update")
#Consumes(MediaType.APPLICATION_XML)
#Produces(MediaType.APPLICATION_XML)
public Employee updateEmployee(Employee employee) {
employee.setName(employee.getName() + " updated");
return employee;
}
#DELETE
#Path("/delete/{empID}")
public Response deleteEmployee(#PathParam(value = "empID") String empID) {
return Response.status(200)
.entity("Employee with " + empID + " is deleted successfully.")
.build();
}
}
The lack of providers is not relevant, it just means you don't have any.
You have an index.jsp, but if you mapped the Jersey filter at the context root (/), it's rightfully saying there's no resource there - based on your screenshots you only have one resource, starting at /emp which has sub-resources for the CRUD operations at deeper paths.
Edit: On second look, your index.jsp is in WEB-INF. I don't think it should be based on the fact you appear to be trying to get a simple example together.
So, what do you expect to see at /JerseyRESTCRUD/?
Related
I'm using the following code in my startup class to prevent errors serializing my entities which may cause circular references, but it is not working.
Why?
public partial class Startup
{
public static void ConfigureMobileApp(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
new MobileAppConfiguration()
.UseDefaultConfiguration()
.ApplyTo(config);
config.MapHttpAttributeRoutes();
// Use Entity Framework Code First to create database tables based on your DbContext
Database.SetInitializer(new MobileServiceInitializer());
MobileAppSettingsDictionary settings = config.GetMobileAppSettingsProvider().GetMobileAppSettings();
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
config.Services.Add(typeof(IExceptionLogger), new AiExceptionLogger());
if (string.IsNullOrEmpty(settings.HostName))
{
app.UseAppServiceAuthentication(new AppServiceAuthenticationOptions
{
// This middleware is intended to be used locally for debugging. By default, HostName will
// only have a value when running in an App Service application.
SigningKey = ConfigurationManager.AppSettings["SigningKey"],
ValidAudiences = new[] { ConfigurationManager.AppSettings["ValidAudience"] },
ValidIssuers = new[] { ConfigurationManager.AppSettings["ValidIssuer"] },
TokenHandler = config.GetAppServiceTokenHandler()
});
}
app.UseWebApi(config);
}
}
According to your description, I created my Azure Mobile App project to test this issue. Based on your Startup.cs, I added my apiController as follows:
[MobileAppController]
public class ValuesController : ApiController
{
[Route("api/values")]
public HttpResponseMessage Get()
{
Department sales = new Department() { Name = "Sales" };
Employee alice = new Employee() { Name = "Alice", Department = sales };
sales.Manager = alice;
return Request.CreateResponse(sales);
}
}
public class Employee
{
public string Name { get; set; }
//[JsonIgnore]
public Department Department { get; set; }
}
public class Department
{
public string Name { get; set; }
public Employee Manager { get; set; }
}
When access this endpoint, I encountered the following XML Circular Object References error:
Note: For a simple way, I removed the XML Formatter via config.Formatters.Remove(config.Formatters.XmlFormatter);. Also, you could refer to the section about preserving object references in XML from Handling Circular Object References.
After I removed XML Formatter, then I encountered the following error about object references loop in JSON:
Then, I followed this Loop Reference handling in Web API code sample, but without luck in the end. Also, I tried to create a new Web API project and found that ReferenceLoopHandling.Ignore could work as expected.
In the end, I found that if I remove the MobileAppController attribute from my
apiController, then it could work as follows:
In summary, I assumed that you could try to ignore the reference attributes with the JsonIgnore for JSON.NET, for more details you could refer to fix 3:Ignore and preserve reference attributes.
I am trying to make a RESTful application in Java using Spring boot by following the tutorial here. I want to modify it so that I can extract an identifier from the URL and use it to serve requests.
So http://localhost:8080/members/<memberId> should serve me a JSON object with information about the member whose ID is <memberId>. I don't know how to
Map all http://localhost:8080/members/* to a single controller.
Extract the from the URL.
Should the logic of extracting the memberId and using it be part of the controller or a separate class, as per the MVC architecture?
I am new to Spring/Spring-boot/MVC. It is quite confusing to get started with. So please bear with my newbie questions.
Map all http://localhost:8080/members/* to a single controller.
You can use a placeholder in a request mapping to so it'll handle multiple URLs. For example:
#RequestMapping("/members/{id}")
Extract the id from the URL
You can have the value of a placeholder injected into your controller method using the #PathVariable annotation with a value that matches the name of the placeholder, "id" in this case:
#RequestMapping("/members/{id}")
public Member getMember(#PathVariable("id") long id) {
// Look up and return the member with the matching id
}
Should the logic of extracting the memberId and using it be part of the controller or a separate class, as per the MVC architecture?
You should let Spring MVC extract the member id from the URL as shown above. As for using it, you'll probably pass the URL to some sort of repository or service class that offers a findById method.
As you can see in the code below, service for customer are in one controller to get one and to add new customer.
So, you will have 2 services:
http://localhost:8080/customer/
http://localhost:8080/customer/{id}
#RestController("customer")
public class SampleController {
#RequestMapping(value = "/{id}", method = RequestMethod.GET)
public Customer greetings(#PathVariable("id") Long id) {
Customer customer = new Customer();
customer.setName("Eddu");
customer.setLastname("Melendez");
return customer;
}
#RequestMapping(value = "/{id}", method = RequestMethod.POST)
public void add(#RequestBody Customer customer) {
}
class Customer implements Serializable {
private String name;
private String lastname;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getLastname() {
return lastname;
}
}
}
New to Jersey(REST Framework for Java) and I'm trying to setup two resources, in two separate classes that share a root path, and I'm having a problem.
So, I have something like:
#Path("/users")
public class User extends RestSupport {
#GET
#Path("/{user_uuid}")
public String get(#PathParam("user_uuid") String uuid) {
return "Hello User " + uuid;
}
}
The above class works. However, I want to create a child resource in a separate class. But when I do this, it seems to create a URI naming conflict. So, here, I want to get all the pets for a particular users
#Path("/users")
public class Pets extends RestSupport {
#GET
#Path("/{user_uuid}/pets")
public String get(#PathParam("user_uuid") String uuid) {
return "Hello Pets " + uuid;
}
}
These top-level resources have lots of child resources, so I'm looking for the best way to organize them. Any help would be appreciated.
Change the path of Pets class from #Path("/users")to#Path("/users/{user_uuid}/pets")
Don't add the HTTP annotation #GET on your Users root resource method if you want Jersey to delegate calls to a child resource. Consider a User class:
public class User {
String uuid;
User(String id) { this.uuid = id; }
#GET
public String get() { return "Hello user " + uuid; }
#GET
#Path("/pets")
public String getPets() { return "Hello pets " + uuid; }
}
and then adjust your Users resource:
#Path("/users")
public class Users {
#Path("/{user_uuid}")
public User get(#PathParam("user_uuid") String uuid) {
// Get the user from the DAO here...
return new User(uuid);
}
}
https://graph.facebook.com/me/accounts?access_token=USERS_AUTH_TOKEN
returns a list of pages the user has admin status in (in JSON format).
I would like to list all the pages in a dropdownlist, and make the user choose which facebook page he wants to use (on my webapp), so I can obtain the specific access token for that facebook page.
My question is - whats the easiest and best way to do that. Ive never worked with JSON before, but I guess theres a pretty easy was to do this through the facebook-sdk.
Since you're using the C# SDK, just take the array of objects and convert them into a IList<IDictionary>() array using the pageId as the key and the value being the page name.
This is not fully compilable, but you get the idea:
private void IList<IDictionary<long,string>> ConvertToList(dynamic meAccounts)
{
foreach(var acc in meAccounts.data)
{
yield return new Dictionary((long)acc.id, (string)acc.name);
}
{
Okay figured out a way to do it. But I have no idea ifs the right way or the most optimal.
Would very much like inputs on it.
[DataContract]
internal class FacebookObj
{
[DataMember]
public List<FacebookAccount> data;
[DataMember]
public FacebookNext paging;
}
[DataContract]
internal class FacebookAccount
{
[DataMember]
public string name;
[DataMember]
public string category;
[DataMember]
public string id;
[DataMember]
public string access_token;
}
[DataContract]
internal class FacebookNext
{
[DataMember]
public string next;
}
public void ShowPages(string authToken) {
WebRequest webRequest = WebRequest.Create("https://graph.facebook.com/me/accounts?access_token=" + authToken);
WebResponse webResponse = webRequest.GetResponse();
Stream sr = webResponse.GetResponseStream();
if (sr != null)
{
jsonSer = new DataContractJsonSerializer(typeof(FacebookObj));
FacebookObj o = (FacebookObj)jsonSer.ReadObject(sr2);
foreach (FacebookAccount s in o.data)
{
//Do stuff
Response.Write(s.id + " - " + s.name + "<br />");
}
}
}
I'm using EF4 with POCO objects the 2 tables are as follows
Service
ServiceID,
Name,
StatusID
Status
StatusID,
Name
The POCO objects look like this
Service
ServiceID,
Status,
Name
Status
StatusID,
Name
With Status on the Service object being a Navigation Property and of type Status.
In my Service Repository I have a save method that takes a service objects attaches it to the context and calls save. This works fine for the service, but if the status for that service has been changed it does not get updated. My Save method looks like this
public static void SaveService(Service service)
{
using (var ctx = Context.CreateContext())
{
ctx.AttachModify("Services", service);
ctx.AttachTo("Statuses",service.Status);
ctx.SaveChanges();
}
}
The AttachModify method attaches an object to the context and sets it to modified it looks like this
public void AttachModify(string entitySetName, object entity)
{
if (entity != null)
{
AttachTo(entitySetName, entity);
SetModified(entity);
}
}
public void SetModified(object entity)
{
ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
}
If I look at a SQL profile its not even including the navigation property in the update for the service table, it never touches the StatusID. Its driving me crazy. Any idea what I need to do to force the Navigation Property to update?
Edit
To give a quick example of the problem heres a quick console app that uses EF with my POCO objects to produce this issue
static void Main(string[] args)
{
Service svc = GetService();
Console.WriteLine("Service : " + svc.Name + " , Status : " + svc.Status.Name);
//Change and save Status
svc.Status = GetStatus("Stopped");
using (var ctx = new TestEFContext())
{
//Status is changed
Console.WriteLine("Service : " + svc.Name + " , Status : " + svc.Status.Name);
ctx.AttachModify("Services", svc);
ctx.AttachTo("Statuses", svc.Status);
ctx.SaveChanges();
}
//Re-fetch service from db and check status
svc = GetService();
//Status is set back to its old value!!!!!!!!
Console.WriteLine("Service : " + svc.Name + " , Status : " + svc.Status.Name);
Console.ReadLine();
}
private static Service GetService()
{
using (var ctx = new TestEFContext())
{
return ctx.Services.Include("Status").FirstOrDefault();
}
}
private static Status GetStatus(string name)
{
using (var ctx = new TestEFContext())
{
return ctx.Statuses.Where(n=>n.Name == name).FirstOrDefault();
}
}
public class Service
{
[DataMember] public int ServiceID { get; set; }
[DataMember] public string Name { get; set; }
[DataMember] public Status Status { get; set; }
}
public class Status
{
[DataMember] public int StatusID { get; set; }
[DataMember] public string Name { get; set; }
}
The reason I'm not holding on to the context is because in the real app I'm trying to use this on its all done in WCF in a disconnected way.
This problem was dragging on so I ended up going for a solution I'm not overlly happy with but I just needed to get it working.
My solution was on save to re-fetch the entities from the DB and use ApplyCurrentValues to update them to match the updated POCO objects.
Based on my example in the question this is the solution I used
static void Main(string[] args)
{
Service svc = GetService();
svc.Status = GetStatus("Stopped");
using (var ctx = new TestEFContext())
{
var svc2 = ctx.Services.Where(s=>s.ServiceID == svc.ServiceID).FirstOrDefault();
svc2.Status = ctx.Statuses.Where(n => n.StatusID == svc.Status.StatusID).FirstOrDefault();
ctx.ApplyCurrentValues("Services", svc);
ctx.SaveChanges();
}
}
I really would rather get it working the way it was coded in the question as I think that is a much neater solution so if anyone can improve on this please do
You must manually set state to Modified for each entity you want to update. Attaching entity to context set its state to Unchanged. Also you don't need to attach status separately. It is already attached with service because AttachTo method attaches whole object graph. You can also try to use Attach instead of AttachTo but I don't think it will be source of the problem.