I'm trying to remove an object from the DefaultRedisList. The following replaces every single field in the object with the word "null" without actually removing the object from the list. What I'm I doing wrong, please explain?
Code:
public class CreateRedisTweetTester {
private static Logger logger = Logger.getLogger(CreateRedisTweetTester.class);
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(RedisConfig.class);
RedisTweetService tweetService = ctx.getBean("redisTweetService",RedisTweetService.class);
AbstractTweet twt = new AbstractTweet();
twt.setTweetId(4);
twt.setUserId(1);
twt.setTweetFlag(TweetFlag.T);
//newUser(tweetService,"2");
//createPost(tweetService,twt,"2");
tweetService.removeAbstractTweet(tweetId); <--- HERE
//Folllowing Line is the problem
List<AbstractTweet> absTweets = getTimeline(tweetService,"2");
logger.info("Size T => "+absTweets.size());
for(AbstractTweet absTweet : absTweets){
logger.info(absTweet);
}
}
}
==============================================================================================
@Service()
@Repository
public class RedisTweetServiceImpl implements RedisTweetService{
public static final Logger logger = LoggerFactory.getLogger(RedisTweetServiceImpl.class);
@Autowired private RedisAtomicLong userIdCounter;
@Autowired private RedisAtomicLong postIdCounter;
@Autowired private ValueOperations<String, String> valueOps;
// Global Timeline
private final RedisList<String> timeline;
private final RedisList<String> users;
private final StringRedisTemplate stringTemplate;
private BoundListOperations<String, String> timelineLsOp;
private final HashMapper<AbstractTweet, String, String> postMapper = new DecoratingStringHashMapper<AbstractTweet>(
new JacksonHashMapper<AbstractTweet>(AbstractTweet.class));
@Autowired
public RedisTweetServiceImpl(StringRedisTemplate stringTemplate){
this.stringTemplate = stringTemplate;
timelineLsOp = stringTemplate.boundListOps(KeyUtils.timeline());
timeline = new DefaultRedisList<String>(timelineLsOp,800);
users = new DefaultRedisList<String>(KeyUtils.users(), stringTemplate);
}
@Override
public String addUser(String userId) {
String hid = String.valueOf(userIdCounter.incrementAndGet());
// save user_id as hash
// uid -> user
BoundHashOperations<String, String, String> userOps = stringTemplate.boundHashOps(KeyUtils.hid(hid));
userOps.put("user_id", userId);
valueOps.set(KeyUtils.user(userId), hid);
users.add(userId);
return findUser(userId);
}
@Override
public void abstractTweet(String userId, AbstractTweet post) {
String hid = findHid(userId);
post.setHashId(hid);
String pid = String.valueOf(postIdCounter.incrementAndGet());
long tweetId = post.getTweetId();
// add post
post(pid).putAll(postMapper.toHash(post));
valueOps.set(KeyUtils.tweet(String.valueOf(tweetId)), pid);
// add links
posts(hid).addFirst(pid);
timeline(hid).addFirst(pid);
timeline.addFirst(pid);
}
@Override
public void removeAbstractTweet(String tweetId) {
String pid = findPid(tweetId);
timelineLsOp.getOperations().delete(KeyUtils.post(pid));
timelineLsOp.getOperations().delete(KeyUtils.tweet(tweetId));
AbstractTweet t = getAbstractTweet(pid).get(0);
logger.info("Size => "+timeline.size());
}
@Override
public String findPid(String tweetId) {
return valueOps.get(KeyUtils.tweet(tweetId));
}
@Override
public List<AbstractTweet> getAbstractTweet(String pid) {
return Collections.singletonList(post(post(pid)));
}
@Override
public List<AbstractTweet> getAbstractTweets(String uid, Range range) {
return convertPidsToPosts(KeyUtils.posts(uid), range);
}
//TEST
@Override
public List<AbstractTweet> getTimeline(String uid, Range range) {
String hid = findHid(uid);
logger.info("Hash Id: "+hid);
List<AbstractTweet> absList = convertPidsToPosts(KeyUtils.timeline(hid), range);
logger.info(String.valueOf("Redis List Size: "+absList.size()));
return absList;
}
@Override
public Collection<AbstractTweet> timeline(Range range) {
return convertPidsToPosts(KeyUtils.timeline(), range);
}
@Override
public Collection<String> newUsers(Range range) {
return users.range(range.begin, range.end);
}
@Override
public boolean isPostValid(String pid) {
return stringTemplate.hasKey(KeyUtils.post(pid));
}
@Override
public boolean hasMoreTweets(String targetUid, Range range) {
return posts(targetUid).size() > range.end + 1;
}
@Override
public boolean hasMoreTimeline(String targetUid, Range range) {
return timeline(targetUid).size() > range.end + 1;
}
@Override
public boolean hasMoreTimeline(Range range) {
return timeline.size() > range.end + 1;
}
private String findUser(String hid) {
if (!StringUtils.hasText(hid)) {
return "";
}
BoundHashOperations<String, String, String> userOps = stringTemplate.boundHashOps(KeyUtils.hid(hid));
return userOps.get("user_id");
}
public String findHid(String name) {
return valueOps.get(KeyUtils.user(name));
}
public boolean isUserValid(String name) {
return stringTemplate.hasKey(KeyUtils.user(name));
}
private RedisMap<String, String> post(String pid) {
return new DefaultRedisMap<String, String>(KeyUtils.post(pid), stringTemplate);
}
private RedisList<String> posts(String uid) {
return new DefaultRedisList<String>(KeyUtils.posts(uid), stringTemplate);
}
private RedisList<String> timeline(String uid) {
return new DefaultRedisList<String>(KeyUtils.timeline(uid), stringTemplate);
}
private List<AbstractTweet> convertPidsToPosts(String key, Range range) {
logger.info("Key => "+key);
String pid = "pid:*->";
final String pidKey = "#";
final String hashId = "hashId";
final String userId = "userId";
final String tweetId = "tweetId";
final String tweetFlag ="tweetFlag";
SortQuery<String> query = SortQueryBuilder
.sort(key)
.noSort()
.get(pidKey)
.get(pid+userId)
.get(pid+tweetId)
.get(pid+tweetFlag)
.get(pid + hashId).limit(range.begin, range.end).build();
BulkMapper<AbstractTweet, String> hm = new BulkMapper<AbstractTweet, String>() {
@Override
public AbstractTweet mapBulk(List<String> bulk) {
Map<String, String> map = new LinkedHashMap<String, String>();
Iterator<String> iterator = bulk.iterator();
String pid = iterator.next();
map.put(userId, iterator.next());
map.put(tweetId,iterator.next());
map.put(tweetFlag, iterator.next());
map.put(hashId, iterator.next());
return post(map);
}
};
List<AbstractTweet> sort = stringTemplate.sort(query, hm);
return sort;
}
private AbstractTweet post(Map hash) {
return postMapper.fromHash(hash);
}
}