Editing the name parameter of #java.persitence.Entity through external jaxb-Binding - maven

I have the following constellation:
B1.xsd and B2.xsd both import A.xsd. Using maven-hyperjaxb3-plugin I created Java classes with JPA annotations for both B1.xsd and B2.xsd. So the classes of A.xsd are created in the project of B1.xsd as well es in the project of B2.xsd.
In order to use this two sets of classes in one persistence unit, I set through jaxb external binding the database schema on each Entity, like shown in Editing #java.persitence.Table in external jaxb-Binding.
The problem is, after deploying to wildfly, wildfly throws org.hibernate.DuplicateMappingException: duplicate import: B1_ClassName refers to both B1_ClassName and B2_ClassName (try using auto-import=\"false\")"}}
So what I need to do is editing the name parameter of the Entity annotation through jaxb external binding so that
#XmlRootElement(name = "B1_Element1")
#Immutable
#Cacheable(true)
#Entity(name = "B1_Element1")
#Table(name = "B1_Element1")
public class B1_Element1
implements Serializable, Equals, HashCode, ToString
{
...
}
will look like
#XmlRootElement(name = "B1_Element1")
#Immutable
#Cacheable(true)
#Entity(name = "PACKAGE_NAME.B1_Element1")
#Table(name = "B1_Element1")
public class B1_Element1
implements Serializable, Equals, HashCode, ToString
{
...
}
My actual bindings-xjc.xjb looks like this
<jaxb:globalBindings localScoping="toplevel">
<xjc:serializable />
</jaxb:globalBindings>
<jaxb:bindings schemaLocation="B1.xsd"
node="/xs:schema">
<hj:persistence>
<hj:default-generated-id name="Hjid">
<orm:generated-value strategy="IDENTITY" />
</hj:default-generated-id>
<hj:default-entity>
<orm:table schema="B1_database_schema" />
</hj:default-entity>
</hj:persistence>
<jaxb:schemaBindings>
<jaxb:package name="b1.package.name" />
</jaxb:schemaBindings>
</jaxb:bindings>
Anybody has an idea how I can edit the name parameter of #java.persitence.Entity?

Disclaimer: I am the author of Hyperjaxb.
The answer is that you should not need to customize this. I.e. if you need to customize this, something is wrong.
The problem that you're facing is because you generate two sets of classes for your A.xsd schema, probably in different packages. This can be the case if you're either have chameleon schema (A.xsd has no target namespace) or if you just compile it twice because you have B1.xsd and B2.xsd.
The correct solution is not to compile A.xsd twice. I hope you don't have chameleon schema (this is a very bad design pattern for JAXB). In this case you can either compile A.xsd, B1.xsd and B2.xsd together or you can compile all of the separately. You can compile A.xsd first and the use it as an episode in B1 and B2. See Using Episodes on how it works.
In any case you should not produce different packages for A.xsd classes.
To answer your specific question - try customizing your complex types with:
<hj:entity name="MyUniqueName"/>
I think this should override the automatically generated name. However that's not the way to go.
ps. Here's a test project for episodes:
https://github.com/highsource/hyperjaxb3/tree/master/ejb/tests/episodes

Related

Spring autoconfigurations, #ConditionalOnBean with a #Repository

