CassandraOperations queryForObject() method always returning PrimaryKey instead of Entity Object - cassandra

I am trying to access Cassandra # localhost using a standalone main() method. The main() method uses DataStax driver and CassandraOperations class from spring-data-cassandra module. CassandraOperation's queryForObject() method always return the primary key instead of Entity Object.
I am just using the code example given in the Spring Data Documentation.
Apache-Cassandra version : 2.1.2
Spring-Data-Cassandra version : 1.2.0.RELEASE
Entity Class :
import org.springframework.data.cassandra.mapping.PrimaryKey;
import org.springframework.data.cassandra.mapping.Table;
#Table
public class Person {
#PrimaryKey
private String id;
private String name;
private int age;
public Person(String id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
#Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
Client Code:
public class CassandraApp {
private static final Logger LOG = LoggerFactory.getLogger(CassandraApp.class);
private static Cluster cluster;
private static Session session;
public static void main(String[] args) {
try {
cluster = Cluster.builder().addContactPoints(InetAddress.getLocalHost()).build();
session = cluster.connect("person");
CassandraOperations cassandraOps = new CassandraTemplate(session);
cassandraOps.insert(new Person("1234567890", "David", 40));
Select s = QueryBuilder.select().from("person");
s.where(QueryBuilder.eq("id", "1234567890"));
System.out.println(cassandraOps.queryForObject(s, Person.class).getId());
cassandraOps.truncate("person");
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
Runtime exception:
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to com.prashanth.ts.entity.Person
at com.prashanth.ts.client.CassandraApp.main(CassandraApp.java:40)
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 com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
I am new to Spring Data. Any one can help me identify what I am doing wrong here.
I also tried removing the QueryBuilder and passing a simple query String like "select * from person" to the queryForObject() methodd
Note :
The insert operation is working perfectly.

I was able to make it work using selectOne method instead of queryForObject.
LOG.info(cassandraOps.selectOne(s, Person.class).getId());

Judging by documentation here, you need to add one more method(all) for QueryBuilder:
Select s = QueryBuilder.select().all().from("person");
On a side note, you are using spring-data-cassandra but you are not utilizing it's best features which would make your code much simpler.

I can see where the OP could have gotten confused here. Finding no code extension provided by Eclipse I went to the org.springframework.data.cassandra.core
Interface CassandraOperations documentation. There is no queryForObject documented so unless someone can explain otherwise
LOG.info(cassandraOps.queryForObject(s, Person.class).getId());
is just bad code. I tried to find the correct usage of queryForObject but all the searches took me back to the example in question which seems to have originated in 2008. Who knows, at one point it may have worked. The OP was trying to use Cassandra Operations to extract information from "s". I liked the idea of Amit T and got something working. I had my own class using Company instead of Person but the idea is the same.
try {
cluster = Cluster.builder().withoutMetrics().addContactPoints(InetAddress.getByName("192.168.1.5") ).build();
session = cluster.connect("rant");
CassandraOperations cassandraOps = new CassandraTemplate(session);
cassandraOps.insert(new Companies("name1", "user", "category", "first", "last", "city", "state", "zipcode", "phone", "email",
"addr1c", "adddr2c", "cityc", "statec", "zipcodec", "phonec", "emailc", "website", 0.0, 0.0,
0, 0, "pr", 0, "text"));
Select s = QueryBuilder.select().from("companies");
s.where(QueryBuilder.eq("company_company", "name1"));
// LOG.info(cassandraOps.queryForObject(s, Companies.class).getId());
LOG.info(cassandraOps.selectOne(s, Companies.class).CompanyInformation());
cassandraOps.truncate(Companies.class); // empties the table
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
I also created my own CompanyInformation() just as an exercise.
public String CompanyInformation() {
System.out.println("Company Information " + this.company_company);
return this.company_userid;
}
The output was as expected.
19:35:24.456 [cluster1-nio-worker-2] DEBUG com.datastax.driver.core.Connection - Connection[/192.168.1.5:9042-2, inFlight=1, closed=false] Keyspace set to rant
Company Information name1 <== from CompanyInformation()
19:35:24.483 [main] INFO com.androidcommand.app.SpringRbsApplication - user <== from LOG.Info
19:35:24.485 [main] DEBUG org.springframework.data.cassandra.core.cql.CqlTemplate - Executing CQL Statement [TRUNCATE companies;]

Related

Jooq- Updating a field to NULL makes it "null" and not NULL

So this was my query that previously worked in jooq 3.11.
I am updating a JSON field, however it is mapped to a String in my model using a JsonBinding which I will post down below
dsl.update(TASK)
.set(TASK.JSON_SOLUTION, (String) null).
.where(TASK.TENANT.eq(getCurrentTenant()))
.and(TASK.TASK_TEMPLATE_ID.in(taskTemplateIds));execute()
This now no longer works after upgrading to jooq 3.13.2. I also had to change my sql dialect to be mysql even though I am working with a mysql 5_7 database, this may be the issue?
I have also tried this and it is still the same
dsl.update(TASK)
.setNull(TASK.JSON_SOLUTION).
.where(TASK.TENANT.eq(getCurrentTenant()))
.and(TASK.TASK_TEMPLATE_ID.in(taskTemplateIds));execute()
JsonBinding.class
public class JsonBinding implements Binding<JSON, String> {
#Override
public Converter<JSON, String> converter() {
return new JsonConverter();
}
#Override
public void sql(BindingSQLContext<String> bindingSQLContext) {
if (bindingSQLContext.render().paramType() == ParamType.INLINED) {
bindingSQLContext
.render()
.visit(DSL.inline(bindingSQLContext.convert(converter()).value()))
.sql("::json");
} else {
bindingSQLContext.render().sql("?");
}
}
#Override
public void register(BindingRegisterContext<String> bindingRegisterContext) throws SQLException {
bindingRegisterContext
.statement()
.registerOutParameter(bindingRegisterContext.index(), Types.VARCHAR);
}
#Override
public void set(BindingSetStatementContext<String> bindingSetStatementContext)
throws SQLException {
bindingSetStatementContext
.statement()
.setString(
bindingSetStatementContext.index(),
Objects.toString(bindingSetStatementContext.convert(converter()).value(), null));
}
#Override
public void set(BindingSetSQLOutputContext<String> bindingSetSQLOutputContext)
throws SQLException {
throw new SQLFeatureNotSupportedException();
}
#Override
public void get(BindingGetResultSetContext<String> bindingGetResultSetContext)
throws SQLException {
bindingGetResultSetContext
.convert(converter())
.value(
JSON.valueOf(
bindingGetResultSetContext
.resultSet()
.getString(bindingGetResultSetContext.index())));
}
#Override
public void get(BindingGetStatementContext<String> bindingGetStatementContext)
throws SQLException {
bindingGetStatementContext
.convert(converter())
.value(
JSON.valueOf(
bindingGetStatementContext
.statement()
.getString(bindingGetStatementContext.index())));
}
#Override
public void get(BindingGetSQLInputContext<String> bindingGetSQLInputContext) throws SQLException {
throw new SQLFeatureNotSupportedException();
}
}
JsonConverter.class
public class JsonConverter implements Converter<JSON, String> {
#Override
public String from(JSON object) {
return object != null ? object.toString() : null;
}
#Override
public JSON to(String string) {
return JSON.valueOf(string);
}
#Override
public Class<JSON> fromType() {
return JSON.class;
}
#Override
public Class<String> toType() {
return String.class;
}
}
Here is the query jooq runs with .setNull()
update `tasks_service`.`task` set `tasks_service`.`task`.`json_solution` = 'null'::json where (`tasks_service`.`task`.`tenant` = 'skynet' and `tasks_service`.`task`.`task_template_id` in ('55', '33'))
Before the upgrade on jooq 3.11 the query comes out as this
update `tasks_service`.`task` set `tasks_service`.`task`.`json_solution` = null::json where (`tasks_service`.`task`.`tenant` = 'skynet' and `tasks_service`.`task`.`task_template_id` in ('55', '33'))
So before its set 'json_solution' = null and after the upgrade it seems to be set 'json_solution' = 'null'
Not quite sure why this is occurring?
Edit: So from what I can tell this solely seems to be from the upgrade in JOOQ and not the sql-dialect. Using Jooq 3.11.5 with both mysql and mysql_5_7 as the dialects, the query is built as set 'json_solution' = null, if I upgrade JOOQ to 3.13.2 its set 'json_solution' = 'null'
This quirk also seems to only happen on the JSON field, I tried setting another varchar String field to be null on the same table, and I get the correct set "field_name' = null
The problem may be with my JsonBinding/JsonConverter ? I had to modify it slightly to work with the new JSON object in JOOQ, as previously JOOQ mapped JSON as Object
JSON.valueOf(null) vs (JSON) null
The answer is in the Javadoc of org.jooq.JSON:
A CAST(NULL AS JSON) value is represented by a null reference of type JSON, not as data() == null. This is consistent with jOOQ's general way of returning NULL from Result and Record methods.
So, the mistake is in JsonConverter's usage of JSON.valueOf(). Write this instead:
public JSON to(String string) {
return string == null ? null : JSON.valueOf(string);
}
Or, just use Converter.ofNullable(), which handles the null-to-null mapping for you:
Converter<JSON, String> converter = Converter.ofNullable(
JSON.class,
String.class,
JSON::data,
JSON::json
);
Side note on using a Binding
You don't really need the binding anymore, now that the JSON type is suppported natively by jOOQ. If you want to convert JSON to String, your Converter will be sufficient.

Mockito running independently works but fail when run together

I'm mocking the jdbc connection, resultset and PreparedStatment.
So, when a run the tests one-by-one works. But if a run all tests from class the method whenSelectB fail.
java.lang.AssertionError: There are 2 rows
Expected: <2>
but: was <0>
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
at net.sf.jkniv.whinstone.jdbc.dml.MockitoSample.whenSelectB(MockitoSample.java:155)
There is some trick to run this?
public class MockitoSample
{
private DataSource dataSource;
private Connection connection;
private PreparedStatement stmt;
private ResultSet rs;
private ResultSetMetaData rsMetadata;
private DatabaseMetaData dbMetadata;
private RepositoryConfig repositoryConfig;
private SqlContext sqlContext;
private Selectable sql;
#Before
public void setUp() throws SQLException
{
this.connection = mock(Connection.class);
this.dataSource = mock(DataSource.class);
this.stmt = mock(PreparedStatement.class);
this.rs = mock(ResultSet.class);
this.rsMetadata = mock(ResultSetMetaData.class);
this.dbMetadata = mock(DatabaseMetaData.class);
this.repositoryConfig = mock(RepositoryConfig.class);
this.sqlContext = mock(SqlContext.class);
this.sql = mock(Selectable.class);
given(this.dataSource.getConnection()).willReturn(this.connection);
given(this.connection.prepareStatement(anyString(), anyInt(), anyInt())).willReturn(this.stmt);
given(this.stmt.executeQuery()).willReturn(this.rs);
given(this.stmt.executeQuery(anyString())).willReturn(this.rs);
given(this.dbMetadata.getJDBCMajorVersion()).willReturn(1);
given(this.dbMetadata.getJDBCMinorVersion()).willReturn(0);
given(this.dbMetadata.getDriverName()).willReturn("MOCKITO");
given(this.dbMetadata.getDriverVersion()).willReturn("1");
given(this.rs.getMetaData()).willReturn(this.rsMetadata);
given(this.repositoryConfig.getName()).willReturn("Mockito");
given(this.repositoryConfig.lookup()).willReturn(this.dataSource);
given(this.repositoryConfig.getJndiDataSource()).willReturn("jdbc/Mockito");
given(this.repositoryConfig.getProperty(RepositoryProperty.JDBC_ADAPTER_FACTORY.key()))
.willReturn(DataSourceAdapter.class.getName());
given(this.repositoryConfig.getTransactionType()).willReturn(TransactionType.LOCAL);
given(this.repositoryConfig.getQueryNameStrategy()).willReturn("net.sf.jkniv.sqlegance.HashQueryNameStrategy");
given(this.sql.getValidateType()).willReturn(ValidateType.NONE);
given(this.sql.getSql(any())).willReturn("select * from dual");
given(this.sql.getSqlDialect()).willReturn(new AnsiDialect());
given(this.sql.getParamParser()).willReturn(ParamParserFactory.getInstance(ParamMarkType.COLON));
given(this.sql.getStats()).willReturn(NoSqlStats.getInstance());
given(this.sql.getSqlType()).willReturn(SqlType.SELECT);
given(this.sql.asSelectable()).willReturn((Selectable) this.sql);
given(this.sqlContext.getRepositoryConfig()).willReturn(this.repositoryConfig);
given(this.sqlContext.getQuery(anyString())).willReturn(this.sql);
}
#Test
public void whenSelectA() throws SQLException
{
Repository repository = RepositoryService.getInstance().lookup(RepositoryType.JDBC).newInstance(sqlContext);
given(this.rsMetadata.getColumnCount()).willReturn(2);
given(this.rsMetadata.getColumnLabel(1)).willReturn("id");
given(this.rsMetadata.getColumnName(1)).willReturn("id");
given(this.rsMetadata.getColumnLabel(2)).willReturn("name");
given(this.rsMetadata.getColumnName(2)).willReturn("name");
given(this.rs.getMetaData()).willReturn(this.rsMetadata);
given(this.sql.getReturnType()).willReturn(FlatBook.class.getName());
doReturn(FlatBook.class).when(this.sql).getReturnTypeAsClass();
given(rs.next()).willReturn(true, true, false);
given(rs.getObject(1)).willReturn(1001L, 1002L);
given(rs.getObject(2)).willReturn("Beyond Good and Evil", "The Rebel: An Essay on Man in Revolt");
Queryable q = QueryFactory.of("2 FlatBook");
List<FlatBook> books = repository.list(q);
assertThat("There are 2 rows", books.size(), equalTo(2));
assertThat("Row is a FlatBook object", books.get(0), instanceOf(FlatBook.class));
for (FlatBook b : books)
{
assertThat(b.getId(), notNullValue());
assertThat(b.getName(), notNullValue());
}
}
#Test
public void whenSelectB() throws SQLException
{
Repository repository = RepositoryService.getInstance().lookup(RepositoryType.JDBC).newInstance(sqlContext);
given(rsMetadata.getColumnCount()).willReturn(2);
given(this.rsMetadata.getColumnLabel(1)).willReturn("id");
given(this.rsMetadata.getColumnName(1)).willReturn("id");
given(this.rsMetadata.getColumnLabel(2)).willReturn("name");
given(this.rsMetadata.getColumnName(2)).willReturn("name");
given(this.rs.getMetaData()).willReturn(this.rsMetadata);
given(this.sql.getReturnType()).willReturn(FlatAuthor.class.getName());
doReturn(FlatAuthor.class).when(this.sql).getReturnTypeAsClass();
given(rs.next()).willReturn(true, true, false);
given(rs.getObject(1)).willReturn(1L, 2L);
given(rs.getObject(2)).willReturn("Author 1", "Author 2");
Queryable q = QueryFactory.of("2 FlatAuthor");
List<FlatAuthor> books = repository.list(q);
assertThat("There are 2 rows", books.size(), equalTo(2));
assertThat("Row is a FlatAuthor object", books.get(0), instanceOf(FlatAuthor.class));
for (FlatAuthor a : books)
{
assertThat(a.getId(), notNullValue());
assertThat(a.getName(), notNullValue());
}
verify(rs).close();
verify(stmt).close();
verify(connection, atLeast(1)).close();
}
The error happens inside the Repository instance, it uses thers.next ()(ResultSet) method but returnsfalse when it should return true twice.
My Repository instance holds the DataSouce class in theThreadLocal, so when whenSelectB tries to get the new Mock it retrieves the old DataSource that retrieves the old Connection, which gets the old Statement that retrieves the old ResultSet. In other words, I have a dirty context between test. Repository must hold the connection just when a transaction was began.
Thanks #Joakim-Danielson and #Antoniossss

Ektorp - #DocumentReference not working

I am a newbee to Couch and I found lazy-fetching interesting. So I was trying that out but probably due to something wrong I did, it doesn't work and I can't figure out what is wrong. I referred http://ektorp.org/reference_documentation.html#d100e394. I get the error below. (I am able to read the docs separately but not by document referencing). Any help would be much appreciated. I'm using ektorp version 1.4.1.
09:51:03.581 [main] DEBUG org.ektorp.impl.StdCouchDbConnector - Querying CouchDb view at /employee/_design/Employee/_view/ektorp_docrefs_addresses?startkey=%5B%22222%22%2C%22addresses%22%5D&endkey=%5B%22222%22%2C%22addresses%22%2C%7B%7D%5D&include_docs=true.
Exception in thread "main" org.ektorp.DocumentNotFoundException: nothing found on db path: /employee/_design/Employee/_view/ektorp_docrefs_addresses?startkey=%5B%22222%22%2C%22addresses%22%5D&endkey=%5B%22222%22%2C%22addresses%22%2C%7B%7D%5D&include_docs=true, Response body: {"error":"not_found","reason":"missing"}
at org.ektorp.http.StdResponseHandler.createDbAccessException(StdResponseHandler.java:40)
at org.ektorp.http.StdResponseHandler.error(StdResponseHandler.java:68)
at org.ektorp.http.RestTemplate.handleResponse(RestTemplate.java:110)
at org.ektorp.http.RestTemplate.getUncached(RestTemplate.java:27)
at org.ektorp.impl.StdCouchDbConnector.executeQuery(StdCouchDbConnector.java:431)
at org.ektorp.impl.StdCouchDbConnector.queryView(StdCouchDbConnector.java:423)
at org.ektorp.impl.docref.ViewBasedCollection.loadSetResult(ViewBasedCollection.java:69)
at org.ektorp.impl.docref.ViewBasedCollection.loadFromBackReferences(ViewBasedCollection.java:50)
at org.ektorp.impl.docref.ViewBasedCollection.initialize(ViewBasedCollection.java:102)
at
org.ektorp.impl.docref.LazyLoadingViewBasedCollection.invoke(LazyLoadingViewBasedCollection.java:27)
at com.sun.proxy.$Proxy13.size(Unknown Source)
at com.poc.main.Main.main(Main.java:37)
My test files are below.
Employee doc
{
"_id": "222",
"_rev": "1-32d4d52d4ea11b521b1e366959ce5557",
"name": "Mariamma",
"age": 21
}
Address doc
{
"_id": "ad1",
"_rev": "2-39f3162e0fc63ed5526adda5ae496291",
"employeeId": 222,
"addressLine1": "555 Randolph",
"city": "Chicago"
}
Employee.java
public class Employee extends CouchDbDocument {
private String name;
private int age;
#DocumentReferences(backReference = "employeeId", fetch = FetchType.LAZY, cascade=CascadeType.NONE)
private Set<Address> addresses = new HashSet<Address>();
// getters and setters
}
Address.java
public class Address extends CouchDbDocument {
private String employeeId;
private String addressLine1;
private String addressLine2;
private String city;
private String State;
private String zipCode;
// getters and setters
}
EmployeeDao.java
public class EmployeeDao {
private final CouchDbConnector db;
public EmployeeDao() {
db = getEmployeeDatabaseConnector();
}
public CouchDbConnector getEmployeeDatabaseConnector() {
HttpClient httpClient = new StdHttpClient.Builder().build();
CouchDbInstance couchDbInstance = new StdCouchDbInstance(httpClient);
CouchDbConnector connector = new StdCouchDbConnector("employee", couchDbInstance);
connector.createDatabaseIfNotExists();
return connector;
}
public Employee read(String employeeId) {
return this.db.get(Employee.class, employeeId);
}
}
Main.java
public class Main {
public static void main(String[] args) {
EmployeeDao dao = new EmployeeDao();
Employee employee = dao.read("222");
System.out.println(employee.getName());
System.out.println(employee.getAddresses().size()); // this line throws error.
}
}
From your stack trace
... Response body: {"error":"not_found","reason":"missing"}
This suggests that the view /_design/Employee/_view/ektorp_docrefs_addresses isn't there.
Update
Chapter 6 of the Ektorp Reference Docs talks about view generation. It looks like you are not created it yourself and have not told Ektorp to do it for you.
You should look at creating a repository class for Employee by extending CouchDbRepositorySupport and then calling initStandardDesignDocument() on it.

ServiceStack ORMLite

We are migrating our SProc based solution over to ORMLite, and so far has been pretty painless. Today I wrote the following method:
public AppUser GetAppUserByUserID(int app_user_id)
{
var dbFactory = new OrmLiteConnectionFactory(this.ConnectionString, SqlServerOrmLiteDialectProvider.Instance);
AppUser item = null;
var rh = new RedisHelper();
var id= CacheIDHelper.GetAppUserID( app_user_id );
item = rh.Get<AppUser>(id);
if (item == null)
{
try
{
using (var db = dbFactory.OpenDbConnection())
{
item = db.Single<AppUser>("application_user_id={0}", app_user_id);
rh.Set<AppUser>(item, id);
}
}
catch (Exception ex)
{
APLog.error(ex, "Error retrieving user!");
}
}
return item;
}
I have remove some of the extraneous fields, but they are basically:
[Alias("application_user")]
public class AppUser : APBaseObject
{
[Alias("application_user_id")]
[AutoIncrement]
public int? UserID
{
get;
set;
}
[Alias("application_user_guid")]
public string UserGUID
{
get;
set;
}
//MORE FIELDS here.
}
The challenge is that they only field that is populate is the ID field, AND I already know that ID because I am passing it into the method.
I did get the last SQL called and ran that against the DB directly and all of the fields were being referenced correctly.
I stepped through the code in the debugger, and everything came back correctly, except that the only field returned was the ID.
Thoughts?
I had a similar issue which was caused by my class methods not mapping to the db properly. My exact issue was caused by a nullable int field in the db and the class method was defined as an 'int' instead of 'int?'.
Perhaps you have a similar issue?

How do you invoke a Runnable using Spring Framework?

I have a service that needs to invoke a runnable class.
Here are the lines of code that are being used in my service.
#Autowired
private LinkBrc2MemberProfile brcTask;
// Background Task.
SimpleAsyncTaskExecutor sate = new SimpleAsyncTaskExecutor();
sate.createThread(new LinkBrc2MemberProfile(user));
Here is my Runnable class
#Service
public class LinkBrc2MemberProfile implements Runnable {
private final Logger log = LoggerFactory.getLogger(LinkBrc2MemberProfile.class);
#Autowired
private LoyaltyDao dao;
private Member member;
public LinkBrc2MemberProfile() {
super();
}
public LinkBrc2MemberProfile(Member member) {
this.member = member;
}
public void run() {
log.debug("*** Member User Name: " + member.getString("USER_NAME"));
String emailAddress = member.getString("USER_NAME");
Map<String, Object> map = dao.findBrcByEmailAddress( emailAddress );
log.debug("==========================================================");
if( ! map.isEmpty() ) {
try {
//a.CUSTOMER_ID, a.EMAIL_ADDRESS, b.card_no
String customerId = (String) map.get("CUSTOMER_ID");
String brcCardNumber = (String) map.get("CARD_NO");
log.debug("\ncustomerId: " + customerId + " brcCardNumber: " + brcCardNumber);
if(!brcCardNumber.equals("")) {
// Add the Be Rewarded Card.
HashMap<String, String> userAttributes = new HashMap<String, String>();
String brcNumber = member.getString("BREWARDED_CARD_NO");
if (brcNumber.equals("")) {
userAttributes.put("BREWARDED_CARD_NO", brcCardNumber);
try {
member.putAll(userAttributes);
} catch (Exception e) {
String errorMessage = "Unable to save user's BRC information due to: " + e.getMessage();
log.error("{}", errorMessage);
}
}
}
} catch (Exception e) {
log.error(e.getMessage());
e.printStackTrace();
}
}
}
I'm not seeing any errors in the log but at the same time it does not appear to be invoking the Runnable class. Am I missing an annotation somewhere? Are there any good examples that you can point me to, the only ones I have found use XML files to configure the runnable class I would like to use annotations. Thanks in Advance.
I've updated my service to do the following.
Please help, my DAO is NULL so it looks like my #Autowired in my Runnable class is not wiring it in.
I've added the following bean to my bean-config.xml file.
<bean id="brcType" class="com.ws.ocp.service.LinkBrc2MemberProfile" scope="prototype"/>
I removed my #Autowired annotation and added the following to my service class.
ClassPathResource rsrc = new ClassPathResource("bean-config.xml");
XmlBeanFactory factory = new XmlBeanFactory(rsrc);
LinkBrc2MemberProfile brcTask = (LinkBrc2MemberProfile) factory.getBean("brcType");
SimpleAsyncTaskExecutor sate = new SimpleAsyncTaskExecutor();
// Set Member attribute
brcTask.setMember(user);
// Executer
sate.execute(brcTask);
Why is my dao still null?
The runnable will throw a NullPointerException, since you create it yourself (using the new operator), instead of letting Spring create it. This obviously means that the autowired DAO attribute won't be autowired, which will lead to a NPE when calling dao.findBrcByEmailAddress(...).
You should get your Runnable instance from the bean factory (as a prototype), set its member attribute, and then submit it to the executor.
To answer your question of how to properly use a Prototype-Bean, this is my favorite way:
#Component
abstract class MyBean {
/* Factory method that will be installed by Spring */
#Lookup
protected abstract YourPrototypeBean createBean();
void someCode() {
YourPrototypeBean bean = createBean();
}
}
Since it's a factory method, you can create as many instances as you like.

Resources