Whenever I am executing a POST request an error "405 method not found" is coming, although I have included a required POST method in it. I don't know why the error is coming.
i had tried a lot, I am not getting what the problem is. Please help me out with the same.
My resource file is :
#Path("/customer")
public class CustomerResource {
CustomerDao service = new CustomerDao();
#GET
#Path("/greet")
public String greetCustomer() {
return "Hello, Welcome to our site !!";
}
#GET
#Path("/{name}")
public String getCustomerByName(#PathParam("name") String name) {
return service.getCustomerByName(name).toString();
}
#GET
#Path("/{firstname}-{lastname}")
public String getCustomerByName(#PathParam("firstname") String first,
#PathParam("lastname") String last) {
Collection<Customer> customerCollection = service.getAllCustomers();
for (Customer customer : customerCollection) {
if (customer.getFirstname().equalsIgnoreCase(first)
&& customer.getLastname().equalsIgnoreCase(last)) {
return customer.toString();
}
}
return "Customer with " + first + " " + last + "not found";
}
#GET
#Path("/range/{start}")
#Produces("text/plain")
public String getCustomersInRange(#QueryParam("start") int start) {
List<Customer> allCustomerList = new ArrayList<Customer>(service.getAllCustomers());
List<Customer> customerListInRange = new ArrayList<Customer>();
if (start < allCustomerList.size()) {
for (int i = start; i < allCustomerList.size(); i++) {
customerListInRange.add(allCustomerList.get(i));
}
return customerListInRange.toString();
} else {
return "No customers in this range";
}
}
#POST
#Path("/add")
#Consumes("application/x-www-form-urlencoded")
public String createCustomer(#FormParam("firstname") String first,
#FormParam("lastname") String last) {
Customer newCustomer = new Customer();
newCustomer.setFirstname(first);
newCustomer.setLastname(last);
service.addCustomer(newCustomer);
return newCustomer.toString();
}
#PUT
#Path("/{id}")
#Produces("text/plain")
#Consumes("application/x-www-form-urlencoded")
public String updateCustomer(#PathParam("id") int id,
#FormParam("firstname") String first,
#FormParam("lastname") String last) {
System.out.println(first + " " + last);
Customer customer = service.updateCustomer(id, first, last);
if (customer != null) {
return "Updated Customer : " + customer.toString();
} else {
return "Customer with this id : " + id + "not found";
}
}
#DELETE
#Path("/{id}")
#Produces("text/plain")
public String deleteCustomer(#PathParam("id") int id) {
Customer customer = service.deleteCustomer(id);
if (customer != null) {
return "Deleted Customer: " + customer.toString();
} else {
return "Customer with id : " + id + "was not found";
}
}
}
And my service file is:
public class CustomerDao {
static private List<Customer> customerList = new ArrayList<Customer>();
static {
customerList.add(new Customer(101, "Roy", "Singh", "roy#gmail.com", "Pune"));
customerList.add(new Customer(102, "Joy", "Jackson", "joy#gmail.com", "Nagpur"));
customerList.add(new Customer(103, "Soy", "Nichol", "soy#gmail.com", "Mumbai"));
customerList.add(new Customer(104, "Toy", "Sim", "toy#gmail.com", "Nasik"));
customerList.add(new Customer(105, "Robin", "Singh", "john#gmail.com", "Nasik"));
}
public Customer getCustomerById(int id) {
for (Customer cust : customerList) {
if (cust.getId() == id) {
return cust;
}
}
return null;
}
public Customer getCustomerByName(String name) {
for (Customer cust : customerList) {
if (cust.getFirstname().equals(name)) {
return cust;
}
}
return null;
}
public List<Customer> getAllCustomers() {
return customerList;
}
public List<Customer> getCustomersByCity(String city) {
List<Customer> customersByCity = new ArrayList<Customer>();
for (Customer cust : customerList) {
if (cust.getCity().equals(city)) {
customersByCity.add(cust);
}
}
return customersByCity;
}
public void addCustomer(Customer cust) {
customerList.add(cust);
}
public Customer updateCustomer(int id, String firstname, String lastname) {
List<Customer> customers = getAllCustomers();
for (Customer customer : customers) {
if (customer.getId() == id) {
customer.setFirstname(firstname);
customer.setLastname(lastname);
return customer;
}
}
return null;
}
public Customer deleteCustomer(int id) {
List<Customer> customers = getAllCustomers();
for (Customer customer : customers) {
if (customer.getId() == id) {
customers.remove(customer);
return customer;
}
}
return null;
}
}
The path am using is :
http://localhost:8080/CustomerServiceApp/rest/customer/add
The error am getting on postman is:
405 method not allowed
The exception occured is:
org.apache.wink.server.internal.registry.ResourceRegistry - The system cannot find any method in the resource.CustomerResource class that supports POST. Verify that a method exists.
org.apache.wink.server.internal.RequestProcessor - The following error occurred during the invocation of the handlers chain: WebApplicationException (405) with message 'null' while processing POST request sent to http://localhost:8080/CustomerServiceApp/rest/customer/add
Related
In my case I need subscribe to TFS events (create/delete team project, workitem, checkin, iteration, areas) for realization some business logic. I based on this manual. Now I can catch only workitem and checkin events, but I need more (team project, iteration, areas). In this list, I did not find the right events.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.TeamFoundation.Common;
using Microsoft.TeamFoundation.Framework.Server;
using Microsoft.TeamFoundation.Integration.Server;
using Microsoft.TeamFoundation.VersionControl.Server;
using Microsoft.TeamFoundation.WorkItemTracking.Server;
public class WorkItemChangedEventHandler : ISubscriber
{
public string Name
{
get { return "WorkItemChangedEventHandler"; }
}
public SubscriberPriority Priority
{
get { return SubscriberPriority.Normal; }
}
public Type[] SubscribedTypes()
{
var types = new List<Type>
{
typeof(Microsoft.TeamFoundation.WorkItemTracking.Server.WorkItemChangedEvent),// working
typeof(Microsoft.TeamFoundation.VersionControl.Server.CheckinNotification),// working
typeof(Microsoft.TeamFoundation.Integration.Server.ProjectCreatedEvent)// NOT working
};
return types.ToArray();
}
public EventNotificationStatus ProcessEvent(TeamFoundationRequestContext requestContext, NotificationType notificationType,
object notificationEventArgs, out int statusCode, out string statusMessage, out ExceptionPropertyCollection properties)
{
statusCode = 0;
properties = null;
statusMessage = String.Empty;
try
{
EventLog.WriteEntry("WorkItemChangedEventHandler", string.Format("Entity: {0} was modified", notificationEventArgs.GetType()));
}
catch (Exception ex)
{
EventLog.WriteEntry("WorkItemChangedEventHandler", ex.Message + ex.StackTrace);
}
return EventNotificationStatus.ActionPermitted;
}
}
I have one class for CheckinNotificationEventHandler:
public class CheckinNotificationEventHandler : ISubscriber
{
public Type[] SubscribedTypes()
{
return new Type[1] { typeof(CheckinNotification) };
}
public EventNotificationStatus ProcessEvent(TeamFoundationRequestContext requestContext, NotificationType notificationType, object notificationEventArgs, out int statusCode, out string statusMessage, out ExceptionPropertyCollection properties)
{
if (notificationType == NotificationType.Notification && notificationEventArgs is CheckinNotification)
{
...
}
return EventNotificationStatus.ActionPermitted;
}
}
and a second class for WorkItemChangedEventHandler:
public class WorkItemChangedEventHandler : ISubscriber
{
public Type[] SubscribedTypes()
{
return new Type[1] { typeof(Microsoft.TeamFoundation.WorkItemTracking.Server.WorkItemChangedEvent) };
}
public EventNotificationStatus ProcessEvent(TeamFoundationRequestContext requestContext, NotificationType notificationType, object notificationEventArgs, out int statusCode, out string statusMessage, out ExceptionPropertyCollection properties)
{
if (notificationType == NotificationType.Notification && notificationEventArgs is WorkItemChangedEvent)
{
...
}
return EventNotificationStatus.ActionPermitted;
}
}
UPDATED: I've taken Chris's answer into account but it didn't help - I'm still facing the issue. I've updated the code below to incorporate Chris's answer. Something to note is that when implementing Chris's suggestion, the relations were persisted but not reflected on the view.xhtml page. I had to replace the db object with the object returned form the call to GenericDao.update().
I've got the following relations:
One Customer to many PurchaseOrders (PO)
One PO to many Invoices.
I've read up on bi-directional relations and I know that if I have a bi-directional relation, I should update both sides of the relation when updating entities.
I perform the following steps:
Create a customer (Customer 1)
Create a purchase order (Order 1) linked to Customer 1
Create an invoice (Invoice 1) linked to Order 1.
What I observe is that all entities and relations are persisted but the list of Customer's Orders is not displayed.
view Customer:
view PurchaseOrder:
DB queries:
> select * from customer;
> +----+------------+
> | ID | NAME |
> +----+------------+
> | 1 | Customer 1 |
> +----+------------+
> 1 row in set (0.00 sec)
>
> mysql> select * from purchaseorder;
> +----+---------+-------------+
> | ID | NAME | customer_id |
> +----+---------+-------------+
> | 1 | Order 1 | 1 |
> +----+---------+-------------+
> 1 row in set (0.00 sec)
>
> mysql> select * from invoice;
> +----+-----------+------------------+
> | ID | NAME | purchaseorder_id |
> +----+-----------+------------------+
> | 1 | Invoice 1 | 1 |
> +----+-----------+------------------+
> 1 row in set (0.00 sec)
The DB reflects the relation between the configured entities so I know my changes are being persisted and, as far as I can tell, I've implemented the Customer-PO relation the same ways as the PO-Invoice relation. Since the list of Invoices for PO is updated correctly, I don't think I have a systemic issue so there must be something different between the implementation of Customers-PO and PO-Invoices relations but I can't spot it.
Why don't I see a list of PO's for my Customer even though there are clearly PO's configured for the customer?
Any help will be appreciated.
Classes(truncated for brevity):
Entities
Customer
private int id; //#Id and #GeneratedValue(IDENTITY) on getter
private String name;
#OneToMany(mappedBy="customer")
private Set<PurchaseOrder> purchaseOrders;
public Customer()
{
purchaseOrders = new HashSet<PurchaseOrder> ();
}
public Set<PurchaseOrder> getPurchaseOrders()
{
return this.purchaseOrders;
}
public void setPurchaseOrders(Set<PurchaseOrder> orders)
{
this.purchaseOrders = orders;
}
public void addPurchaseOrder(PurchaseOrder purchaseOrder)
{
this.purchaseOrders.add(purchaseOrder);
//this IF is important for avoiding an infinite loop
if (purchaseOrder.getCustomer() != this)
{
purchaseOrder.setCustomer(this);
}
}
public void removePurchaseOrder(PurchaseOrder purchaseOrder)
{
this.purchaseOrders.remove(purchaseOrder);
//this IF is important to avoid an infinite loop
if(purchaseOrder.getCustomer() != null)
{
purchaseOrder.removeFromCustomer(this);
}
}
PO
private int id; //#Id and identity column
private String name;
#ManyToOne
#JoinColumn(name="customer_id")
private Customer customer;
#OneToMany(mappedBy="purchaseOrder")
private Set<Invoice> invoices;
public PurchaseOrder() {
invoices = new HashSet<Invoice> ();
}
public Customer getCustomer()
{
return this.customer;
}
public void setCustomer(Customer customer)
{
this.customer = customer;
}
public void addToCustomer(Customer customer)
{
//this IF is important for avoiding an infinite loop
if(!customer.getPurchaseOrders().contains(this))
{
customer.addPurchaseOrder(this);
}
this.customer = customer;
}
public void removeFromCustomer(Customer customer)
{
//this IF is important for avoiding an infinite loop
if(customer.getPurchaseOrders().contains(this))
{
customer.removePurchaseOrder(this);
}
this.customer = null;
}
public Set<Invoice> getInvoices()
{
return this.invoices;
}
public void setInvoices(Set<Invoice> invoices)
{
this.invoices = invoices;
}
public void addInvoice(Invoice invoice)
{
this.invoices.add(invoice);
//this IF is important for avoiding an infinite loop
if (invoice.getPurchaseOrder() != this)
{
invoice.addToPurchaseOrder(this);
}
}
public void removeInvoice(Invoice invoice)
{
this.invoices.remove(invoice);
//this IF is important to avoid an infinite loop
if(invoice.getPurchaseOrder() != null)
{
invoice.removeFromPurchaseOrder(this);
}
}
Invoice
private int id; //#Id and identity column
private String name;
#ManyToOne
#JoinColumn(name="purchaseorder_id")
private PurchaseOrder purchaseOrder;
public Invoice() {
}
public PurchaseOrder getPurchaseOrder()
{
return this.purchaseOrder;
}
public void setPurchaseOrder(PurchaseOrder purchaseOrder)
{
this.purchaseOrder = purchaseOrder;
}
public void addToPurchaseOrder(PurchaseOrder purchaseOrder)
{
//this IF is important for avoiding an infinite loop
if(!purchaseOrder.getInvoices().contains(this))
{
purchaseOrder.addInvoice(this);
}
this.purchaseOrder = purchaseOrder;
}
public void removeFromPurchaseOrder(PurchaseOrder purchaseOrder)
{
//this IF is important for avoiding an infinite loop
if(purchaseOrder.getInvoices().contains(this))
{
purchaseOrder.removeInvoice(this);
}
this.purchaseOrder = null;
}
GenericDao (Parent of all other DAOs)
#Stateful
public class GenericDao<T extends Serializable, PK> implements IGenericDao<T, PK>
{
#PersistenceContext(unitName = "my_PU")
protected EntityManager em;
private Class<T> type;
public Class<T> getType()
{
return type;
}
public void setType(Class<T> type)
{
this.type = type;
}
public void create(T newObject)
{
em.persist(newObject);
}
public T read(PK id)
{
return em.find(type, id);
}
public T update(T transientObject)
{
return em.merge(transientObject);
}
public void delete(T objectToDelete)
{
em.remove(objectToDelete);
}
public T getResultObject(String namedQuery, Map<String, Object> criteria)
throws DatabaseException
{
List<T> records = getResultSetList(namedQuery, criteria);
if(records.isEmpty())
{
return null;
}
else if (records.size() != 1)
{
throw new DatabaseException("Too many records found!");
}
else
{
return records.remove(0);
}
}
}
Controllers
CustomerController
#RequestScoped
public class CustomerController extends FormRequestController
{
#Inject
private HTMLDataTableActionBean htmlDataTableActionBean;
#EJB
private ICustomerDao customerDao;
#Inject
private Customer customer;
#PostConstruct
public void init() throws DatabaseException
{
setEntityObjectList(findAll());
if (null == this.getCustomer())
{
setCustomer(new Customer());
}
}
public void processRequest(FormActionToPerform action) throws DatabaseException
{
switch (action)
{
case SHOW_ADD_VIEW:
setCustomer(new Customer());
break;
case SHOW_VIEW_FOR_LIST:
setEntityObjectList(findAll());
break;
case SHOW_EDIT_VIEW:
case SHOW_VIEW_TO_VIEW_SELECTED_OBJECT:
setCustomer((Customer) getHtmlDataTableActionBean()
.getSelectedEntityObject());
break;
case SHOW_DELETE_VIEW:
setCustomer((Customer) getHtmlDataTableActionBean()
.getSelectedEntityObject());
delete();
break;
}
}
public String doShowUIView(FormActionToPerform action)
{
String responseURL = "fail.xhtml";
if (null == this.customer)
{
return responseURL;
}
else
{
switch (action)
{
case SHOW_ADD_VIEW:
responseURL = "customer.xhtml";
break;
case SHOW_EDIT_VIEW:
responseURL = "customer.xhtml";
break;
case SHOW_VIEW_TO_VIEW_SELECTED_OBJECT:
responseURL = "viewCustomer.xhtml";
break;
case SHOW_DELETE_VIEW:
responseURL = "customerList.xhtml";
break;
case SHOW_VIEW_FOR_LIST:
if (this.entityObjectList.size() == 0)
{
setErrorMessage("No customers to display");
}
responseURL = "customerList.xhtml";
break;
default:
responseURL = "index.xhtml";
}
}
return responseURL;
}
public String save()
{
String url = "success.xhtml";
Customer existingCustomer = null;
try
{
existingCustomer =
customerDao.getCustomerByName(this.getCustomer().getName());
if(existingCustomer != null)
{
//there's already a customer with this name, don't make a new one
setErrorMessage("Customer already exists");
url = "fail.xhtml";
}
customerDao.update(customer);
}
catch (DatabaseException e)
{
setErrorMessage(e.toString());
e.printStackTrace();
url = "fail.xhtml";
}
return url;
}
}
POController
#RequestScoped
public class PurchaseOrderController extends FormRequestController
{
#Inject
private HTMLDataTableActionBean htmlDataTableActionBean;
#EJB
private IPurchaseOrderDao purchaseOrderDao;
#EJB
private IInvoiceDao invoiceDao;
#EJB
private ICustomerDao customerDao;
#Inject
private PurchaseOrder purchaseOrder;
private List<SelectItem> customerList;
private String selectedCustomer;
#PostConstruct
public void init() throws DatabaseException
{
setEntityObjectList(findAll());
if (null == purchaseOrder)
{
purchaseOrder = new PurchaseOrder();
setEditMode(false);
}
}
public void processRequest(FormActionToPerform action)
throws DatabaseException
{
switch (action)
{
case SHOW_ADD_VIEW:
setPurchaseOrder(new PurchaseOrder());
break;
case SHOW_VIEW_FOR_LIST:
setEntityObjectList(findAll());
break;
case SHOW_EDIT_VIEW:
case SHOW_VIEW_TO_VIEW_SELECTED_OBJECT:
{
setPurchaseOrder(
(PurchaseOrder)getHtmlDataTableActionBean().
getSelectedEntityObject());
}
break;
case SHOW_DELETE_VIEW:
{
setPurchaseOrder(
(PurchaseOrder)getHtmlDataTableActionBean().
getSelectedEntityObject());
delete();
}
break;
}
}
String doShowUIView(FormActionToPerform action)
{
String responseURL = "fail.xhtml";
switch (action)
{
case SHOW_ADD_VIEW:
responseURL = "purchaseOrder.xhtml";
break;
case SHOW_EDIT_VIEW:
setEditMode(true);
setComponent(null);
responseURL = "purchaseOrder.xhtml";
break;
case SHOW_DELETE_VIEW:
case SHOW_VIEW_FOR_LIST:
if (this.entityObjectList.size() == 0)
{
setErrorMessage("No orders to display");
}
responseURL = "purchaseOrderList.xhtml";
break;
case SHOW_VIEW_TO_VIEW_SELECTED_OBJECT:
responseURL = "viewPurchaseOrder.xhtml";
break;
default:
responseURL = HOME;
}
return responseURL;
}
public String save()
{
String responseURL = "fail.xhtml";
try
{
PurchaseOrder dbPurchaseOrder =
purchaseOrderDao.getPurchaseOrderByName(purchaseOrder.getName());
if(dbPurchaseOrder == null)
{
dbPurchaseOrder = purchaseOrder;
}
Customer customer = customerDao.getCustomerByName(selectedCustomer);
dbPurchaseOrder.addToCustomer(customer);
purchaseOrder = purchaseOrderDao.update(dbPurchaseOrder);
//replace the not-yet-persisted dbPurchaseOrder object in customer
//with the persisted purchaseOrderobject returned from the update()
//call above.
customer.removePurchaseOrder(dbPurchaseOrder);
customer.addPurchaseOrder(purchaseOrder);
customerDao.update(customer);
System.out.println("# of Purchase orders for customer: "+
purchaseOrder.getCustomer().getPurchaseOrders().size());
//Output: # of Purchase orders for customer: 1
responseURL = "success.xhtml";
}
catch (DatabaseException e)
{
e.printStackTrace();
setErrorMessage(e.toString());
responseURL = null;
}
return responseURL;
}
}
InvoicesController
#RequestScoped
public class InvoiceController extends FormRequestController
{
#Inject
private HTMLDataTableActionBean htmlDataTableActionBean;
#EJB
private IInvoiceDao invoiceDao;
#Inject
private Invoice invoice;
#EJB
private IPurchaseOrderDao purchaseOrderDao;
private List<SelectItem> purchaseOrderList;
private String selectedPurchaseOrder;
#PostConstruct
public void init() throws DatabaseException
{
setEntityObjectList(findAll());
if (null == invoice)
{
invoice = new Invoice();
setEditMode(false);
}
}
public void processRequest(FormActionToPerform action) throws DatabaseException
{
switch (action)
{
case SHOW_ADD_VIEW:
break;
case SHOW_VIEW_FOR_LIST:
setEntityObjectList(findAll());
break;
case SHOW_EDIT_VIEW:
case SHOW_VIEW_TO_VIEW_SELECTED_OBJECT:
{
setInvoice((Invoice)getHtmlDataTableActionBean().
getSelectedEntityObject());
}
break;
case SHOW_DELETE_VIEW:
{
setInvoice((Invoice)getHtmlDataTableActionBean().
getSelectedEntityObject());
delete();
}
break;
}
}
String doShowUIView(FormActionToPerform action)
{
String responseUrl = "fail.xhtml";
if (null == invoice)
{
System.out.println("invoice == null");
return responseUrl;
}
else
{
switch (action)
{
case SHOW_ADD_VIEW:
responseUrl = "invoice.xhtml";
break;
case SHOW_EDIT_VIEW:
setEditMode(true);
setComponent(null);
responseUrl = "invoice.xhtml";
break;
case SHOW_VIEW_TO_VIEW_SELECTED_OBJECT:
responseUrl = "viewInvoice.xhtml";
break;
case SHOW_DELETE_VIEW:
case SHOW_VIEW_FOR_LIST:
if (this.entityObjectList.size() == 0)
{
setErrorMessage("no invoices to display");
}
responseUrl = "invoiceList.xhtml";
break;
default:
responseUrl = "index.xhtml";
}
}
return responseUrl;
}
public String save()
{
String responseUrl = "fail.xhtml";
try
{
Invoice dbInvoice = invoiceDao.getInvoiceByName(invoice.getName());
if(dbInvoice == null)
{
//this is a new invoice
dbInvoice = invoice;
}
PurchaseOrder purchaseOrder =
purchaseOrderDao.getPurchaseOrderByName(selectedPurchaseOrder);
dbInvoice.addToPurchaseOrder(purchaseOrder);
invoice = invoiceDao.update(dbInvoice);
//replace the not-yet-persisted dbInvoice object in purchaseOrder
//with the persisted invoice object returned from the update() call above.
purchaseOrder.removeInvoice(dbInvoice);
purchaseOrder.addInvoice(invoice);
purchaseOrderDao.update(purchaseOrder);
System.out.println("# of Invoices for purchase order: "+
invoice.getPurchaseOrder().getInvoices().size());
//Output: # of Invoices for purchase order: 1
responseUrl = "success.xhtml";
}
catch (Exception e)
{
System.out.println(e.toString());
e.printStackTrace();
setErrorMessage(e.toString());
}
return responseUrl;
}
}
FormRequestController
public abstract class FormRequestController implements NavigationConstants
{
protected enum FormActionToPerform {
SHOW_ADD_VIEW,
SHOW_EDIT_VIEW,
SHOW_DELETE_VIEW,
SHOW_VIEW_TO_VIEW_SELECTED_OBJECT,
SHOW_VIEW_FOR_LIST;
}
protected FacesContext context;
protected List<?> entityObjectList;
private UIComponent component;
protected boolean editMode;
protected String componentId = null;
public String showViewDataTable() throws DatabaseException {
processRequest(FormActionToPerform.SHOW_VIEW_FOR_LIST);
return doShowUIView(FormActionToPerform.SHOW_VIEW_FOR_LIST);
}
public String showViewToAdd() throws DatabaseException {
processRequest(FormActionToPerform.SHOW_ADD_VIEW);
return doShowUIView(FormActionToPerform.SHOW_ADD_VIEW);
}
public String showViewToEdit() throws DatabaseException {
processRequest(FormActionToPerform.SHOW_EDIT_VIEW);
return doShowUIView(FormActionToPerform.SHOW_EDIT_VIEW);
}
public String showViewToDeleteDetails() throws DatabaseException {
processRequest(FormActionToPerform.SHOW_DELETE_VIEW);
return doShowUIView(FormActionToPerform.SHOW_DELETE_VIEW);
}
public String showViewToViewDetails() throws DatabaseException {
processRequest(FormActionToPerform.SHOW_VIEW_TO_VIEW_SELECTED_OBJECT);
return doShowUIView(FormActionToPerform.SHOW_VIEW_TO_VIEW_SELECTED_OBJECT);
}
abstract String doShowUIView(FormActionToPerform action);
abstract void processRequest(FormActionToPerform action) throws DatabaseException;
protected void bindData() {
}
abstract String save();
abstract void delete() throws DatabaseException;
public List<?> getEntityObjectList() {
return entityObjectList;
}
public void setEntityObjectList(List<?> entityObjectList) {
this.entityObjectList = entityObjectList;
}
public FacesContext getContext() {
setContext(FacesContext.getCurrentInstance());
return context;
}
public void setContext(FacesContext context) {
this.context = context;
}
public UIComponent getComponent() {
return component;
}
public void setComponent(UIComponent component) {
this.component = component;
}
}
I'm iterating over the Customer#purchaseOrders and PurchaseOrder#invoices using a h:dataTable. SO keeps misidentifying my JSF code as misformatted code and telling me to indent it as such so I can't show my webpage code but hopefully there's enough above to spot my mistake.
Thanks in advance for your time.
You should not have logic within the set/get methods if JPA is set to use property access. The logic within the set methods will cause JPA to trigger lazy collections etc when building entities and might have other adverse affects depending on the provider internals. I would either switch your annotations so they are on the fields, or remove the
if(!purchaseOrder.getInvoices().contains(this))
{
purchaseOrder.addInvoice(this);
}
logic from the set methods. The application can still use the addInvoice and have it set both sides of the relationship as the addInvoice methods are not used by JPA when loading entities.
I am always getting NULL from a JOIN FETCH clause in my JPA Query, even though I have everything configured as expected:
#XmlRootElement
#XmlAccessorType(XmlAccessType.PROPERTY)
#Entity
#Table(name = "TB_BANNER_IMAGE")
public class BannerImage extends BaseEntity<Integer> {
protected FileReference fileReference;
private String type;
private String labelTitle;
protected BannerImage() {}
#Id
#TableGenerator(name="genBannerImage", table="TB_ID_GENERATOR",
pkColumnName="ID_NAME", valueColumnName="ID_VAL",
pkColumnValue="TB_BANNER_IMAGE", allocationSize=1)
#GeneratedValue(strategy=GenerationType.TABLE, generator="genBannerImage")
#Column(name = "ID_BANNER_IMAGE", unique = true, nullable = false)
public Integer getId() {
return super.getId();
}
#Override
public void setId(Integer id) {
super.setId(id);
}
#Column(name="TYPE")
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
#OneToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
#JoinColumn(name="ID_FILE_REFERENCE", nullable=false)
public FileReference getFileReference() {
return fileReference;
}
public void setFileReference(FileReference fileReference) {
this.fileReference = fileReference;
}
#Column(name="LABEL_TITLE")
public String getLabelTitle() {
return labelTitle;
}
public void setLabelTitle(String labelTitle) {
this.labelTitle = labelTitle;
}
}
for File Reference Class:
#Entity
#Table(name = "TB_FILE_REFERENCE")
public class FileReference extends BaseNamedEntity<String> {
private String type;
public FileReference() {}
#Id
#TableGenerator(name="genFileReference", table="TB_ID_GENERATOR",
pkColumnName="ID_NAME", valueColumnName="ID_VAL",
pkColumnValue="TB_FILE_REFERENCE", allocationSize=1)
#GeneratedValue(strategy=GenerationType.TABLE, generator="genFileReference")
#Column(name = "ID_FILE_REFERENCE", unique = true, nullable = false)
public String getId() {
return super.getId();
}
#Override
public void setId(String id) {
super.setId(id);
}
#Column(name = "TYPE")
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
Service class:
#Path("/banner")
public class BannerImageService extends BaseServiceFacade<BannerImage, Integer> {
#SuppressWarnings("unchecked")
#Override
public Crud<BannerImage, Integer> lookupService() throws ServiceLocatorException {
return ServiceLocator.getInstance()
.getLocalHome(ServicesConstants.BANNER_IMAGE_SERVICE);
}
#Override
protected String getDefaultGetQuery() {
return BannerImageDAO.GET_BY_ID_FETCH_FILE_REF;
}
#Override
protected String getDefaultQuery() {
return BannerImageDAO.GET_ALL_FETCH_FILE_REF;
}
}
get REST method of BaseServiceFacade:
#Override
#GET
#Consumes(MediaType.APPLICATION_JSON)
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
#Path("/{id}")
public T get(#PathParam("id") ID id) {
try {
if (!validateID(id)) {
logMessage("Invalid Entity ID: " + id);
return null;
}
String defaultGetQuery = getDefaultGetQuery();
if (defaultGetQuery != null) {
Map<String, Object> mapParams = new HashMap<String, Object>();
mapParams.put("id", id);
List<T> entityList = getService().search(defaultGetQuery, mapParams);
if (entityList != null && entityList.size() == 1) {
T ent = entityList.get(0);
return ent;
} else {
logMessage("Invalid search by Entity ID: " + id);
}
} else {
return getService().findById(clazz, id);
}
} catch (ServiceException e) {
serviceException(e);
} catch (Exception ex) {
logException(ex);
}
return null;
}
And finally the Service Bean EJB which reads from entityManager:
public class BaseServiceBean<T extends IEntity<ID>, ID extends Serializable> implements Crud<T,ID> {
// ... generic methods to be reused by subclasses
#Override
public List<T> search(String queryOrNamedQuery) throws ServiceException {
return search(queryOrNamedQuery, null, 0, 0);
}
#SuppressWarnings("unchecked")
public List<T> search(String namedQueryOrHql, Map<String, Object> parameters, int start, int chunkSize) {
try {
Query query = createQuery(namedQueryOrHql, getQueryType(namedQueryOrHql));
if (start > 0) {
query.setFirstResult(start);
}
if (chunkSize > 0) {
query.setMaxResults(chunkSize);
}
addParameters(query, parameters);
List<T> result = query.getResultList();
afterSearch(result);
return result;
} catch (NoResultException nre) {
nre.printStackTrace();
} catch (ClassCastException cce) {
cce.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
protected void afterSearch(List<T> result) {
}
// etc...
implementation specific class for BannerImageService:
#Stateless(mappedName="ejb/BannerImageService")
public class BannerImageServiceBean extends BaseServiceBean<BannerImage, Integer> implements BannerImageServiceBeanRemote, BannerImageServiceBeanLocal {
#Override
protected void afterSearch(List<BannerImage> result) {
if (result != null && result.size() == 1) {
BannerImage bannerImage = result.get(0);
bannerImage.getFileReference();
}
super.afterSearch(result);
}
// additional code ...
When I try to fetch my BannerImage class together with it's corresponding FileReference member I always get NULL even though in my DB there is an existing foreign key present:
JPQL:
"SELECT a FROM BannerImage a join fetch a.fileReference WHERE a.id = :id";
Generated SQL:
SELECT t1.ID_BANNER_IMAGE, t1.LABEL_TEXT, t1.LABEL_TITLE, t1.TYPE,
t1.ID_FILE_REFERENCE, t0.ID_FILE_REFERENCE, t0.NAME,
t0.TYPE FROM TB_FILE_REFERENCE t0, TB_BANNER_IMAGE
t1 WHERE (t0.ID_FILE_REFERENCE = t1.ID_FILE_REFERENCE) AND t1.ID_BANNER_IMAGE = 1
in my DB the record shows a correct reference:
BANNER_IMAGE:
1;"";"main";"2bdbb063d0d0ee2939c89763945d9d9e";"banner1.png";"image/png"
If I execute :
select * from TB_FILE_REFERENCE where ID_FILE_REFERENCE = '2bdbb063d0d0ee2939c89763945d9d9e'
I can find the record in the DB, although my EclipseLink JPA Implementation always returns null:
EclipseLink Version 2.5.2-M1
This is how the Entity gets passed from Service Layer to the
Can someone help pointing why the JOIN FETCH is not properly working?
I faced a similar issue and looking closely I see that this issue was happening only to entities recently created/saved. Then I figured that it has something to do with eclipselink cache. I solved this problem by adding this line before making a join fetch JPQL query,
em.getEntityManagerFactory().getCache().evictAll();
em.createQuery("SELECT a FROM BannerImage a join fetch a.fileReference WHERE a.id = :id").getResultList();
HTH!
I'm pretty new to unit testing and I'm having some problems with regards, to unit testing a generic repository in my application. I've implemented the unit of work pattern in my ASP.NET MVC application. My classes look like this:
public class UnitOfWork : IUnitOfWork
{
private bool disposed = false;
private IGenericRepository<Shop> _shopRespository;
public UnitOfWork(PosContext context)
{
this.Context = context;
}
public PosContext Context { get; private set; }
public IGenericRepository<Shop> ShopRepository
{
get
{
return this._shopRespository ?? (this._shopRespository = new GenericRepository<Shop>(this.Context));
}
}
public void SaveChanges()
{
this.Context.SaveChanges();
}
public void Dispose()
{
this.Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
this.Context.Dispose();
}
this.disposed = true;
}
}
}
public class PosContext : DbContext, IPosContext
{
public DbSet<Shop> Shops { get; private set; }
}
public class GenericRepository<T> : IGenericRepository<T>
where T : class
{
private readonly PosContext context;
private readonly DbSet<T> dbSet;
public GenericRepository(PosContext context)
{
this.context = context;
this.dbSet = context.Set<T>();
}
public virtual IEnumerable<T> Get(
Expression<Func<T, bool>> filter = null,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null,
string includeProperties = "")
{
IQueryable<T> query = this.dbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
public virtual T Find(object id)
{
return this.dbSet.Find(id);
}
public virtual void Add(T entity)
{
this.dbSet.Add(entity);
}
public virtual void Remove(object id)
{
T entityToDelete = this.dbSet.Find(id);
this.Remove(entityToDelete);
}
public virtual void Remove(T entityToDelete)
{
if (this.context.Entry(entityToDelete).State == EntityState.Detached)
{
this.dbSet.Attach(entityToDelete);
}
this.dbSet.Remove(entityToDelete);
}
public virtual void Update(T entityToUpdate)
{
this.dbSet.Attach(entityToUpdate);
this.context.Entry(entityToUpdate).State = EntityState.Modified;
}
I'm using NUnit and FakeItEasy to write my unit tests. In my set up function, I create a UnitIfWork object with a fake PosContext object. I then populate the context with a few Shop objects.
[SetUp]
public void SetUp()
{
this.unitOfWork = new UnitOfWork(A.Fake<PosContext>());
this.unitOfWork.ShopRepository.Add(new Shop() { Id = 1, Name = "Test name1" });
this.unitOfWork.ShopRepository.Add(new Shop() { Id = 2, Name = "Test name2" });
this.unitOfWork.ShopRepository.Add(new Shop() { Id = 3, Name = "Test name3" });
this.unitOfWork.ShopRepository.Add(new Shop() { Id = 4, Name = "Test name4" });
this.unitOfWork.ShopRepository.Add(new Shop() { Id = 5, Name = "Test name5" });
this.Controller = new ShopController(this.unitOfWork);
}
It works fine when I test the Find-method of the GenericRepository. The correct Shop object is returned and I can assert that it works fine:
[TestCase]
public void DetailsReturnsCorrectShop()
{
// Arrange
int testId = 1;
// Act
Shop shop = this.unitOfWork.ShopRepository.Find(testId);
ViewResult result = this.Controller.Details(testId) as ViewResult;
// Assert
Shop returnedShop = (Shop)result.Model;
Assert.AreEqual(testId, returnedShop.Id);
}
But when I want to test that the Get-method returns all shops from the repository, if I do not give any filter params, I get an empty list back. I can't figure out why?
[TestCase]
public void IndexReturnsListOfShops()
{
// Arrange
// Act
ViewResult result = this.Controller.Index() as ViewResult;
// Assert
List<Shop> returnedShops = (List<Shop>)result.Model;
Assert.AreEqual(5, returnedShops.Count);
}
The ShopController looks like this:
public class ShopController : Controller
{
private readonly IUnitOfWork unitOfWork;
public ShopController(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
// GET: /Shop/
public ActionResult Index()
{
return View(this.unitOfWork.ShopRepository.Get());
}
// GET: /Shop/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Shop shop = this.unitOfWork.ShopRepository.Find(id);
if (shop == null)
{
return HttpNotFound();
}
return View(shop);
}
}
Can you help me figure out why I get an empty list back from the Get-method?
I am using MVC2 with Entity Framework 4 and am trying to implement a Repository and UnitofWork pattern. My Adds and Deletes work fine, however when the edit is called _context.SaveChanges() does save the new changes to the database. I have stepped through the code in debug and see the new values are in the object being passed to the Edit function in the controller, but when the commit is called, nothing is updated.See my code below: Thanks for your help.
Here is my IRepository
namespace EventScheduling.DataModel.Custom
{
public interface IRepository<T>
{
void Add(T newEntity);
void Remove(T entity);
IQueryable<T> Find(Expression<Func<T, bool>> predicate);
IQueryable<T> FindAll();
}
}
SQLRepository Implementation
namespace EventScheduling.DataModel.Custom
{
public class SQLRepository<T>:IRepository<T> where T : class
{
protected ObjectSet<T> _objectSet;
public SQLRepository(ObjectContext context)
{
_objectSet = context.CreateObjectSet<T>();
}
public IQueryable<T> Find(Expression<Func<T, bool>> predicate){
return _objectSet.Where(predicate);
}
public void Add(T newEntity)
{
_objectSet.AddObject(newEntity);
}
public void Remove(T entity)
{
_objectSet.DeleteObject(entity);
}
public IQueryable<T> FindAll()
{
return _objectSet;
}
}
}
Unit of Work Implementation
namespace EventScheduling.DataModel.Custom
{
public interface IUnitOfWork
{
IRepository<utility_event> utility_event { get; }
IRepository<event_activity> event_activity { get; }
IRepository<employee> employee{ get; }
IRepository<activity_resource> activity_resource { get; }
IRepository<Elmah_Error> Elmah_Error { get; }
IRepository< location> location { get; }
IRepository<location_station> location_station { get; }
IRepository<registration_type> registration_type { get; }
IRepository< resource> resource { get; }
IRepository<shift> shift { get; }
IRepository<shift_person> shift_person{ get; }
IRepository<event_type> event_type { get; }
IRepository<status> status { get; }
void Commit();
}
}
SqlUnitOfWork Implementation
namespace EventScheduling.DataModel.Custom
{
public class SqlUnitOfWork: IUnitOfWork
{
readonly ObjectContext _context;
const String ConnectionStringName = "EventEntities";
public SqlUnitOfWork()
{
var connectionString = ConfigurationManager.ConnectionStrings[ConnectionStringName].ConnectionString;
_context = new ObjectContext(connectionString);
_context.ContextOptions.LazyLoadingEnabled = true;
}
public IRepository<utility_event> utility_event
{
get {
if (_utilityEvent == null)
{
_utilityEvent = new SQLRepository<utility_event>(_context);
}
return _utilityEvent;
}
}
public IRepository<event_activity> event_activity
{
get
{
if (_eventActivities == null)
{
_eventActivities = new SQLRepository<event_activity>(_context);
}
return _eventActivities;
}
}
public IRepository<employee> employee
{
get
{
if (_employees == null)
{
_employees = new SQLRepository<employee>(_context);
}
return _employees;
}
}
public IRepository<activity_resource> activity_resource
{
get
{
if (_activityResources == null)
{
_activityResources = new SQLRepository<activity_resource>(_context);
}
return _activityResources;
}
}
public IRepository<location> location
{
get
{
if (_locations == null)
{
_locations = new SQLRepository<location>(_context);
}
return _locations;
}
}
public IRepository<location_station> location_station
{
get
{
if (_locationStations == null)
{
_locationStations = new SQLRepository<location_station>(_context);
}
return _locationStations;
}
}
public IRepository<registration_type> registration_type
{
get
{
if (_registrationTypes == null)
{
_registrationTypes = new SQLRepository<registration_type>(_context);
}
return _registrationTypes;
}
}
public IRepository<resource> resource
{
get
{
if (_resources == null)
{
_resources = new SQLRepository<resource>(_context);
}
return _resources;
}
}
public IRepository<shift> shift
{
get
{
if (_shifts == null)
{
_shifts = new SQLRepository<shift>(_context);
}
return _shifts;
}
}
public IRepository<shift_person> shift_person
{
get
{
if (_shiftPersons == null)
{
_shiftPersons = new SQLRepository<shift_person>(_context);
}
return _shiftPersons;
}
}
public IRepository<Elmah_Error> Elmah_Error
{
get
{
if (_ElmahError == null)
{
_ElmahError = new SQLRepository<Elmah_Error>(_context);
}
return _ElmahError;
}
}
public IRepository<event_type> event_type
{
get
{
if (_eventTypes == null)
{
_eventTypes = new SQLRepository<event_type>(_context);
}
return _eventTypes;
}
}
public IRepository<status> status
{
get
{
if (_status == null)
{
_status = new SQLRepository<status>(_context);
}
return _status;
}
}
public void Commit()
{
_context.SaveChanges();
}
SQLRepository<utility_event> _utilityEvent = null;
SQLRepository<event_activity> _eventActivities = null;
SQLRepository<employee> _employees = null;
SQLRepository<activity_resource> _activityResources = null;
SQLRepository<Elmah_Error> _ElmahError = null;
SQLRepository<location> _locations = null;
SQLRepository<location_station> _locationStations = null;
SQLRepository<registration_type> _registrationTypes = null;
SQLRepository<resource> _resources = null;
SQLRepository<shift> _shifts = null;
SQLRepository<shift_person> _shiftPersons = null;
SQLRepository<event_type> _eventTypes = null;
SQLRepository<status> _status = null;
}
}
Controller Edit Implementation
public ActionResult Edit(int id, shift e)
{
if (!ModelState.IsValid)
{
return View(e);
//return to view
}
else
{
e.shift_begin = (DateTime)e.shift_date.Value.Add(e.shift_begin.Value.TimeOfDay);
e.shift_end = (DateTime)e.shift_date.Value.Add(e.shift_end.Value.TimeOfDay);
_unitOfWork.Commit();
return RedirectToAction("Details", "EventActivity", new { id = e.activity_id });
}
}
When you want to update entity in EF you must first Attach entity to ObjectContext instance or instance of related ObjectSet and use ObjectStateManager.ChangeObjectState to set state of entity to EntityState.Modified.
Other possibility is to load entity first from database and merge changes directly into this entity.
Check link in comment for examples or try to use search box. This question is one of the most frequent in EF tag.