I have a starter module which expose a marker interface along with some repository:
interface AwesomeRepo
...
internal interface FakeRepository: Repository<JPAStub, String>, AwesomeRepo {
fun count(): Long
}
#Entity
class JPAStub(#Id val name: String)
#Configuration(proxyBeanMethods = false)
#ConditionalOnBean(EntityManagerFactory::class)
#AutoConfigureAfter(JpaRepositoriesAutoConfiguration::class)
#EnableJpaRepositories(basePackageClasses = [FakeRepository::class])
#EntityScan(basePackageClasses = [FakeRepository::class])
class AwesomePersistenceAutoConfiguration
In another module, I have an auto configuration which depends on the AwesomeRepo to instantiate the AwesomeApplicationService
#Configuration(proxyBeanMethods = false)
class AwesomeAutoConfiguration {
#Bean
#ConditionalOnMissingBean
#ConditionalOnBean(AwesomeRepo::class)
fun awesomeAppService(awesomeRepo: AwesomeRepo) =
AwesomeApplicationService(awesomeRepo)
I import both autoconfigure starters in a root project.
I observe:
AwesomeApplicationService cannot be instantiated because AwesomeRepo bean cannot be found
When enabling debug through debug=true:
AwesomeAutoConfiguration #awesomeAppService:
Did not match:
- #ConditionalOnBean (types: *****.AwesomeRepo; SearchStrategy: all) did not find any beans of type *******.AwesomeRepo(OnBeanCondition)
I tried adding #AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) to AwesomePersistenceAutoConfiguration and #AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE) to AwesomeAutoConfiguration. It did not change the issue
When I remove the #ConditionOnBean(AwesomeRepo::class), the AwesomeApplicationService is correctly instantiated with the repository and everything is fine.
Why does the #ConditionOnBean(AwesomeRepo::class) does not detect the AwesomeRepo bean?
EDIT: After more trials and errors, it seems order was causing the issue, applying accepted answer worked. If someone needs to go further there is a baseline of code illustrating the issue here: https://github.com/Nimamoh/spring-autoconfigurations-conditionalonbean-with-a-repository (accepted answer is on snic-answer branch)
AwesomeAutoConfiguration should be ordered after AwesomePersistenceAutoConfiguration so that the bean definitions for the repositories are processed before the condition kicks in.
There is a note in #ConditionalOnBean about this specifically:
The condition can only match the bean definitions that have been processed by the application context so far and, as such, it is strongly recommended to use this condition on auto-configuration classes only. If a candidate bean may be created by another auto-configuration, make sure that the one using this condition runs after.
You can use #AutoConfigureAfter(AwesomePersistenceAutoConfiguration.class) on AwesomeAutoConfiguration to order things properly.

Autowire using "byName" ignores the autowire-candidate=false configuration

According to this section of Spring Framework Reference documentation, when autowire-candidate is set to false in a bean's XML definition, it excludes the bean from the autowiring infrastructure. The section doesn't talk about any exceptions to this case.
This works when autowire is set to byType. But when it is set to byName, the autowire-candidate="false" configuration is ignored and the bean is still autowired.
My question is:
Is this by design and not documented (or)
Is it a bug (or)
Am I missing something in my configuration?
Following is the list of relevant source listings:
MovieDataStore.java
public class MovieDataStore {
// Just some dummy class
}
MovieDao.java
public class MovieDao {
private MovieDataStore movieDataStore;
public MovieDataStore getMovieDataStore() {
return movieDataStore;
}
public void setMovieDataStore(MovieDataStore movieDataStore) {
this.movieDataStore = movieDataStore;
}
}
spring-context.xml snippet
<bean id="movieDao" class="com.example.spring.MovieDao" autowire="byName"/>
<bean id="movieDataStore" class="com.example.spring.MovieDataStore"
autowire-candidate="false"/>
Testing code
ClassPathXmlApplicationContext ctx;
ctx = new ClassPathXmlApplicationContext("spring-context.xml");
MovieDao movieDao = ctx.getBean("movieDao", MovieDao.class);
System.out.println(movieDao.getMovieDataStore());
ctx.close();
I am expecting it to print null because the only dependency that I asked to autowire is actually excluded from autowiring. But, the above testing code prints this:
com.example.spring.MovieDataStore#22915056
Note that this happens only in case of autowire byName. If I autowire byType, it prints null as expected.
I am using Spring Framework version 4.3.5.RELEASE and Java 7.
According to this Spring JIRA ticket which I raised, it is by design and not documented.
Comment from Juergen Hoeller on the ticket:
This is an old design decision where autowire-candidate="false" only affects type-based autowiring attempts, not direct references by name... and not autowire="byName" either. While the latter may be debatable, I'm not inclined to change it at this point since autowire="byName" is an outdated mechanism to begin with. I'm therefore turning this into a documentation issue.

Spring could not create EntityManagerFactory after upgrading to Hibernate 5.x

I'm using latest springframework disto v4.2.5.RELEASE and Hibernate v5.0.7.Final when spring loads EntityManagerFactory i'm getting the below exception
Caused by: org.hibernate.HibernateException: Not all named super-types (extends) were found : [com.sample.model.Sample]
at org.hibernate.boot.model.source.internal.hbm.EntityHierarchyBuilder.buildHierarchies(EntityHierarchyBuilder.java:76)
at org.hibernate.boot.model.source.internal.hbm.HbmMetadataSourceProcessorImpl.<init>(HbmMetadataSourceProcessorImpl.java:66)
at org.hibernate.boot.model.source.internal.hbm.HbmMetadataSourceProcessorImpl.<init>(HbmMetadataSourceProcessorImpl.java:40)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.<init>(MetadataBuildingProcess.java:142)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:141)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874)
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:343)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:319)
The same code was working with v4.2.5.RELEASE and Hibernate v.4.3.10.
I know Hibernate changed core metadata building in v5.x, is there anything needs to be specified in spring config of JPA/EntityManagerFactory/Hibernate Properties to make it work with Hibernate 5.x?
#Entity
#Table(name = "tbl_sample")
public class Sample extends Auditable {
private Long id;
#ManyToOne
#JoinColumn(name = "relationA", nullable = true)
private RelationA relationA;
... etc
}
#MappedSuperClass
public abstract class Auditable extends Persistable {
//audit props
}
#MappedSuperClass
public abstract class Persistable {
//common props
}
I could able to narrow down the issue after enabling trace log, there was one more class which is extending Sample Class and its mapped using hbm.xml like below
<hibernate-mapping package="com.sample.model">
<joined-subclass name="BloodSample" table="tbl_blood_sample"
extends="com.sample.model.Sample">
<key column="ID" />
<property name="sampleNo" column="sampleNo"/>
etc....
</joined-subclass>
The moment i removed this relation hbm it started working... Still wondering why its happening now which was not in older version of hibernate.
So i guess this issue is nothing to do with spring but something related hibernate. Any insight ?
I have a similar your issue.
You try to class tag instead joined-subclass tag in hbm.xml file

