lazy fetching problem - java

I have a problem with lazy fetching. here's what I have. I have a entity class called channel. and another entity class called show. Each channel has many show's. I've implemented hibernate with lazy fetching.But heres the problem, when I get a channel from database and after that try to access the programm list I get a nullpointerException.
Here's some code:
telekanalService.findAllTelekanal(new AsyncCallback<List<Telekanal>>() {
public void onFailure(Throwable caught) {
// Show the RPC error message to the user
errorLabel.setText(caught.getMessage());
}
public void onSuccess(List<Telekanal> result) {
//Programm tel = result.get(1);
List<Programm> prog = result.get(0).getProgrammid(); //problem with this
//Telekanal tell = tel.getTelekanal();
errorLabel.setText("tehtud:" + prog.size()); //returns Nullpointerexception
}
});
Maybe I have some mapping errors, here are my mapping files
Programm.hbm.xml:http://pastebin.com/Q639HreT
Telekanal.hbm.xml: http://pastebin.com/4c3h0fZj
Programm class:http://pastebin.com/ws57uGg2
Telekanal class:http://pastebin.com/MZB7KgT1
Or maybe I have problem in my sql setup: http://pastebin.com/AVBM8882
And also I'm using opensessioninview for keeping the session open
My code
Really hope that someone can help

<list name="programmid" inverse="false" table="programm" lazy="true">
<key>
<column name="t_id" />
</key>
<list-index></list-index>
<one-to-many class="com.tvkava.shared.model.Programm" />
</list>
Shouldn't declaring an empty list-index cause an error? I'm not sure how this would work.

Related

Store Java enums in Postgresql and Hibernate 6 using hbm.xml

I am unable to figure out how to store a Java Enum using a Postgresql Enum Type with Hibernate 6 and the legacy hbm.xml.
With Hibernate 5, I used to use the hiberate-types project with following XML:
<property name="type" column="Type" access="field">
<type name="com.vladmihalcea.hibernate.type.basic.PostgreSQLEnumType">
<param name="enumClass">"my-java-enum-type"</param>
<param name="useNamed">true</param>
</type>
</property>
But, this is not working with Hibernate 6 anymore. There is a documentation from the package's Author how to use it with annotations, but currently it is not feasible for us to switch to annotations (https://vladmihalcea.com/the-best-way-to-map-an-enum-type-with-jpa-and-hibernate/).
I would be glad if anyone could give a hint.
I solved the issue by writing my own type:
public class PersistentEnum<T extends Enum<T>> extends EnumType<T>
{
#Override
public void
nullSafeSet(PreparedStatement preparedStatement, T obj, int index, SharedSessionContractImplementor session) throws HibernateException,
SQLException
{
if(obj == null)
{
preparedStatement.setNull(index, java.sql.Types.OTHER);
}
else
{
preparedStatement.setObject(index, obj.toString(), java.sql.Types.OTHER);
}
}
}
With this, the former posted hbm.xml code is working.

How to unproxy child objects from org.springframework.data.repository.CrudRepository descendant

