Spring JPA Stored Procedure with a null value? - java

I have a stored procedure and it's being called from a JpaRepository implementation as such
#Repository
public interface DataMartRepo extends JpaRepository<DataMartDAO, String> {
#Procedure(procedureName = "dbo.txn_ETL")
public void txnETL(
#Param("txId") String txId,
#Param("inId") String inId,
#Param("proc") String proc,
#Param("qtys") String qtys);
Now, this works fine, expect for when "proc" is a null value, in which case it throws an exception:
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/Authenticator]
threw exception [Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException:
Error calling CallableStatement.getMoreResults; nested exception is org.hibernate.exception.GenericJDBCException:
Error calling CallableStatement.getMoreResults] with root cause
com.microsoft.sqlserver.jdbc.SQLServerException: The value is not set for the parameter number 3.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:190)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.buildParamTypeDefinitions(SQLServerPreparedStatement.java:260)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.buildPreparedStrings(SQLServerPreparedStatement.java:219)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doPrepExec(SQLServerPreparedStatement.java:612)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:400)
[...]
How do I deal with null values? Setting all Strings to "" doesn't offer null inserts.

Looks like the parameter with null value in SP call is open issue. Please see https://hibernate.atlassian.net/browse/HHH-9007

Related

Spring Boot - update data

