At the moment, if you use the following
c.CustomOperationIds(apiDesc =>
{
return apiDesc.TryGetMethodInfo(out MethodInfo methodInfo) ? methodInfo.Name : null;
});
And, by programmer mistake, you have 2 methods with same name, you are not warned that you violate OpenAPI spec
Is there a way to add a check ?
I was thinking to either
at the end of generation like "2 operations with id {0}"
when swashbuckle calls CustomOperationId "selector", have a hook to access already defined operations
Thanks for your time
P.S : using Swashbuckle.AspNetCore.SwaggerGen 5.3.1
After many tries, I've found a workaround: use an operation filter that will throw an exception if OperationId is already used
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System;
using System.Collections.Generic;
namespace Service.Utils
{
/// <summary>
/// Guarantee that OperationId is not already used
/// </summary>
public class SwaggerUniqueOperationId : IOperationFilter
{
private readonly HashSet<string> ids = new HashSet<string>();
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (operation.OperationId != null)
{
if (ids.Contains(operation.OperationId))
throw new NotSupportedException($"There are 2 operations with same OperationId {operation.OperationId}");
ids.Add(operation.OperationId);
}
}
}
}
This is not ideal at all because the error message is pretty vague and it is a runtime error, but this is better than providing an OpenApi spec that violates this unique OperationId constraint...
Related
is it possible to implement a custom hydration and persistence in Doctrine 2 on a per entity basis?
Doctrine 2 has some major limitations regarding value objects (e.g. collections and ids). I wonder if it would be possible to use custom mechanisms (or implementations) for the mapping from object properties to the database (loading and persistence).
I know there are some possibilities to "solve" this problem but I like none of them:
Fake entities require proper handling in the entity which leaks the persistence layer into the domain objects
real entities require a lot more work in persistence (more repositories and more complex handling)
Embaddables have the mentioned limitations
Custom DBAL types with serialization makes querying for certain values impossible or at least extremely slow
I know there are the lifecycle events in doctrine which may be usable. I could't find out if the postLoad event carries an already constructed entity object (with all the VOs)? Becuase in that case it would be useless to me.
best regards,
spigandromeda
Yes, you can register new hydrators in your config/packages/doctrine.yaml like this:
doctrine:
dbal: ...
orm:
hydrators:
CustomEntityHydrator: 'App\ORM\Hydrator\CustomEntityHydrator'
...
mapping: ...
...
You can then use it in your queries like this:
public function findCustomEntities(): array
{
return $this->createQueryBuilder('c')
...your query logic...
->getResult('CustomEntityHydrator');
}
Note, that you can only specify which hydrator you want to use for the root entity. If you fetch associated entities you might end up with a more complicated setup that is hard to debug.
Instead you could consider dealing with value objects (VOs) only in the interface of your entity. In other words, the fields are scalar values, but your method arguments and return values are VOs.
Here is an example with an entity that has a id of type Uuid, a location (some numeric identifier), status (e.g. ternary true/false/null). These are only there to showcase how to deal with different type of value objects:
/**
* #ORM\Entity()
*/
class CustomEntity
{
/**
* #ORM\Id()
* #ORM\Column(type="string", length=64)
*/
private string $id;
/**
* #ORM\Column(type="int")
*/
private int $location;
/**
* #ORM\Column(type="bool, nullable=true)
*/
private bool $status;
private function __construct(Uuid $id, Location $location, Status $status)
{
$this->id = (string) $id;
$this->location = $location->getValue();
$this->status = $status->get();
}
public static function new(Location $location, Status $status): self
{
return new self(Uuid::v4(), $location, $status);
}
public function getId(): Uuid
{
return Uuid::fromString($this->id);
}
public function getLocation(): Location
{
return new Location($this->location);
}
public function activate(): void
{
$this->status = true;
}
public function deactivate(): void
{
$this->status = false;
}
public function isActive(): bool
{
$this->status === true;
}
public function isInactive(): bool
{
$this->status === false;
}
public function isUninitialized(): bool
{
$this->status === null;
}
public function getStatus(): Status
{
if ($this->status === null) {
return new NullStatus();
}
if ($this->status === true) {
return new ActiveStatus();
}
return new InactiveStatus();
}
}
As you can see, you could replace new() with a public constructor. It would work similar with setters. I sometimes even use (private) setters for this in the constructor. In case of the status you don't even need setters if you instead use multiple methods that set the value internally. Similarly you might want to return scalar values instead of a VO in some cases (or the other way around as shown with the status getter and issers).
The point is, your entity looks from the outside as if it would use your VOs, but internally it already switches to a representation that works better with Doctrine ORM. You could even mix this with using VOs and custom types, e.g. for the UUID. You just have to be careful, when your VO needs more info for being constructed than you want to store in the database, e.g. if the numeric location in our example would also use a locale during creation, then we would need to store this (which makes sense as it seems to be related to the numeric id) or we have to hardcode it in the entity or add an abstraction above, that has access to the locale, in which case your entity would likely not return a Location or at least not a LocalizedLocation.
You might also want to consider not having a VO for each and every property in your entity. While it definitely can be helpful, e.g. to wrap an Email into a custom VO to ensure validity instead of just type hinting for string, it might be less useful for something as generic as a (user's) name, which should be very lenient with which strings it accepts as there are a wide variety of names. Using the approach above you can easily introduce a VO later, by adding a new getter for the VO, changing new() or any other method that mutates your property and then not having to change anything in the data model below (unless there is a more drastic change to how the value is represented).
For some reasons, I need to implement a custom resource for Tensorflow. I tried to get inspiration from lookup table implementations. If I understood well, I need to implement 3 TF operations:
creation of my resource
initialization of the resource (e.g. populate the hash table in case of the lookup table)
implementation of the find / lookup / query step.
To facilitate the implementation, I'm relying on tensorflow/core/framework/resource_op_kernel.h. I get the following error
[F tensorflow/core/lib/core/refcount.h:90] Check failed: ref_.load() == 0 (1 vs. 0)
1] 29701 abort python test.py
Here is the full code to reproduce the issue:
using namespace tensorflow;
/** CUSTOM RESOURCE **/
class MyVector : public ResourceBase {
public:
string DebugString() override { return "MyVector"; };
private:
std::vector<int> vec_;
};
/** CREATE VECTOR **/
REGISTER_OP("CreateMyVector")
.Attr("container: string = ''")
.Attr("shared_name: string = ''")
.Output("resource: resource")
.SetIsStateful();
class MyVectorOp : public ResourceOpKernel<MyVector> {
public:
explicit MyVectorOp(OpKernelConstruction* ctx) : ResourceOpKernel(ctx) {}
private:
Status CreateResource(MyVector** resource) override {
*resource = CHECK_NOTNULL(new MyVector);
if(*resource == nullptr) {
return errors::ResourceExhausted("Failed to allocate");
}
return Status::OK();
}
Status VerifyResource(MyVector* vec) override {
return Status::OK();
}
};
REGISTER_KERNEL_BUILDER(Name("CreateMyVector").Device(DEVICE_CPU), MyVectorOp)
and then, after compiling, the error can be reproduced with this Python snippet of code:
test_module = tf.load_op_library('./test.so')
my_vec = test_module.create_my_vector()
with tf.Session() as s:
s.run(my_vec)
As a side question, I'd be interested in having tutorials / guidelines to implement custom resources. In particular, I'd like to have information about what needs to be implemented for checkpoints / graph export / serialization / etc.
Thanks a lot.
Add -DNDEBUG to your build flags.
This workaround is explained in TF issue 17316.
I am trying to embed collection of Tag forms to Service form, according to this tutorial. Tag and Service entities have many-to-many relationship.
Form is rendering correctly. But when I submit form, I get
Could not determine access type for property "tagList"
error. I don't understand why new Tag object is not added to the Service class by calling the addTag() method.
ServiceType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', TextType::class, array(
'label' => 'Title'
))
;
$builder->add('tagList', CollectionType::class, array(
'entry_type' => TagType::class,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false
)));
}
Service class
{
....
/**
* #ORM\ManyToMany(targetEntity="Tag", mappedBy="serviceList",cascade={"persist"})
*/
private $tagList;
/**
* #return ArrayCollection
*/
public function getTagList()
{
return $this->tagList;
}
/**
* #param Tag $tag
* #return Service
*/
public function addTag(Tag $tag)
{
if ($this->tagList->contains($tag) == false) {
$this->tagList->add($tag);
$tag->addService($this);
}
}
/**
* #param Tag $tag
* #return Service
*/
public function removeTag(Tag $tag)
{
if ($this->tagList->contains($tag)) {
$this->tagList->removeElement($tag);
$tag->removeService($this);
}
return $this;
}
}
Tag class
{
/**
* #ORM\ManyToMany(targetEntity="Service", inversedBy="tagList")
* #ORM\JoinTable(name="tags_services")
*/
private $serviceList;
/**
* #param Service $service
* #return Tag
*/
public function addService(Service $service)
{
if ($this->serviceList->contains($service) == false) {
$this->serviceList->add($service);
$service->addTag($this);
}
return $this;
}
/**
* #param Service $service
* #return Tag
*/
public function removeService(Service $service)
{
if ($this->serviceList->contains($service)) {
$this->serviceList->removeElement($service);
$service->removeTag($this);
}
return $this;
}
}
ServiceController
public function newAction(Request $request)
{
$service = new Service();
$form = $this->createForm('AppBundle\Form\ServiceType', $service);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($service);
$em->flush();
return $this->redirectToRoute('service_show', array('id' => $service->getId()));
}
return $this->render('AppBundle:Service:new.html.twig', array(
'service' => $service,
'form' => $form->createView(),
));
}
Could you please try to implement code from this URL?
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#owning-and-inverse-side-on-a-manytomany-association
First, please try to change mapped/inverse sides, and remove $service->addTag($this); from Tag::addService method.
Short version:
I just ran into this problem and solved it by adding a setter for the affected property:
Could not determine access type for property "tagList"
public function setTagList(Array $tagList)
{
$this->tagList = $tagList;
}
Long version:
The error message is signaling that Symfony is trying to modify the object's state, but cannot figure out how to actually make the change due to the way its class is set up.
Taking a look at Symfony's internals, we can see that Symfony gives you 5 chances to give it access and picks the best one in this order from top to bottom:
A setter method named setProperty() with one argument:
This is the first thing Symfony checks for and is the most explicit way to achieve this. As far as I'm aware this is the best practice:
class Entity {
protected $tagList;
//...
public function getTagList()
{
return $this->tagList;
}
//...
}
A combined getter and setter in one method with one argument:
It's important to realize that this method will also be accessed by Symfony in order to get the object's state. Since those method calls don't include an argument, the argument in this method must be optional.
class Entity {
protected $tagList;
//...
public function tagList($tags = null)
{
if($reps){
$this->tagList = $tags;
} else {
return $this->tagList;
}
}
//...
}
The affected property being declared as public:
class Entity {
public $tagList;
//... other properties here
}
A __set magic method:
This will affect all properties rather than just the one you intended.
class Entity {
public $tagList;
//...
public function __set($name, $value){
$this->$name = $value;
}
//...
}
A __call magic method (in some cases):
I wasn't able to confirm this, but the internal code suggests this is possible when magic is enabled on PropertyAccessor's construction.
Only using one of the above strategies is required.
Maybe the problem is that Symfony can't access that property?
If you look at where that exception is thrown (writeProperty method in the PropertyAccessor class) it says it can be thrown:
If the property does not exist or is not public.
In the tutorial you mentioned it has property $tags, and method addTag. I'm just guessing here, but maybe there's a convention where it tries to call a method names add($singularForm) and this is failing for you because the property is tagList and the method is addTag.
I'm not 100% sure, but you could try debugging by setting a stop point in that Symfony method to see why it's being thrown.
Maybe you forgot in the __construct() of Service class and Tag class to initialize $tagList and $serviceList like this ?
$this->tagList = new ArrayCollection();
$this->serviceList = new ArrayCollection();
This seems like an error with your constructor. Try this :
public function __construct()
{
$this-> tagList = new \Doctrine\Common\Collections\ArrayCollection();
}
It's a long shot, but looking at your annotations I think the problem might be related to your manyToMany relationship. Try to change the owning side and inverse side (Swap the relationship) unless you specifically need to update from both ends (In that case I think the only solution is to add the objects manually or use oneToMany relationships).
Changes made only to the inverse side of an association are ignored.
Make sure to update both sides of a bidirectional association (or at
least the owning side, from Doctrine’s point of view)
This is a problem related to Doctrine I have suffered before, see:
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/unitofwork-associations.html
Based on Symfony 3.3.10
I actually faced this problem many and many times, finally once i discovered where this problem was coming from, depending on the name you give to your entity property it can happen that the adder and the remover for your collection property aren't exactly what you are expecting.
Example: Your entity properity name is "foo" and you would expect the adder to be called "addFoo" and remover "removeFoo", but then all of a sudden the "Could not determine access type for property" appear.
So you start going into fear searching for w/e problems in your code, instead you just have to look this file inside Symfony core files:
vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php
Inside this file there's a method called findAdderAndRemover.
Go there with your debugger and you will eventually find out that symfony searches for weird name for your adder/remover, they may actually end with "um" or "on" or "us" depending on the language (human language) you used to name them. Since i'm Italian this happen quite often.
Watch out for that, since the fix may be as simple as changing the name used for your add/remove method inside your entity to make them match with what Symfony core is looking for.
This happens to me when i use bin/console doctrine:generate:entities to create the methods automatically for me
If you are using symfony, and use EntityRepository instead of CollectionType, make sure you use the 'multiple' => true, on your form build, otherwise the input will be for one entity and not for many, therefore it will call the setTagList instead of using the methods addTagList and removeTagList.
When unit testing with RavenDb, it is often the case that newly added data is retrieved or otherwise processed. This can lead to 'stale index' exceptions e.g.
Bulk operation cancelled because the index is stale and allowStale is false
According to a number of answers
How should stale indexes be handled during testing?
WaitForNonStaleResults per DocumentStore
RavenDb : Update a Denormalized Reference property value
The way to force the database (the IDocumentStore instance) to wait until its indexes are not stale before processing a query or batch operation is to use DefaultQueryingConsistency = ConsistencyOptions.QueryYourWrites during the IDocumentStore initialisation, like this:
public class InMemoryRavenSessionProvider : IRavenSessionProvider
{
private static IDocumentStore documentStore;
public static IDocumentStore DocumentStore
{
get { return (documentStore ?? (documentStore = CreateDocumentStore())); }
}
private static IDocumentStore CreateDocumentStore()
{
var store = new EmbeddableDocumentStore
{
RunInMemory = true,
Conventions = new DocumentConvention
{
DefaultQueryingConsistency = ConsistencyOptions.QueryYourWrites,
IdentityPartsSeparator = "-"
}
};
store.Initialize();
IndexCreation.CreateIndexes(typeof (RavenIndexes).Assembly, store);
return store;
}
public IDocumentSession GetSession()
{
return DocumentStore.OpenSession();
}
}
Unfortunately, the code above does not work. I am still receiving exceptions regarding stale indexes. These can be resolved by putting in dummy queries that include .Customize(x => x.WaitForNonStaleResultsAsOfLastWrite()).
This is fine, as long as these can be contained in the Unit Test, but what if they can't? I am finding that these WaitForNonStaleResults* calls are creeping into production code just so I can get unit-tests to pass.
So, is there a sure fire way, using the latest version of RavenDb, to force the indexes to freshen before allowing commands to be processed - for the purposes of unit testing only?
Edit 1
Here is a solution based on the answer give below that forces a wait until the index is not stale. I have written it as an extension method for the sake of unit-testing convenience;
public static class IDocumentSessionExt
{
public static void ClearStaleIndexes(this IDocumentSession db)
{
while (db.Advanced.DatabaseCommands.GetStatistics().StaleIndexes.Length != 0)
{
Thread.Sleep(10);
}
}
}
And here is a Unit Test that was using the verbose WaitForNonStaleResultsAsOfLastWrite technique but now uses the neater extension method.
[Fact]
public void Should_return_list_of_Relationships_for_given_mentor()
{
using (var db = Fake.Db())
{
var mentorId = Fake.Mentor(db).Id;
Fake.Relationship(db, mentorId, Fake.Mentee(db).Id);
Fake.Relationship(db, mentorId, Fake.Mentee(db).Id);
Fake.Relationship(db, Fake.Mentor(db).Id, Fake.Mentee(db).Id);
//db.Query<Relationship>()
// .Customize(x => x.WaitForNonStaleResultsAsOfLastWrite())
// .Count()
// .ShouldBe(3);
db.ClearStaleIndexes();
db.Query<Relationship>().Count().ShouldBe(3);
MentorService.GetRelationships(db, mentorId).Count.ShouldBe(2);
}
}
If you have a Map/Reduce index, DefaultQueryingConsistency = ConsistencyOptions.QueryYourWrites won't work. You need to use an alternative method.
In your units tests, call code like this, straight after you've inserted any data, this will force the all indexes to update before you do anything else:
while (documentStore.DatabaseCommands.GetStatistics().StaleIndexes.Length != 0)
{
Thread.Sleep(10);
}
Update You can of course put it in an extension method if you want to:
public static class IDocumentSessionExt
{
public static void ClearStaleIndexes(this IDocumentSession db)
{
while (db.Advanced.DatabaseCommands.GetStatistics().StaleIndexes.Length != 0)
{
Thread.Sleep(10);
}
}
}
Then you can say:
db.ClearStaleIndexes();
You can actually add a query listener on the DocumentStore to wait for nonstale results. This can be used just for unit tests as it is on the document store and not each operation.
// Initialise the Store.
var documentStore = new EmbeddableDocumentStore
{
RunInMemory = true
};
documentStore.Initialize();
// Force queries to wait for indexes to catch up. Unit Testing only :P
documentStore.RegisterListener(new NoStaleQueriesListener());
....
#region Nested type: NoStaleQueriesListener
public class NoStaleQueriesListener : IDocumentQueryListener
{
#region Implementation of IDocumentQueryListener
public void BeforeQueryExecuted(IDocumentQueryCustomization queryCustomization)
{
queryCustomization.WaitForNonStaleResults();
}
#endregion
}
#endregion
(Shamelessly stolen from RavenDB how to flush?)
Be aware that StaleIndexes also include abondoned and disabled indices - which will never get up to date.
So to avoid waiting indefinetely use this property instead:
var staleIndices = store.DatabaseCommands.GetStatistics().CountOfStaleIndexesExcludingDisabledAndAbandoned;
I've isolated the behaviour into the following test case. I'd be grateful to anyone who can tell me how to expect/verify a property set for a List<T> property - it appears there's something going on inside It.Is<T>(predicate) that isn't making a whole lot of sense to me right now. Sample code will run as a console app from VS2008 - you'll need to add a reference to Moq 2.6 (I'm on 2.6.1014.1) - please try uncommenting the different ExpectSet statements to see what's happening...
using System;
using Moq;
using System.Collections.Generic;
namespace MoqDemo {
public interface IView {
List<string> Names { get; set; }
}
public class Controller {
private IView view;
public Controller(IView view) {
this.view = view;
}
public void PopulateView() {
List<string> names = new List<string>() { "Hugh", "Pugh", "Barney McGrew" };
view.Names = names;
}
public class MyApp {
public static void Main() {
Mock<IView> mockView = new Mock<IView>();
// This works - and the expectation is verifiable.
mockView.ExpectSet(mv => mv.Names);
// None of the following can be verified.
// mockView.ExpectSet(mv => mv.Names, It.Is<Object>(o => o != null));
// mockView.ExpectSet(mv => mv.Names, It.Is<List<string>>(names => names.Count == 3));
// mockView.ExpectSet(mv => mv.Names, It.IsAny<IList<String>>());
Controller controller = new Controller(mockView.Object);
controller.PopulateView();
try {
mockView.VerifyAll();
Console.WriteLine("Verified OK!");
} catch (MockException ex) {
Console.WriteLine("Verification failed!");
Console.WriteLine(ex.Message);
}
Console.ReadKey(false);
}
}
}
}
I'm not using the very latest version of Moq, so I don't have an overload of ExpectSet that takes two parameters, but I've had some success with this pattern:
mockView.ExpectSet(mv => mv.Names).Callback(n => Assert.That(n != null));
The Assert (from NUnit) call in the callback will throw an exception if the value assigned to .Names doesn't match the predicate. It does make it hard to trace when a test fails, though. I agree that the ability to pass an It.Is or It.IsAny as the second parameter would be handy.
The second parameter of ExpectSet() is the value you're expecting. You can't use It.Is<T> in this case as there's no overload that takes a predicate - though it would be nice ;) Here's a (simplified) excerpt from your sample, illustrating the use of a value:
var mockView = new Mock<IView>();
var list = new List<string> { "Hugh", "Pugh", "Barney McGrew" };
mockView.ExpectSet(mv => mv.Names, list);
mockView.Object.Names = list;
Hope that helps.
Edit: fixed typo.
BTW, It.Is is not supported on ExpectSet. Your code compiles just because they are regular method invocations when used as values (as opposed to expressions), whereas when used in an Expect expression they are pre-processed by Moq and given specific meaning (rather than the null/default value that all It.Is members actually return).
You could use the stub behavior on the given property (mockView.Stub(mv => mv.Names)) and later assert directly for its value after execution.
Moq doesn't provide an overload receiving It.IsAny as it's effectively the same as calling ExpectSet without passing an expected value ;)