I have created a many-to-many relationship of users to projects in a MySQL database and have used hbm2java (the hibernate tool to generate java classes from the data base tables). Since I'm using the gradle plugin org.hibernate.gradle.tools.Schema I don't have a hibernate.cfg.xml.
I can fetch and correctly print the list of users from my descendant of CrudRepository<User,Long> (see my code below) and each user object has a getProjects() function. When I try to iterate the projects owned by the user, I get this error:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.xyz.dbmodel.orm.User.projects, could not initialize proxy - no Session
I want to stick with the default lazy loading approach used by java code generated by hbm2java.
I've tried calling Hibernate.Initialize(user.getProjects()) (as discussed at https://howtodoinjava.com/hibernate/use-hibernate-initialize-to-initialize-proxycollection/) but I still get the same error when I try to do
for(Project project : user.getProjects()) {... }
All the examples I could find seamed to assume I could execute the above for loop and unproxy each project. I cannot.
Here is my repository:
import org.springframework.data.repository.CrudRepository;
import com.xyz.dataservice.dbmodel.orm.User;
public interface UserRepository extends CrudRepository<User, Long> {}
Here I create the repository:
#Autowired com.xyz.repository.UserRepository userRepository;
Here I successfully fetch the list of users
Iterable<User> users = userRepository.findAll();
for(User user : users) {
log.info("User="+user.getName()); // this works!
Set<Project> projects = user.getProjects();
for(Project p : projects) // Error happens here!
{
log.info(" project="+p.getName());
}
}
The expected results are that I get a list of projects for each user.
The actual results are the exception org.hibernate.LazyInitializationException.
Thank you!
Feb 02 2019 Morning Update
Regarding Hibernate Configuration
I'm not sure what you mean. My gradle plugin is generating this hibernate.cfg.xml file:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration
SYSTEM "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306</property>
<property name="hibernate.connection.username">searchapp_user</property>
<property name="hibernate.connection.password">secret</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.connection.zeroDateTimeBehavior">convertToNull</property>
</session-factory>
</hibernate-configuration>
…
Adding Transactional
I have added org.springframework.transaction.annotation.Transactional to the new function I am calling
#Transactional
public int fetchUsers() {
Iterable<User> users = userRepository.findAll();
return listUsers(users, "");
}
When this did not help, I tried enhancing my repository with the Transactional attribute:
#Repository
public interface UserRepository extends CrudRepository<User, Long> {
#Transactional
public List<User> findAll();
}
Shucks, this did not help either.
I did notice this strange entry in the acres of log entries. What does it mean?
2019-02-01 10:50:42.285 INFO 5096 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$6c9c1be1] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
Thanks again!
Feb 02 2019 Afternoon Update
Oops, I forgot to check that link concerning the tranasactional documenation.
I'm not sure how to use #Bean and #Transactional on the same function.
Can you show me an example?
The #Bean examples I've seen return a lambda that is then called mysteriously later. Do I need the lambda to be declared transactional? Is that possible? If not, do I need to replace the lambda with a descendant of java.util.function.Consumer<> whose accept function is declared with #Transactional?
Feb 05 2019 Update: Solution Found!
I was using the new Java8 lambda syntax and I had to abandon it in favor of the older inner class syntax so I could declere the function #Transactional.
#Transactional
class InitSpecialCommandLineRunner implements org.springframework.boot.CommandLineRunner{
#Transactional // this is important!
#Override
public void run(String[] args) {
int count = listProjectsForEachUser(); // this works!
}
}
#org.springframework.context.annotation.Profile("initialize")
#org.springframework.context.annotation.Bean
#Transactional
public org.springframework.boot.CommandLineRunner initSpecial() {
return new InitSpecialCommandLineRunner(); // this works
// How to declare this transactional?
// return args ->
// {
// int count = fetchUsers();
// Iterable<User> users;
// };
}
I hope this will help someone else some day.
It looks like the transactions only span the immediate call to the repository.
To fix this put a #Transactional annotation on the method that should define your transaction scope.
At least the method that hosts the code you showed us.
That method needs to be public and on a Spring bean.
See https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html for details.

How to write to multiple tables per read row using Spring Batch with no conditions

