I am using datanucleus JDO API for persisting objects.
my orm file looks like this:
<class name="MyClass" table="mytable">
<inheritance strategy="complete-table"/>
<field name="id" column="id" primary-key="true" value- strategy="AUTO_INCREMENT"/>
</class>
I have an inheritance hierarchy of
#PersistenceCapable
public class MyClass extends NonAbstractMyClassParent {
}
public class NonAbstractMyClassParent extends AbstractMyClassParent
{
}
public class AbstractMyClassParent
{
private Long id;
}
The id is defined in the MyClassAbstractParent.
MyClassParent does NOT have a corresponding table in the database.
When I try to persist the MyClass, I get the below error. I tried making the MyClassParent also abstract but still I get the same error.
Any insights please?
TIA
javax.jdo.JDOException: Metadata for member "com.xxx.MyClass.id" is attempting to illegally override the primary-key setting of its "root" metadata definition (annotations or ".jdo" XML file). You must specify primary-key information in the "root" metadata definition
at org.datanucleus.api.jdo.JDOPersistenceManagerFactory.initialiseMetaData(JDOPersistenceManagerFactory.java:772)
at org.datanucleus.api.jdo.JDOPersistenceManagerFactory.(JDOPersistenceManagerFactory.java:564)
at org.datanucleus.api.jdo.JDOPersistenceManagerFactory.createPersistenceManagerFactory(JDOPersistenceManagerFactory.java:308)
at org.datanucleus.api.jdo.JDOPersistenceManagerFactory.getPersistenceManagerFactory(JDOPersistenceManagerFactory.java:217)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at javax.jdo.JDOHelper$16.run(JDOHelper.java:1975)
Move
<field name="id" column="id" primary-key="true" value- strategy="AUTO_INCREMENT"/>
to the class that defines that field, namely AbstractMyClassParent (whilst also marking it as persistence capable).
Related
I have this class
class ScanRequest4Command implements Validateable {
String _ScanType
static constraints = {
pScanType inList:["a", "b"]
}
}
this code worked fine in grails 2.4.4
lately, we started upgrading to grails 3.1.16
now when I try to run the code if fails and throw the following exception:
java.lang.IllegalArgumentException: object is not an instance of declaring class
at com.evercompliant.commands.v4.ScanRequest4Command$__clinit__closure9.doCall(ScanRequest4Command.groovy:151)
at com.evercompliant.commands.v4.ScanRequest4Command$__clinit__closure9.doCall(ScanRequest4Command.groovy)
at com.evercompliant.commands.v4.ScanRequest4Command$__clinit__closure9.call(ScanRequest4Command.groovy)
at com.evercompliant.commands.v4.ScanRequest4Command$__clinit__closure9.call(ScanRequest4Command.groovy)
at com.evercompliant.commands.v4.ScanRequest4Command.validate(ScanRequest4Command.groovy)
at com.evercompliant.commands.v4.ScanRequest4Command.validate(ScanRequest4Command.groovy)
at com.evercompliant.commands.v4.Base4Command.validateWithErrors(Base4Command.groovy:98)
at com.evercompliant.commands.v4.PortfolioManagementBase4Command.validateWithErrors(PortfolioManagementBase4Command.groovy)
at com.evercompliant.commands.v4.ScanRequest4Command.super$2$validateWithErrors(ScanRequest4Command.groovy)
at com.evercompliant.commands.v4.ScanRequest4Command.validateWithErrors(ScanRequest4Command.groovy:164)
at com.evercompliant.commands.v4.ScanRequest4Command$validateWithErrors.call(Unknown Source)
at com.evercompliant.data.Merchant.withTransaction(Merchant.groovy)
at com.evercompliant.data.Merchant$withTransaction.call(Unknown Source)
at com.evercompliant.utils.CorsFilter.doFilterInternal(CorsFilter.java:35)
which did not help much.
if I remove the inList constraint the code passes, meaning the problem is in the inList constraint.
so after test-and-failed, I found out the if I change the member's name to pScanType the code passes.
so my question is this:
is the underscore not allowed in member name prefix? if so is it
documented anywhere? if not then what is the problem with the code?
I am trying to create service in symfony2 which will verify if session contains certain information and if not redirect the user to another controller. I want this piece of code to work as a service as I will be using it in many controllers.
I have problem as manual on Symfony2 book does not provide information how service file should look like. Should it be a normal php class?
Please find below dump of my files with information on error that I receive.
In \AppBundle\Services I create file my_isbookchosencheck.php containing:
<?php
namespace AppBundle\my_isbookchosencheck;
class my_isbookchosencheck
{
public function __construct();
{
$session = new Session();
$session->getFlashBag()->add('msg', 'No book choosen. Redirected to proper form');
if(!$session->get("App_Books_Chosen_Lp")) return new RedirectResponse($this->generateUrl('app_listbooks'));
}
}
My service.yml:
my_isbookchosencheck:
class: AppBundle\Services\my_isbookchosencheck
My conntroller file:
/**
* This code is aimed at checking if the book is choseen and therefore whether any further works may be carried out
*/
$checker = $this->get('my_isbookchosencheck');
Error:
FileLoaderLoadException in FileLoader.php line 125: There is no extension able to load the configuration for "my_isbookchosencheck" (in C:/wamp/www/symfony_learn/app/config\services.yml). Looked for namespace "my_isbookchosencheck", found "framework", "security", "twig", "monolog", "swiftmailer", "assetic", "doctrine", "sensio_framework_extra", "fos_user", "knp_paginator", "genemu_form", "debug", "acme_demo", "web_profiler", "sensio_distribution" in C:/wamp/www/symfony_learn/app/config\services.yml (which is being imported from "C:/wamp/www/symfony_learn/app/config\config.yml").
There are few mistakes that you made, which I am going to explain in short, and I will give you an example of the service you want to create.
You created your service in AppBundle\Services, yet your namespace is registered differently - namespace AppBundle\Services\my_isbookchosencheck;. It should be namespace AppBundle\Services;. I would also advise you to use singular names when creating directories - in this case Service would be better, instead of Services.
You're using your __constructor directly to apply some logic and return the result of it. Better way would be to create a custom method, which could be accessed when necessary.
You're creating new instance of Session which means that you wont be able to access anything that was previously added and stored in session. The right way here, would be to inject RequestStack which holds the current Request and get the session from there.
I believe you also registered your service wrong. In your services.yml file, it should be under services: option. This is why you got the error you pasted.
So, let's see how your service should like.
services.yml
services:
book_service:
class: AppBundle\Service\BookService
arguments:
- #request_stack
- #router
BookService.php
namespace AppBundle\Service;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\RouterInterface;
class BookService {
/* #var $request Request */
private $request;
/* #var $router RouterInterface */
private $router;
public function __construct(RequestStack $requestStack, RouterInterface $router) {
$this->request = $requestStack->getCurrentRequest();
$this->router = $router;
}
public function isBookChoosen() {
$session = $this->request->getSession();
// Now you can access session the proper way.
// If anything was added in session from your controller
// you can access it here as well.
// Apply your logic here and use $this->router->generate()
}
}
Now in your controller you can simply use it like this:
$this->get('book_service')->isBookChoosen()
Well this is a short example, but I hope you got the idea.
try
services:
my_isbookchosencheck:
class: AppBundle\Services\my_isbookchosencheck
in your services.yml, and check that you use the correct namespaces.
Your Class is fine and it should work, however may i suggest that you use
symfony2 session service instead of creating the session object yourself, you can pass it as a constructor argument:
<?php
// namespace edited
namespace AppBundle\Services;
use Symfony\Component\HttpFoundation\Session\Session;
class my_isbookchosencheck
{
public function __construct(Session $session);
{
$session->getFlashBag()->add('msg', 'No book choosen. Redirected to proper form');
if(!$session->get("App_Books_Chosen_Lp")) return new RedirectResponse($this->generateUrl('app_listbooks'));
}
}
and then edit your services.yml accordingly, so the service container will inject the session object:
services:
my_isbookchosencheck:
class: AppBundle\Services\my_isbookchosencheck
arguments: [#session]
Also check out his question on so:
How do you access a users session from a service in Symfony2?
Services are just regular PHP classes, nothing special. But you must register it in order to be recognized by the system. Here are the steps how you do it,
Create a regular PHP class (you can inject other services if it requires)
namespace Acme\DemoBundle\Service;
class MyService
{
private $session;
public function _construct(SessionInterface $session /* here we're injecting the session service which implements the SessionInterface */)
{
$this->session = $session;
}
// other methods go here, which holds the business logic of this class
}
ok, we created a class, we need to register it to be able to use it by service container, here how you do it:
the simplest way is to put it into config.yml file, like this:
services:
my_service:
class: Acme\DemoBundle\Service\MyService
arguments:
- #session
or, another way, is to create a file (e.g. services.yml, may be in config folder), and import it inside the config.yml file (the content of the file is the same as the first way):
imports:
- { resource: services.yml }
or, you can create a services.yml(the content of the file is the same as the first way) file inside you bundle's Resources folder, specify it under the load method of your Extension class (under the DependencyInjection folder), (this way requires some special directory and file structure, read about it in the doc):
class AcmeDemoExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
$loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources'));
$loader->load('services.yml');
}
}
In you case, you're not registering your service, the service container just couldn't find it. Register it by one of the above ways.
I am trying to implement a custom repository class in symfony2, and I want it to extend EntityRepository class. I am having trouble with passing the getting arguments to the parent (i.e. EntityRepository) constructor. This is the signiture of parent constructor:
public function __construct($em, Mapping\ClassMetadata $class)
So I had to add this to my services.yml file, in order to get the arguments:
parameters:
user_provider.class: Untitled\F5Bundle\Security\UserRepository
services:
user_meta_data:
class: Doctrine\ORM\Mapping\ClassMetaData
arguments:
name: "Untitled\F5Bundle\Entity\User"
user_provider:
class: "%user_provider.class%"
arguments:
entityManager: "#doctrine.orm.entity_manager"
meta_data: "#user_meta_data"
And I also added the annotation tag to my User class (which I'm not sure if it was neccessary)
Now when I run it, it raises an error. the message says:
FatalErrorException: Error: Class 'Doctrine\ORM\Mapping\ClassMetaData' not found
in /mnt/data/Projects/F5/app/cache/dev/appDevDebugProjectContainer.php line 2749
(/mnt/data/Projects/F5/ is where I keep the code)
I don't get it. What's wrong here? What am I doing wrong?
Metadata is obtained with the MetadataFactory. As an example you can see how it works in EntityManager.
public function getClassMetadata($className)
{
return $this->metadataFactory->getMetadataFor($className);
}
You can retrieve you repository as service as well. Look at this question.
You don't need to inject these constructor arguments yourself, just specify which repository class you want to use:
/**
* #Entity(repositoryClass="MyProject\UserRepository")
*/
class User
{
...
}
See also http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/annotations-reference.html#entity
You miss typed classname "ClassMetaData" should be ClassMetadata
class: Doctrine\ORM\Mapping\ClassMetadata
in what file, or where ,is the mapping of controller to model occur in
symfony 1.4
symfony 2
are there any yml/config files that tell the system to recognize the appropriate model?
what I mean is:
let's say a controller looks like this:
class jobActions extends sfActions
{
public function executeIndex(sfWebRequest $request)
{
$user=new PcUser();
$user->username=$request->GetParameters(...);
}
}
and PcUser.php is an entity file that has PcUser class inside.
where is the mapping done? how does the controller jobActions know PcUser?
It's done by symfony's autoloader. If the script doesn't know about class you are trying to use, then autoloader try include appropriate class based on namespace.
So, for your example:
class SomeController
{
public function executeIndex(sfWebRequest $request)
{
$user=new \NamespaceForBundle\Entity\PcUser();
$user->username=$request->GetParameters(...);
}
}
And if you ask about ORM mapping - you can do it in several ways like appropriate yaml configuration file, or annotations inside entities.
What is the best way to have an event that fires after a record is inserted in Symfony2 / Doctrine?
First, register a service as a Doctrine event listener:
app/config.yml:
services:
foo.listener:
class: Vendor\FooBundle\BarClass
tags:
- { name: doctrine.event_listener, event: postPersist, method: onPostPersist }
Then in your listener class, define an onPostPersist method (or whatever you named the method in the config) that takes a Doctrine\ORM\Event\LifecycleEventArgs argument:
public function onPostPersist(LifecycleEventArgs $eventArgs)
{
// do stuff with the entity here
}
Note that you can't pass an instance of EntityManager to the listener class, because $eventArgs contains a reference to it, and doing so will throw a CircularReferenceException.
Doctrine Project documentation here. Symfony Project documentation here (out of date, but included for reference)/
Try injecting the container itself instead of the security context. with FOS_USER, security.context depends on your listener (EM) and your listener requires security.context.
<service id="foo.listener" class="%foo.listener.class%">
<argument type="service" id="service_container"/>
<tag name="doctrine.event_listener" event="postPersist" method="fooMethod" />
</service>
By the way, at least in XML, the method name does not seem to be working, by default it call the method 'postPersist' instead and ignore whatever method name you give (fooMethod); Please let me know if that's the case with YAML config, too, or I am just wrong.