I have a little problem.
I try update in repository one column.
Repository
#Modifying
#Query("UPDATE Conversation conversation SET conversation.friend = ?1 WHERE conversation.id = ?2")
fun setConversationInfoById(friend: Boolean, id: UUID): List<Conversation>
Service
fun addDeleteFriend(conversation: Conversation) {
val openedConversation = db.findByIdOrNull(conversation.id)
if (openedConversation == null) db.save(conversation)
else db.setConversationInfoById(openedConversation.friend, openedConversation.id)
}
Controler
#PostMapping("/friend", consumes = [MediaType.APPLICATION_JSON_VALUE])
#ResponseBody
fun friend(#RequestBody conversation: Conversation) = service.addDeleteFriend(conversation)
It's about the flag - boolean whos will change status column "friend".
When I'm starting BE the console shows me this error:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with
name 'conversationController' defined in file [####]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name
'conversationService' defined in file [####]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name
'conversationRepository' defined in com.###.backend.repository.ConversationRepository defined in
#EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration:
Invocation of init method failed; nested exception is org.springframework.data.repository.query.QueryCreationException: Could not create query for
public abstract java.util.List com.###.backend.repository.ConversationRepository.setConversationInfoById(boolean,java.util.UUID)!
Reason: Failed to create query for method public abstract java.util.List
com.##.backend.repository.ConversationRepository.setConversationInfoById(boolean,java.util.UUID)!
No property 'setConversationInfoById' found for type 'Conversation'!; nested exception is
java.lang.IllegalArgumentException: Failed to create query for method public abstract
java.util.List com.###.backend.repository.ConversationRepository.setConversationInfoById(boolean,java.util.UUID)!
No property 'setConversationInfoById' found for type 'Conversation'!
I tried all option, but I don't know what is the problem ..
query method changes Conversation data by id, which is one data.
So it will be return one Conversation object.
try to change List to Conversation.
or, I don't know well, but quertymethod naming convention is exist, so try to check out.

Can you get more specific exception or cause of getting PersistenceException when calling createEntityManager while using OpenJPA

While connecting to Derby database using OpenJPA, i have encountered this PersistenceException, which says connection could not be obtained for Derby EmbeddedDriver driver class, but that is not important (i know how to fix it):
77 RegistryManagement INFO [JavaFX Application Thread] openjpa.jdbc.JDBC - Using dictionary class "org.apache.openjp
a.jdbc.sql.DerbyDictionary".
<openjpa-3.1.2-r66d2a72 nonfatal general error> org.apache.openjpa.persistence.PersistenceException: There were errors i
nitializing your configuration: <openjpa-3.1.2-r66d2a72 fatal user error> org.apache.openjpa.util.UserException: A conne
ction could not be obtained for driver class "org.apache.derby.jdbc.EmbeddedDriver" and URL "jdbc:derby:db". You may ha
ve specified an invalid URL.
....
Important is that there is this Caused by in that exception:
....
Caused by: ERROR XJ004: XJ004.C : [0] db
at
....
which is one of Derby error codes (https://db.apache.org/derby/docs/10.5/ref/rrefexcept71493.html).
This PersistenceException was thrown when calling .createEntityManager(). Is it pretty long when it comes to text length.
I can catch that PersistenceException by wrapping .createEntityManager() with try-catch, but i can not figure out how to find more information about what is the cause, aka. get the error code, because PersistenceException can be thrown for various reasons. And i can not wrap it with catching SQLException or UserException, because my IDE says that method does not throw these exceptions.
I tried calling .getMessage() or .getCause() on that PersistenceException, but i got almost same long text.
When i called .getCause() it returns RuntimeException and I could see this, that Derby thrown SQLException:
....
Caused by: java.sql.SQLException: XJ004.C : [0] db
at
....
calling .getCause() again returns null.
I do not want to search the whole message (String) for occurences of some error codes, because that might be resource heavy. I think this problem might not be specific to Derby and happen while using other sql dbs, which might also throw some exception.
My code:
public class DatabaseManager
{
private EntityManagerFactory managerFactory;
private EntityManager manager;
public DatabaseManager(String persistenceUnitName, Map<String, String> properties)
{
managerFactory = Persistence.createEntityManagerFactory(persistenceUnitName, properties);
try
{
manager = managerFactory.createEntityManager();
}
catch(PersistenceException e)
{
//stuff
}
}
....
EntityManagerFactory is an interface from javax.persistence package:
public interface EntityManagerFactory {
public EntityManager createEntityManager();
....
As i was debugging, found this methods in PersistenceExceptions class, which are
from OpenJPA:
#Override
public RuntimeException translate(RuntimeException re) {
return PersistenceExceptions.toPersistenceException(re);
}
this method translates caught RuntimeException, which is in question's case OpenJPA's UserException caused by SQLException, and then creates new PersistenceException based on it here and returns it:
/**
* Translate the given general exception.
*/
private static Throwable translateGeneralException(OpenJPAException ke) {
Exception e = new org.apache.openjpa.persistence.PersistenceException
(ke.getMessage(), getNestedThrowables(ke),
getFailedObject(ke), ke.isFatal());
e.setStackTrace(ke.getStackTrace());
return e;
}
As you can see creating new org.apache.openjpa.persistence.PersistenceException based on OpenJPAException values (and not itself) causes that it is not possible to retrieve lower cause.
OpenJPA version 3.1.2

Spring org.springframework.beans.ConversionNotSupportedException exception

Could someone say why I am getting this exception ?
And how to solve the problem ?
If I understand correctly com.test.dao.CustomerDAO$$EnhancerByCGLIB$$ae49026e_3 class generated at runtime by spring.
Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'com.test.dao.CustomerDAO$$EnhancerByCGLIB$$ae49026e_3' to required type 'com.test.dao.CustomerDAO'

Spring Security method rules: returned value contains a Collection

In Spring Security I want to secure a method incorporating returned values and using #PostAuthorize.
I want to add a constraing that will not allow one user to access to resources they are not owners. The problem I face is that I want to check principal id against one collection of values.
Scenario:
Domain objects:
public class Car implements Serializable {
private Integer id;
private Collection<Driver> drivers;
...
}
public class Driver implements Serializable {
private Integer id;
...
}
Service:
#PostAuthorize("hasRole('ROLE_ADMIN') or principal.id == returnObject.drivers.driver.id")
public Car getCar(int id) throws DAOException {
...
return carDAO.get(id);
}
Of course this Spel expression does not works.
SEVERE: El Servlet.service() para el servlet [dispatcher] en el contexto con ruta [] lanzó la excepción [Request processing failed; nested exception is java.lang.IllegalArgumentException: Failed to evaluate expression 'hasRole('ROLE_ADMIN') or principal.id == returnObject.drivers.driver.id'] con causa raíz
org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 42): Field or property 'driver' cannot be found on object of type 'org.eclipse.persistence.indirection.IndirectList'
I haven't seen any example that works over a Collection.
This unsolved question is similar but I don't know if matches my particular scenario.
Is possible to do something like that?
It is another way to do what I am trying to do?
Try to rewrite your expression as follows:
#PostAuthorize("hasRole('ROLE_ADMIN') or returnObject.hasDriverWithId(principal.id)")
and then add corresponding hasDriverWithId method to your Car class
Trying to access the property driver on a List doesn't really make sense. Are you wanting the first item in the list? What about returnObject.drivers[0].id?

netbeans, EJB, glassfish, e-commerce tutorial issues

I’ve been following the e-commerce tutorial located here: http://netbeans.org/kb/docs/javaee/ecommerce/intro.html
Code repo of project here.
I have ran into a few problems that I believe are related:
1: Trying to view the customers’ orders on the Admin page results in:
**WARNING**: EJB5184:A system exception occurred during an invocation on EJB OrderManager, method: public java.util.Map session.OrderManager.getOrderDetails(int)
**WARNING**: javax.ejb.EJBTransactionRolledbackException
**WARNING**: EJB5184:A system exception occurred during an invocation on EJB OrderedproductFacade, method: public java.util.List session.OrderedproductFacade.findByOrderId(java.lang.Object)
**WARNING**: javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean
Caused by: java.lang.IllegalArgumentException: You have attempted to set a parameter value using a name of customerOrderId that does not exist in the query string SELECT o FROM Orderedproduct o WHERE o.orderedproductPK.custOrderid = :custOrderid.
2: Trying to view details for a particular order in the admin page results in:
WARNING: StandardWrapperValve[AdminServlet]: PWC1406: Servlet.service() for servlet AdminServlet threw exception
Caused by: java.lang.IllegalArgumentException: You have attempted to set a parameter value using a name of customerOrderId that does not exist in the query string SELECT o FROM Orderedproduct o WHERE o.orderedproductPK.custOrderid = :custOrderid.
Both problems have the ‘findByOrderId’ method in common and I am at a loss as to what is wrong with it.
The offending method is located in the following directory: src/jsf_crud/src/java/session/OrderedProductFacade.java
(I would link it as a hyperlink but spam prevention measures prevent me)
Not sure what the best course of action is, any recommendations?
Your query needs a parameter called "custOrderid" and not "customerOrderId"
Either change the query or change the called parameter.
The query in the OrderedProduct class uses "customerOrderId"
http://netbeans.org/projects/samples/sources/samples-source-code/content/samples/javaee/AffableBean/src/java/entity/OrderedProduct.java

Categories