I am updating an application. I have replaced most of the queries in the app with calls to ejbs but the code below calls a huge procedure and it would be almost impossible to re-write.
I would like to return an ejb to the result set R but I have not been able to figure this out....
java.sql.ResultSet R = Cmd.executeQuery("SELECT * FROM TableData");
String[] Names = {"id","Project","Resource","Week","Hours"};
out.print(getTableXML(R,Names));
R.close();
My ejb:
public List<Gridmaster> getDisplayGridList() {
return em.createQuery("FROM Gridmaster order by gridid", Gridmaster.class).getResultList();
Is this possible or do I need to create an old style db connection?
Thanks for any help.
Related
I am implementing a feature where if there is any exception while writing data into DB, we should retry it for 5 times before failing. I have implemented the feature but not able to test it using arquillian test.
We are using JPA and Versant as database. Till now, I am debbuging the the arquillian test and once my flow reaches DB handler code, I am stopping the database. But this is worst way of testing.
Do you have any suggestion how to achieve the same ?
With JPA in mind, the easiest way is to add method to your data access layer, with which you are able to run native queries. Then you run query against nonexisting table or something similar. So in my DAO utilities I found method like this:
public List findByNativeQuery(String nativeQuery, Map<String, Object> args) {
try{
final EntityManager em = getEntityManager();
final Query query = em.createNativeQuery(nativeQuery);
if (args!=null && args.entrySet().size()>0) {
final Iterator it = args.entrySet().iterator();
while (it.hasNext()) {
final Map.Entry pairs = (Map.Entry)it.next();
query.setParameter(pairs.getKey().toString(), pairs.getValue());
}
}
return query.getResultList();
}
catch (RuntimeException e) {
// throw some new Exception(e.getMessage()); // the best is to throw checked exception
}
}
Native solutions
There is the old trick by dividing by zero in the database. At the time of selection you could try:
select 1/0 from dual;
Insertion time (you need a table):
insert into test_table (test_number_field) values (1/0);
pure JPA solution
You can try to utilize the #Version annotation and decrement it to throw OptimisticLockException. This is not thrown in the database, but in the Java layer, but fullfills your need.
Those all will result in DB fail.
I have the following code which I call from the front end
public Login update(Login i) {
em = emf.createEntityManager();
em.getTransaction().begin();
Login result=infoDAO.update(i);
em.getTransaction().commit();
em.close();
return result;
}
public Login update(Login i) {
return em.merge(i);
}
I have
private static final EntityManagerFactory emf = Persistence.createEntityManagerFactory("HRTool-JPA");
protected EntityManager em=emf.createEntityManager();
The methods are being called and the values are passed to the DB correctly(I am using Apache derby) but I can see the new changed values in the DB only after I disconnect and reconnect to it. Am I missing some step after merge ? I am new to JPA and appreciate any suggestions on the same
By default Hibernate keep the requests in its cache and Hibernate decides when it wants to execute them.
You can try to add a em.flush() after em.merge()
It will execute all the requests left in its cache.
So, the question at hand is about initializing the lazy collections of an "unknown" entity, as long as these are known at least by name. This is part of a more wide effort of mine to build a generic DataTable -> RecordDetails miniframework in JSF + Primefaces.
So, the associations are usually lazy, and the only moment i need them loaded is when someone accesses one record of the many in the datatable in order to view/edit it. The issues here is that the controllers are generic, and for this I also use just one service class backing the whole LazyLoading for the datatable and loading/saving the record from the details section.
What I have with come so far is the following piece of code:
public <T> T loadWithDetails(T record, String... associationsToInitialize) {
final PersistenceUnitUtil pu = em.getEntityManagerFactory().getPersistenceUnitUtil();
record = (T) em.find(record.getClass(), pu.getIdentifier(record));
for (String association : associationsToInitialize) {
try {
if (!pu.isLoaded(record, association)) {
loadAssociation(record, association);
}
} catch (..... non significant) {
e.printStackTrace(); // Nothing else to do
}
}
return record;
}
private <T> void loadAssociation(T record, String associationName) throws IntrospectionException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {
BeanInfo info = Introspector.getBeanInfo(record.getClass(), Object.class);
PropertyDescriptor[] props = info.getPropertyDescriptors();
for (PropertyDescriptor pd : props) {
if (pd.getName().equals(associationName)) {
Method getter = pd.getReadMethod();
((Collection) getter.invoke(record)).size();
}
}
throw new NoSuchFieldException(associationName);
}
And the question is, did anyone start any similar endeavor, or does anyone know of a more pleasant way to initialize collections in a JPA way (not Hibernate / Eclipselink specific) without involving reflection?
Another alternative I could think of is forcing all entities to implement some interface with
Object getId();
void loadAssociations();
but I don't like the idea of forcing my pojos to implement some interface just for this.
With the reflection solution you would suffer the N+1 effect detailed here: Solve Hibernate Lazy-Init issue with hibernate.enable_lazy_load_no_trans
You could use the OpenSessionInView instead, you will be affected by the N+1 but you will not need to use reflection. If you use this pattern your transaction will remain opened until the end of the transaction and all the LAZY relationships will be loaded without a problem.
For this pattern you will need to do a WebFilter that will open and close the transaction.
I'd like to find out my data source name in the code. Is there a way of doing that?
I am using eclipselink.
thanks
To be more specific, my aim is to get an jdbc connection object.
I know i can do that thru:
datasource = (DataSource) (new InitialContext()).lookup("my_data_source_name")
connection = dataSource.getConnection();
But I don't want to hard code the data source name in my code.
I also tried
java.sql.Connection connection = em.unwrap(java.sql.Connection.class);
and it always return null.
.unwrap() should be the way to go, as written in EclipseLink wiki.
I also used to get null when calling em.unwrap(java.sql.Connection.class); because it was not inside a transaction. When called like this:
em.getTransaction().begin();
java.sql.Connection conn = em.unwrap(java.sql.Connection.class);
// ...
em.getTransaction().commit();
everything works fine!
java.sql.Connection connection = em.unwrap(java.sql.Connection.class);
Should work, what version are you using? Ensure that a transaction is active.
To get the data source name you should be able to use,
((JNDIConnector)em.unwrap(JpaEntityManager.class).getSession().getLogin().getConnector()).getName();
Here's what I've found helpful:
private DataSource createDataSource() {
ClientDataSource dataSource = new ClientDataSource();
dataSource.setServerName("localhost");
dataSource.setPortNumber(1527);
dataSource.setDatabaseName("sample");
dataSource.setUser("app");
dataSource.setPassword("app");
return dataSource;
}
private EntityManagerFactory getEntityManagerFactory() {
if (emf == null) {
Map properties = new HashMap();
properties
.put(PersistenceUnitProperties.NON_JTA_DATASOURCE,createDataSource());
emf = Persistence.createEntityManagerFactory(PU_NAME, properties);
}
return emf;
}
Can you create your datasource in the code, rather than configure via persistence.xml?
I'm new to Moq, and just started on a project that's already in development. I'm responsible for setting up unit testing. There's a custom class for the DatabaseFactory that uses EnterpriseLibrary and looks like this:
public Database CreateCommonDatabase()
{
return CreateDatabaseInstance(string.Empty);
}
private static Database CreateDatabaseInstance(string foo)
{
var database = clientCode == string.Empty
? DatabaseFactory.CreateDatabase("COMMON")
: new OracleDatabase(new ClientConnections().GetConnectionString(foo)));
return database;
}
Now, here's where that gets used (ResultData is another class of the type DataSet):
public ResultData GetNotifications(string foo, string foo2, Database database)
{
var errMsg = string.Empty;
var retval = 0;
var ds = new DataSet();
var sqlClause =
#"[Some SELECT statement here that uses foo]";
DbCommand cm = database.GetSqlStringCommand(sqlClause);
cm.CommandType = CommandType.Text;
// Add Parameters
if (userSeq != string.Empty)
{
database.AddInParameter(cm, ":foo2", DbType.String, foo2);
}
try
{
ds = database.ExecuteDataSet(cm);
}
catch (Exception ex)
{
retval = -99;
errMsg = ex.Message;
}
return new ResultData(ds, retval, errMsg);
}
Now, originally, the Database wasn't passed in as a parameter, but the method was creating a new instance of the DatabaseFactory using the CreateCommonDatabase method, and using it from there. However, that leaves the class untestable because I can't keep it from actually hitting the database. So, I went with Dependency Injection, and pass the Database in.
Now, I'm stuck, because there's no way to mock Database in order to test GetNotifications. I'm wondering if I'm overly complicating things, or if I'm missing something. Am I doing this the right way, or should I be rethinking how I've got this set up?
Edit to add more info*****
I really don't want to test the database. I want the Data.Notifications class (above) to return an instance of ResultData, but that's all I really want to test. If I go a level up, to the Business layer, I have this:
public DataSet GetNotifications(string foo, string foo1, out int returnValue, out string errorMessage, Database database)
{
ResultData rd = new data.Notifications().GetNotifications(foo, foo1, database);
returnValue = rd.ResultValue;
errorMessage = rd.ErrorMessage;
return rd.DataReturned;
}
So, originally, the database wasn't passed in, it was the Data.Notifications class that created it - but then again, if I left it that way, I couldn't help but hit the database to test this Business layer object. I modified all of the code to pass the Database in (which gets created a the web's Base page), but now I'm just not certain what to do next. I thought I was one unit test away from having this resolved, but apparently, either I'm wrong or I've got a mental roadblock to the right path.
You should be able to create a mock Database object if the methods in it are virtual. If they are not, then you have a little bit of a problem.
I don't know what type "Database" is, but you have a few options.
If you own the source code to Database, I would recommend extracting an interface IDatabase, rather than dealing with a Database class type. This will eliminate some complexity and give you something extremely testable.
If you don't have access to the Database class, you can always solve this with another layer of abstraction. Many people in this case use a Repository pattern that wraps the data access layer. Generally speaking in this case, most people leave testing Respository classes to integration tests (tests without any isolation), rather than unit tests.
Here's how you'd setup your test using option #1:
[TestMethod]
public void GetNotifications_PassedNullFoo_ReturnsData()
{
//Arrange
Mock<IDatabase> mockDB = new Mock<IDatabase>();
mockDB.Setup(db => db.ExecuteDataSet()).Returns(new DataSet() ... );
//Act
FooClass target = new fooClass();
var result = target.GetNotifications(null, "Foo2", mockDB.Object);
//Assert
Assert.IsTrue(result.DataSet.Rows.Count > 0);
}
My dataset code is a little rusty, but hopefully this gives you the general idea.
Based on the code you've given, I would think you would want to talk to the database, and not a mocked version.
The reason is that your GetNotifications code contains DB-specific instructions, and you'll want those to pass validation at the DB Engine level. So just pass in a Database that is connected to your test DB instance.
If you took the testing abstraction to a higher level, where you built unit tests for the database call and a version of this test that used a mocked database, you'd still have to run integration tests, which ends up being triple the work for the same amount of code coverage. In my opinion, it's far more efficient to do an integration test at tier borders you control then to write unit tests for both sides of the contract and integration tests.