I have found many examples to use multiple writers in this forum. Most, if not all, of the answers focus on CompositeItemWriter and ClassifierItemWriter.
Business Need: Read a single line from an input file. This line will contain multiple fields (over 50) which need to be written to their own database tables (in theory represent different classes).
----- claimwriter(write to claim table)
/
/
claimlineitemprocessor -----
\
\
----- pharmacywriter(write to pharmacy table)
I have used a fieldset mapper to create the object representing the claim line (ClaimLine). Most of the fields are a simple mapping to the data in the file, but a few need to have their format changed or related field mapping logic.
Basic item writer code looks like this:
#SuppressWarnings({ "unchecked", "rawtypes" })
#Bean
public ItemWriter<ClaimLine> writer() {
CompositeItemWriter<ClaimLine> cWriter = new CompositeItemWriter<ClaimLine>();
JdbcBatchItemWriter claimWriter = new JdbcBatchItemWriter();
claimWriter.setItemSqlParameterSourceProvider(new ClaimItemSqlParameterSourceProvider());
claimWriter.setSql( // would like to insert into pharmacy table);
claimWriter.setDataSource(dataSource);
claimWriter.afterPropertiesSet();
JdbcBatchItemWriter pharmacyWriter = new JdbcBatchItemWriter();
pharmacyWriter.setItemSqlParameterSourceProvider(new PharmacyItemSqlParameterSourceProvider());
pharmacyWriter.setSql( // would like to insert into pharmacy table);
pharmacyWriter.setDataSource(dataSource);
pharmacyWriter.afterPropertiesSet();
List<ItemWriter<? super ClaimLine>> mWriter = new ArrayList<ItemWriter<? super ClaimLine>>();
mWriter.add(claimWriter);
mWriter.add(pharmacyWriter);
cWriter.setDelegates(mWriter);
// other code
return cWriter;
};
When creating the custom source providers, each of them seem to expect because that is the class that has already been mapped to the input line and contain the values I would like to send to the respective tables.
This is basically where I am now stuck thinking I cannot use a CompositeItemWriter because I am trying to transform a single object into two different ones. And ClassifierCompositeItemWriter works like a router and sends it down a path specific to a condition, which is not what I want to do.
For reference, I tried doing something similar with Spring Integration and also hit a similar roadblock.
Any help is appreciated.
I believe the comments from #Hansjoerg and #Luca provide valuable responses to this question and were researched prior to and during the research for an answer.
I was able to resolve this issue by continuing the use of a ItemSqlParameterSourceProvider and the code is below. When I initially explored how to use this class and its methods, my thought was that I was still only operating on the ClaimLine class.
What is truly happening is the method is receiving the class from the writer and you are setting the values of the SQL statement you set with setSQL(String sql). With the use of ItemSqlParameterSourceProvider, you are using the named parameters in the SQL for the put statement. The code below only shows the code for a claim. The pharmacy would be similar.
public class ClaimItemSqlParameterSourceProvider implements ItemSqlParameterSourceProvider<ClaimLine> {
#SuppressWarnings({ "serial"})
#Override
public SqlParameterSource createSqlParameterSource(final ClaimLine item) {
return new MapSqlParameterSource(new HashMap<String, Object>() {
{
put("rxclaimid", item.getRxClaimID());
...
// many more
}
});
}
}
A custom item writer may have also resolved this issue, but it seems to require more coding to support it. In the end, either using a ItemPreparedStatementSetter or a ItemSqlParameterSourceProvider should be fine for this case. The main reason we choose the latter is because the parameters are clearly named instead of accessing the parameter values by index values (1,2,3, etc) and using "?" in the setSQL call.
you can use chain to write in multiple tables ,
<int:chain input-channel="processTransactionChannel"
output-channel="processedItems">
<int:header-enricher>
<int:header name="savePayload" expression="payload" />
</int:header-enricher>
<int-jpa:updating-outbound-gateway
auto-startup="true"
native-query="insert into TableOne values( :transactionStatus ,bank_Reference_Number = :bankReferenceNumber )"
entity-manager="entityManager"
use-payload-as-parameter-source="false">
<int-jpa:transactional />
<int-jpa:parameter name="transactionStatus"
expression="payload['transactionStatus']" />
<int-jpa:parameter name="bankReferenceNumber"
expression="payload['bankReferenceNumber']" />
</int-jpa:updating-outbound-gateway>
<int:transformer expression="headers.savePayload" />
<int-jpa:updating-outbound-gateway
native-query="insert
into PARTNER_RESPONSE_DETAILS(PARTNER_ID,BANK_REFERENCE_NUMBER,REQUEST_STRING,RESPONSE_STRING)
values (:partnerId,:bankRefNumber,:requestString,:responseString)"
entity-manager="entityManager">
<int-jpa:transactional />
<int-jpa:parameter name="partnerId" expression="payload['partnerId']" />
<int-jpa:parameter name="bankRefNumber" expression="payload['bankRefNumber']" />
<int-jpa:parameter name="requestString" expression="payload['requestString']" />
<int-jpa:parameter name="responseString"
expression="payload['responseString']" />
<int-jpa:parameter name="transactionStatus"
expression="payload['transactionStatus']" />
<int-jpa:parameter name="bankReferenceNumber"
expression="payload['bankReferenceNumber']" />
</int-jpa:updating-outbound-gateway>
<int:transformer expression="headers.savePayload" />
</int:chain>
this code updates 2 tables and it is working for me.
maybe my answer is your except. I also see the same problem, I used classifierCompositeWriter to resolve it. I define my classifier in my project, as you see, you can decide which writer you should use in your logic. for example, in my logic
if(baseEntity instanceof Product){
return productItemWriter;
}else {
return otherItemWriter;
}
good lucky.

Catching global "#In attribute requires non-null value" in SEAM 2

On PAGE A is a table with some data from the database.
by clicking on a row, the page will be forwarded to PAGE B and in the controller the entity will be injected
#DataModelSelection(value = ENTITY_LIST_NAME)
#Out(value = ENTITY_NAME, scope = ScopeType.CONVERSATION, required = false)
private Entity entity;
this works as it should.
The problem is, that our users seems to use bookmark for PAGE B, so the entity will never be injected because they never visited PAGE A
so they always throw this exception
#In attribute requires non-null value
Is there a global function to catch all #In attribute requires non-null value exceptions and forward the user to PAGE C (startpage)?
(of course i can catch this execption on PAGE B but this happens not only on one page, we want to handle this exception on every page)
we are using: jboss5 + jsf 1.2 + seam 2
UPDATE after the answer of EmirCalabuch:
I also tried the hint from EmirCalabuch with:
<page conversation-required="true" no-conversation-view-id="PageC.xhtml" />
but the problem is, that the conversation is alive at this moment, to this forwarding to pageC never happens...
i also made in the page.xml of this page something like:
<action execute="#{controller.checkIfEntityIsSet()}" />
<navigation>
<rule if-outcome="HOME">
<redirect
view-id="/pages/home.xhtml"
/>
</rule>
</navigation>
and in my Controller.java i have somthing like this:
public String checkIfEntityIsSet(){
if(getEntity() == null){
return "HOME";
}
return "";
}
but this checkIfEntityIsSet() is never called, because the #In attribute requires non-null value is thrown before... so this was not a help at all...
Exception handling rules are specified in pages.xml. You could include a rule to catch the org.jboss.seam.RequiredException that is thrown for that type of error and perform your navigation to page C in it.
This however is not a very clean solution as you would bind that exception to that page and most probably you will have this exception elsewhere and would like to redirect to a different page.
A simpler way of achieving the same result is making the conversation required in PageB.page.xml and specifying the view to redirect to when no conversation is active. The page descriptor has an option that allows you to do just that (on PageB.page.xml):
<page conversation-required="true" no-conversation-view-id="PageC.xhtml" />
This tells Seam that if a user tries to display page B and there is no conversation active (which happens when the user gets there from a bookmark), then redirect the user to PageC.xhtml.
Anyway, it takes very little effort to make the page bookmarkable (if you feel your users will be bookmarking it a lot), using page parameters and actions, for example:
In your list page A, instead of an h:commandLink or h:commandButton for each of the rows that take you to page B, use s:link or s:button:
<h:dataTable var="var" value="#{myList.dataModel}">
...
<s:link value="PageB.xhtml">
<f:param name="id" value="#{var.id}" />
</s:link>
...
</h:dataTable>
This will create a link to Page B for each of the entities in the list, passing its ID (for example, PageB.seam?id=1 in the first row, PageB.seam?id=2 in the second and so on. These links are bookmarkable.
On PageB.page.xml declare the parameter:
<param name="id" value="#{myHomeComponent.id}" />
Where myHomeComponent is a component of type EntityHome<YourEntity>. You can then use #{myHomeComponent.instance} inside Page B to access the entity selected.
i managed it now different:
in the Controller.java i have for the initialization something like this:
#Create
public void initialize() throws MissingMyEntityException {
if(qualifiedCustomer == null){
throw new MissingMyEntityException("something wrong");
}
....
}
my MissingMyEntityException.java looks like this:
public class MissingMyEntityException extends Exception {
private static final long serialVersionUID = 8640645441429393157L;
public MissingMyEntityException(String message) {
super(message);
}
}
and in the pages.xml i have the exception handler like this:
<exception class="com.dw.companyName.view.xyz.exception.MissingMyEntityException">
<redirect view-id="/pages/home.xhtml">
<message>something went wrong</message>
</redirect>
</exception>
and this fixed the problem.
but thanks for your help, but it was not working your way :(

How do I add additional context / values for a custom XML based method constraint with the OVal validation framework

With the OVal validation framework (http://oval.sourceforge.net/) it is possible to create custom annotation or XML based constraints (http://oval.sourceforge.net/userguide.html#d4e493).
My intention is to generate an OVal XML configuration file out of some constraint definitions, that's why I would like to do the complete OVal constraint definition with the XML configuration (http://oval.sourceforge.net/userguide.html#d4e551).
I would like to validate the return value of a certain method (getDomain) of a class (Attend) and I have to add additional values (six strings) for the isSatisfied method of my custom check class.
My XML configuration so far looks like this:
<class type="my.package.Attend"
overwrite="false" applyFieldConstraintsToSetter="true">
<field name="NAME">
<notNull />
<maxLength max="4" />
</field>
<method name="getDomain">
<returnValue>
<my.package.DomainCheck />
</returnValue>
</method>
</class>
I have a checker class DomainCheck which should receive the return value from the getDomain method.
In the isSatisfied method of the DomainCheck I have to validate the return value with some additional parameters that I have to configure somehow in the XML.
My first problem is, that the isSatisfied method of the DomainCheck is not invoked.
If I delete the method constraint, the validation result is invalid as I expect it from the field constraint. But if I add the method constraint, the DomainCheck is not invoked and the validation result is valid (should still be invalid). I can not see why the custom check is not invoked. Something must be wrong with my method constraint definition.
Here are my custom check class and the appropriate interface:
package my.package;
import ...
public class DomainCheck extends AbstractAnnotationCheck<Domain> {
public boolean isSatisfied(Object validatedObject, Object valueToValidate, OValContext context, Validator validator) {
if (valueToValidate == null) {
return true;
}
List<?> domainMembers = (ArrayList<?>) valueToValidate;
for (Object domainMember : domainMembers) {
// do validation
}
return false
}
}
package my.package;
import ...
#Retention(RetentionPolicy.RUNTIME)
#Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
#net.sf.oval.configuration.annotation.Constraint(checkWith = DomainCheck.class)
public #interface Domain {
String message() default "must be conform to ...";
}
If this would work, my second problem would be to configure the additional parameters.
I thought of something like:
<method name="getDomain">
<returnValue>
<my.package.DomainCheck />
</returnValue>
<parameter type="java.lang.String">OneName</parameter>
<parameter type="java.lang.String">AnotherName</parameter>
<parameter type="java.lang.String">0</parameter>
<parameter type="java.lang.String">*</parameter>
<parameter type="java.lang.String">5</parameter>
<parameter type="java.lang.String">100</parameter>
</method>
The syntax above is for defining constraints for a method signature, so this obviously does not work. But I can not find any possible definition for my purpose.
So, why is my custom check not invoked and if there is a solution for that, how can I define additional parameters for the isSatisfied method in the XML configuration and how do I access them in the isSatisfied method?
Thank you in advance for any advice!
Cheers David
You are trying to use a programming by contract feature here. For this to work you need to perform some additonal preparations: http://oval.sourceforge.net/userguide.html#project-preparation

Categories