I can not understand why stopped working AggregateHydrator if you get it in the mapper factory:
$aggregatehydrator = $container->get(AggregateHydrator::class);
Empty objects are returned. I tried to debug and PHP is dying (excess memory), when I try:
\Zend\debug\debug::dump($aggregatehydrator);
If i get hydrator another way:
$tagsHydrator = $container->get(TagsHydrator::class);
$categoryHydrator = $container->get(CategoryHydrator::class);
$postHydrator = $container->get(PostHydrator::class);
$datesHydrator = $container->get(DatesHydrator::class);
$aggregatehydrator = new \Zend\Hydrator\Aggregate\AggregateHydrator();
$aggregatehydrator->add($postHydrator);
$aggregatehydrator->add($categoryHydrator);
$aggregatehydrator->add($tagsHydrator);
$aggregatehydrator->add($datesHydrator);
it works all. The filled objects are returned.
https://bitbucket.org/mad-max/blog-note3/overview
class AggregateHydratorFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$aggregatehydrator = new AggregateHydrator();
$tagsHydrator = $container->get(TagsHydrator::class);
$categoryHydrator = $container->get(CategoryHydrator::class);
$postHydrator = $container->get(PostHydrator::class);
$datesHydrator = $container->get(DatesHydrator::class);
$aggregatehydrator->add($postHydrator);
$aggregatehydrator->add($categoryHydrator);
$aggregatehydrator->add($tagsHydrator);
$aggregatehydrator->add($datesHydrator);
return $aggregatehydrator;
}
}
I added in AggregateHydratorFactory:
$aggregatehydrator = new AggregateHydrator();
$aggregatehydrator->setEventManager($container->get('EventManager'));
The answer is here:
https://github.com/zendframework/zend-hydrator/issues/40
Related
I'm refactoring some previously written MVC and Entity Framework code. The way the initial code was written they called a DAL.GetGroupDetail(int groupId) method. In that method it created a ViewModel and populated several properties. Some of those properties are Lists for things like CostCenters, Cities, Groups. I want to break those calls out into their own methods so that they can be re-used in other controllers.
My question is that doing that I'm creating new Contexts using the Using statement. My understanding is that would create multiple connections to the database and thus would slow down the site if multiple users were using it at the same time?
Example, currently this is the basic code:
public ClockGroupViewModel GetClockGroupDetail(int groupId)
{
GroupViewModel cgdv = new GroupViewModel();
using (var ctx = new VTContext())
{
bio_group group = ctx.bio_group.Where(x => x.group_id == groupId).FirstOrDefault();
cgdv.GroupId = group.group_id;
cgdv.GroupName = group.group_name;
cgdv.Cities = ctx.bio_city.ToList();
var clocks = from c in ctx.bio_clock.Where(x => x.group_id == groupId)
select new ClockViewModel
{
ClockID = c.rdr_id.ToString(),
ClockDescription = c.clock_desc,
};
cgdv.ClockList = clocks.ToList();
cgdv.CostCtrList = (from g in ctx.bio_clock_group
from cgc in ctx.bio_clock_group_costctr
where cgc.group_id == g.group_id && g.group_id == groupId
select cgc.cost_ctr).ToList();
}
This how I'm thinking of changing it:
public ClockGroupViewModel GetClockGroupDetail(int groupId)
{
GroupViewModel cgdv = new GroupViewModel();
using (var ctx = new VTContext())
{
bio_group group = ctx.bio_group.Where(x => x.group_id == groupId).FirstOrDefault();
cgdv.GroupId = group.group_id;
cgdv.GroupName = group.group_name;
cgdv.Cities = GetCityList();
cgdv.ClockList = GetClockGroupClockList(group.group_id);
cgdv.CostCtrList = GetGroupCostCenter(group.group_id);
}
}
public List<bio_clock_city> GetCityList()
{
using (var ctx = new VTContext())
{
return ctx.bio_city.ToList();
}
}
public List<ClockViewModel> GetClockGroupClockList(int groupId)
{
using (var ctx = new VTContext())
{
var data = (from c in ctx.bio_clock.Where(x => x.group_id == groupId)
select new ClockViewModel
{
ClockID = c.rdr_id.ToString(),
ClockDescription = c.clock_desc,
}).ToList();
return data;
}
}
public List<string> GetGroupCostCenter(int groupId)
{
using (var ctx = new VTContext())
{
var data = (from g in ctx.bio_clock_group
from cgc in ctx.bio_clock_group_costctr
where cgc.group_id == g.group_id && g.group_id == groupId
select cgc.cost_ctr).ToList();
return data;
}
}
So I'm passing a custom class to my controller and it seems that the JsonResult is not properly passed.
What bothers me is that (also the fullcalendar wont read the json) the console.log which I have in my view prints the path to the function (wtf?) instead of what Json shoul return
This is my code:
public JsonResult GetCalendarEvents()
{
var eventList = BusinessLayer.Event.getAllEvents();
return Json(eventList.ToArray(), JsonRequestBehavior.AllowGet);
}
What kind of object has to be passed for this to work?
My evenList is of type List<Event> from here:
public static String ListToString(List<Event> evs)
{
String ret = "";
foreach (var ev in evs)
{
ret += ev.ToString() + "\n";
}
return ret;
}
public static List<Event> getAllEvents()
{
List<DataLayer.Event> dbEvents = DataApi.db.Event.ToList();
List<Event> returnEvents = new List<Event>();
foreach (DataLayer.Event oneEvent in dbEvents)
{
Event newEvent = new Event
{
ID = oneEvent.IDEvent,
userID = oneEvent.UserID,
projectID = oneEvent.ProjectID,
jobtypeID = oneEvent.JobTypeID,
taskID = oneEvent.TaskID,
ticketID = oneEvent.TicketID,
loccoID = oneEvent.LoccoID,
startTime = oneEvent.StartTime,
endTime = oneEvent.EndTime,
shiftFrom = oneEvent.ShiftFrom,
shiftTo = oneEvent.ShiftTo,
description = oneEvent.Description,
billable = oneEvent.Billable
};
returnEvents.Add(newEvent);
}
return returnEvents;
}
I tried displaying the events in fullcalendar:
$('#calendar').fullCalendar({
header: {
left: 'title',
center: '',
right: 'prev,next today basicDay,basicWeek,month',
},
//events: "/Calendar/GetEvents/", // not implemented
events: "#Url.Action("GetCalendarEvents/")",
and outputing the result to console:
console.log("#Url.Action("GetCalendarEvents/")");
but I get:
VM84 Index:83 /Calendar/GetCalendarEvents/
fullcalendar.min.js:6 Uncaught TypeError: Cannot read property 'hasTime' of undefined
It looks like you're missing some required fields. If you look at the documentation, title, start are required. Try setting these in the class to start with and build from that...
public static List<Event> getAllEvents()
{
List<DataLayer.Event> dbEvents = DataApi.db.Event.ToList();
List<Event> returnEvents = new List<Event>();
foreach (DataLayer.Event oneEvent in dbEvents)
{
Event newEvent = new Event
{
start = oneEvent.StartTime,
title = oneEvent.Description // you may need to add this to your Event class.
};
returnEvents.Add(newEvent);
}
return returnEvents;
}
Also, instead of using console to log the Json, use Fiddler or Chrome Advanced Tools
I am using a mojarra-specific code for this:
public static Map<String, ResourceBundle> getBundleMap()
{
Locale locale = Faces.getLocale();
ApplicationAssociate associate = ApplicationAssociate.getCurrentInstance();
Map<String, ApplicationResourceBundle> resourceBundles = associate.getResourceBundles();
Map<String, ResourceBundle> map = new HashMap<>(resourceBundles.size());
for(Entry<String, ApplicationResourceBundle> entry : resourceBundles.entrySet())
{
String name = entry.getKey();
ResourceBundle bundle = entry.getValue().getResourceBundle(locale);
map.put(name, bundle);
}
return map;
}
I'd like to have an implementation-agnostic way to get this map.
Should I parse every faces-config.xml defined in application and libs? Isn't this reinventing the wheel?
A Map<String, String>, where key = /faces-config/application/resource-bundle/var and value = /faces-config/application/resource-bundle/base-name would be sufficient.
Thanks.
I'd like to have an implementation-agnostic way to get this map.
Understandable.
Should I parse every faces-config.xml defined in application and libs?
Yes. This functionality isn't available in JSF API.
Isn't this reinventing the wheel?
Yes, definitely. You could however try to get it into OmniFaces, which has already a similar utility class for /WEB-INF/web.xml and all /META-INF/web-fragment.xml, the WebXml.
A Map<String, String>, where key = /faces-config/application/resource-bundle/var and value = /faces-config/application/resource-bundle/base-name would be sufficient.
Here's a kickoff example using JAXP (cough):
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setNamespaceAware(false);
factory.setExpandEntityReferences(false);
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.newDocument();
document.appendChild(document.createElement("all-faces-configs"));
List<URL> facesConfigURLs = new ArrayList<>();
facesConfigURLs.add(FacesContext.getCurrentInstance().getExternalContext().getResource("/WEB-INF/faces-config.xml"));
facesConfigURLs.addAll(Collections.list(Thread.currentThread().getContextClassLoader().getResources("META-INF/faces-config.xml")));
for (URL facesConfigURL : facesConfigURLs) {
URLConnection connection = facesConfigURL.openConnection();
connection.setUseCaches(false);
try (InputStream input = connection.getInputStream()) {
NodeList children = builder.parse(input).getDocumentElement().getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
document.getDocumentElement().appendChild(document.importNode(children.item(i), true));
}
}
}
Map<String, String> resourceBundles = new HashMap<>();
Element allFacesConfigs = document.getDocumentElement();
XPath xpath = XPathFactory.newInstance().newXPath();
NodeList resourceBundleNodes = (NodeList) xpath.compile("application/resource-bundle").evaluate(allFacesConfigs, XPathConstants.NODESET);
for (int i = 0; i < resourceBundleNodes.getLength(); i++) {
Node resourceBundleNode = resourceBundleNodes.item(i);
String var = xpath.compile("var").evaluate(resourceBundleNode).trim();
String baseName = xpath.compile("base-name").evaluate(resourceBundleNode).trim();
resourceBundles.put(var, baseName);
}
An error occurs when I call the function shown below:
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries."
Function:
[HttpPost]
public ActionResult Index(InsertPo model)
{
var context = new UsersContext();
var po = new Po();
var user = new User();
po.PoId = 12;
po.PoNumber = model.Po.PoNumber;
po.Style = model.Po.Style;
po.Quantity = model.Po.Quantity;
po.Status = "hhh";
po.OrderDate = Convert.ToDateTime("30-12-2011");
po.ShipmentDate = Convert.ToDateTime("2-12-2011");
po.ProductionRate = 10;
po.UserId = 2;
/*buyer.BuyerName = model.Buyer.BuyerName;*/
/* buyer.BuyerId = 1;
buyer.PoId = 10;*/
context.Pos.Add(po);
context.SaveChanges();
return RedirectToAction("Index");
}
Try putting this line outside of your Action method.
var context = new UsersContext();
I have a controller that depends on a Session variable. In order to unit test this controller, I came up with the following solution. It works but I'm wondering if there is a better/cleaner way. Thanks
Controller
public JsonResult UpdateStatus(ImageUpdateStatus imageUpdateStatus, SessionStateItemCollection sessionItems = null)
{
var data = new object();
string status = null;
ImageInfo imageInfo = new ImageInfo();
IImageInfoServices svcImageInfo = new ImageInfoServicesRepository();
imageInfo = svcImageInfo.GetImageByImageId(imageUpdateStatus.ImageId);
IDeviceControlServices svcDevice = new DeviceControlServicesRespository();
IPVSCommandServices svcPVSCmds = new PVSCommandServicesRespository();
if (imageUpdateStatus.Task == "prep")
{
List<UpdateReasonForm> updateReasonForms;
if (sessionItems != null)
{
updateReasonForms = sessionItems["UpdateReasonForms"] as List<UpdateReasonForm>;
}
else
{
updateReasonForms = Session["UpdateReasonForms"] as List<UpdateReasonForm>;
}
foreach (var item in updateReasonForms)
{
if (item.ImageId == imageInfo.ImageId)
{
status = svcPVSCmds.PrepImage(imageInfo, item.NewVersion);
}
}
data = new
{
status
};
}
if (imageUpdateStatus.Task == "boot")
{
status = svcDevice.Boot(imageInfo.ImageId);
data = new
{
status
};
}
return this.Json(data, JsonRequestBehavior.AllowGet);
}
Unit Test
[TestMethod()]
public void UpdateStatusTest()
{
BuildController target = new BuildController(); // TODO: Initialize to an appropriate value
ImageUpdateStatus imageUpdateStatus = new ImageUpdateStatus(); // TODO: Initialize to an appropriate value
imageUpdateStatus.ImageId = 3;
imageUpdateStatus.Task = "prep";
UpdateReasonForm updateReasonForm = new UpdateReasonForm();
updateReasonForm.ImageId = 3;
updateReasonForm.NewVersion = "TestThis";
List<UpdateReasonForm> updateReasonForms = new List<UpdateReasonForm>();
updateReasonForms.Add(updateReasonForm);
var sessionItems = new SessionStateItemCollection();
sessionItems["UpdateReasonForms"] = updateReasonForms;
JsonResult actual;
actual = target.UpdateStatus(imageUpdateStatus, sessionItems);
}
Instead of passing in the session values as a parameter you can mock the session state like here:
How do you mock the session object collection using Moq
You have a dependency on Session. You could move your code into a testable method where you inject the dependency at the method level. It looks like you are on this path I would just abstract the code into its own method allowing you to test the functionality regardless of the whether the data comes from session or not.
public JsonResult UpdateStatusDependencyInjection(ImageUpdateStatus imageUpdateStatus, Dictionary<string, object> sessionValues)
{
var data = new object();
string status = null;
ImageInfo imageInfo = new ImageInfo();
IImageInfoServices svcImageInfo = new ImageInfoServicesRepository();
imageInfo = svcImageInfo.GetImageByImageId(imageUpdateStatus.ImageId);
IDeviceControlServices svcDevice = new DeviceControlServicesRespository();
IPVSCommandServices svcPVSCmds = new PVSCommandServicesRespository();
if (imageUpdateStatus.Task == "prep")
{
List<UpdateReasonForm> updateReasonForms;
if (sessionItems != null)
{
updateReasonForms = sessionItems["UpdateReasonForms"] as List<UpdateReasonForm>;
}
else
{
updateReasonForms = Session["UpdateReasonForms"] as List<UpdateReasonForm>;
}
foreach (var item in updateReasonForms)
{
if (item.ImageId == imageInfo.ImageId)
{
status = svcPVSCmds.PrepImage(imageInfo, item.NewVersion);
}
}
data = new
{
status
};
}
if (imageUpdateStatus.Task == "boot")
{
status = svcDevice.Boot(imageInfo.ImageId);
data = new
{
status
};
}
return this.Json(data, JsonRequestBehavior.AllowGet);
}
http://codingsmith.co.za/a-better-way-of-working-with-httpcontext-session-in-mvc/
This is my implementation of an interface wrapper for Session.
Its currently in production and works fine, its injected into my controllers, but I can use one of the other implementations manually when testing