Why is Mybatis mapper scanner picking up wrong class

I use Spring with Mybatis. I have it configured to scan for mappers in my whole project and I assumed it determined a mapper because it found an XML file which has reference to a java interface.
But this is proven incorrect today because I had to add a new interface which is not a mapper class and Mybatis thinks it is, so it is causing problems in my app due to this error:
Mapped Statements collection does not contain value for com.blah.MyInterface.someMethod
com.blah.MyInterface is just a simple interface which I needed to be included in Spring context so I gave it the #Component tag. Is that the wrong tag to use? Is that where the confusion comes from?
I just needed to create this interface so that I can have a proxy wrap my database calls in one place where I can put a #Transactional tag, since Spring ignores it when it is in my Controller method.
Sample code
package com.blah.something;
#Component public interface MyInterface {
public void someMethod( SomeObject obj) throws Exception;
}
package com.blah.something;
public class MyImplementation implements MyInterface {
#Transactional
public void someMethod( SomeObject obj) throws Exception {
... do a whole bunch of stuff
}
}
I dont want this included in the MyBatis mappers!
Edit: added the mybatis config xml as requested:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="lazyLoadingEnabled" value="false" />
<setting name="defaultStatementTimeout" value="60"/>
</settings>
<typeAliases>
<typeAlias alias="StripTrailingZerosBigDecimalTypeHandler" type="com.blah.typehandlers.StripTrailingZerosBigDecimalTypeHandler"/>
</typeAliases>
</configuration>
This is the part of my spring xml config which calls the mybatis mapper scanner:
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.blah" />
</bean>
So I set it to scan the whole project which includes my interface above but I can't imagine it just grabs every single interface and considers them all mappers!
In my debug log I see mybatis picking up my interface:
12/9/13 11:18:44 904 [org.mybatis.spring.mapper.MapperScannerConfigurer$Scanner.findCandidateComponents:4125] - Scanning file [D:\Weblogic\wls11\domains\ldapdomain\autodeploy\default\WEB-INF\classes\com\blah\MyInterface.class]
12/9/13 11:18:44 904 [org.mybatis.spring.mapper.MapperScannerConfigurer$Scanner.findCandidateComponents:4125] - Identified candidate component class: file [D:\Weblogic\wls11\domains\ldapdomain\autodeploy\default\WEB-INF\classes\com\blah\MyInterface.class]
12/9/13 11:18:44 904 [org.mybatis.spring.mapper.MapperScannerConfigurer$Scanner.findCandidateComponents:4125] - Scanning file [D:\Weblogic\wls11\domains\ldapdomain\autodeploy\default\WEB-INF\classes\com\blah\MyImplementation .class]
12/9/13 11:18:44 904 [org.mybatis.spring.mapper.MapperScannerConfigurer$Scanner.findCandidateComponents:4125] - Ignored because not a concrete top-level class: file [D:\Weblogic\wls11\domains\ldapdomain\autodeploy\default\WEB-INF\classes\com\blah\MyImplementation .class]
There is no XML for this interface, there is no mapper namespace for it, it's just a plain old regular interface and MyBatis should not be thinking it is a mapper service
Ok it looks like MyBAtis scanner does indeed take every interface, it does not have any "smarts" in it to identify mapper interfaces as I thought it would - based on finding matching XML or namespaces. I had to add a filter to the mapper configuration and then introduce a new annotation to annotate my mapper interfaces.

Scan specific packages for Spring AOP

I'm trying to use AOP into an existing (big) Spring project. The thing is that I don't want Spring to create proxies for all the objects in the ApplicationContext, mainly for performance but also because there are final classes that I cannot modify.
I've tried to make Spring search only inside "com.foo.bar.*" by defining the following aspect:
com.baz.MyAspect
#Aspect
public class MyAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(MyAspect.class);
#Before("within(com.foo.bar.*) && " +
"execution(* com.foo.bar.MyController.handleRequest(..))")
public void getData() {
// Nothing yet
}
}
And I've added this lines to the configuration:
<?xml version="1.0" encoding="utf-8"?>
<beans ...>
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean id="myAspect" class="com.baz.MyAspect"/>
</beans>
But when I run the app, I get the following Exception:
Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.foobar.FinalController]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class com.foobar.FinalController
So it seems that Spring is scanning packages other than the ones defined in the within expression. I would like to know whether there is a way to specify the packages to be scanned or any other way to solve this problem.
yes you can define your point cut like this
the execution of any method defined in the bar package or a sub-package:
execution(* com.foo.bar...(..)) click here for detail

Resources