What do I do about a Context? - parceler

I have a class which is a subclass of ArrayAdpater, and I'm trying to make it parcable.
I keep getting this error
"Error:(21, 36) error: Parceler: Unable to find read/write generator for type android.content.Context for android.content.Context context"
Here is the class:
#org.parceler.Parcel
public class conversation_pager extends ArrayAdapter<String> {
private final ArrayList<String> messages;
private Context context;
#ParcelConstructor
public conversation_pager(Context context) {
super(context, -1);
// Initilize our variables
this.context = context;
this.messages = null;
}
public void addMessage(String user, String message) {
// Calm the linter down about a NUllPointerException.
if (messages == null) {
return;
}
// Add the message.
messages.add("<%s> %s".format(user, message));
notifyDataSetChanged();
}
};
I'm trying to avoid using a static context variable.

You shouldn't pass the context via a Parcelable. You'll need to rework your #Parcel object to only hold data and pass in the context where needed. Possibly like the following?:
public class ConversationPager extends ArrayAdapter<String> {
private final List<String> messages;
private fianl Context context;
public ConversationPager(Context context, List<Messages> messages) {
super(context, -1);
// Initilize our variables
this.context = context;
this.messsages = messages;
}
public ConversationPager(Context contex) {
this(context, new ArrayList<String>());
}
public void addMessage(String user, String message) {
// Calm the linter down about a NUllPointerException.
if (messages == null) {
return;
}
// Add the message.
messages.add("<%s> %s".format(user, message));
notifyDataSetChanged();
}
public List<String> getMessages() {
return messages;
}
};
Then you can wrap/unwrap the messages directly:
ConversationPager pager = new ConversationPager(context);
// Add some messages
// Parcel messages directly
Parcels.wrap(pager.getMessages();
// Then unwrap in the receiving context:
List<String> messages = Parcels.unwrap(incomingParcelableExtra);
ConversationPager
pager = new ConversationPager(context, messages);

Related

how to propagate the ServiceRequestContext to my customized thread pool

I have a scenario, which process armeria request, and dispatch some event to guava's EventBus. the problem is I loss the context while process the event in the EventBus handler.
I want to know is there any way to let the event processor access ServiceRequestContext.
class EventListener {
#Subscribe
public void process(SomeCustomizedClass event) {
final ServiceRequestContext context = ServiceRequestContext.currentOrNull();
log.info("process ServiceRequestContext context={}", context);
}
}
register the event handler.
EventBus eventBus = new AsyncEventBus(ThreadPoolTaskExecutor());
eventBus.register(new EventListener());
here is my Armeria service
#Slf4j
public class NameAuthRestApi {
final NameAuthService nameAuthService;
#Post("/auth")
#ProducesJson
public Mono<RealNameAuthResp> auth(RealNameAuthReq req) {
return nameAuthService.auth(NameAuthConverter.CONVERTER.toDto(req))
.handle((result, sink) -> {
if (result.isSuccess()) {
// I post an event here, but the event process couldn't access the ServiceRequestContext
// that's would be the problem.
eventBus.post(new SomeCustomizedClass(result));
final RealNameAuthResp realNameAuthResp = new RealNameAuthResp();
realNameAuthResp.setTradeNo(result.getTradeNo());
realNameAuthResp.setSuccess(true);
sink.next(realNameAuthResp);
sink.complete();
} else {
sink.error(new SystemException(ErrorCode.API_ERROR, result.errors()));
}
});
}
}
You need to do:
public Mono<RealNameAuthResp> auth(ServiceRequestContxt ctx, RealNameAuthReq req) {
// Executed by an EventLoop 1.
// This thread has the ctx in its thread local.
return nameAuthService.auth(NameAuthConverter.CONVERTER.toDto(req))
.handle((result, sink) -> {
// Executed by another EventLoop 2.
// But this doens't.
try (SafeCloseable ignord = ctx.push()) {
if (result.isSuccess()) {
...
} else {
...
}
}
});
}
The problem is that the handle method is executed by another thread that does not have the ctx in its thread local. So, you should manually set the ctx.
You can achieve the same effect using xAsync method with the ctx.eventLoop():
public Mono<RealNameAuthResp> auth(ServiceRequestContxt ctx, RealNameAuthReq req) {
return nameAuthService.auth(NameAuthConverter.CONVERTER.toDto(req))
.handleAsync((result, sink) -> {
if (result.isSuccess()) {
...
} else {
...
}
}, ctx.eventLoop());
}
We have two ways to solve this:
First, use the executor which has the ctx:
ctx.eventLoop().submit(new Task(new Event("eone")));
// If it's blocking task, then we must use ctx.blockingTaskExecutor().
Or, propagate the ctx manually:
#Slf4j
public static class Task implements Runnable {
private final Event event;
private final ServiceRequestContext ctx;
Task(Event event) {
this.event = event;
ctx = ServiceRequestContext.current();
}
#Override
public void run() {
try (SafeCloseable ignored = ctx.push()) {
...
}
}
}
#minwoox, to simplify, my code would be looks like this
public class NameAuthRestApi {
JobExecutor executor = new JobExecutor();
#Post("/code")
public HttpResponse authCode(ServiceRequestContext ctx) {
try (SafeCloseable ignore = ctx.push()) {
executor.submit(new Task(new Event("eone")));
}
return HttpResponse.of("OK");
}
#Getter
#AllArgsConstructor
public static class Event {
private String name;
}
#RequiredArgsConstructor
#Slf4j
public static class Task implements Runnable {
final Event event;
#Override
public void run() {
// couldn't access ServiceRequestContext here
ServiceRequestContext ctx = ServiceRequestContext.currentOrNull();
log.info("ctx={}, event={}", ctx, event);
}
}
public static class JobExecutor {
ExecutorService executorService = Executors.newFixedThreadPool(2);
public void submit(Task task) {
executorService.submit(task);
}
}
}

GWT Unit Testing with RequestFactory / Activities

I'm trying to test the start method of an Activity that uses RequestFactory.
I manage to test RF calls invoking directly the service using this article example, but I'm missing something mocking RF calls called from the tested activity.
It's more clear with the code.
EDIT : more specific
What I really want to know, is how to replace the response of a Receiver method (onSuccess,onFailure...) called in an Activity? This way I would be able to test the code inside the receiver method.
So basically here is my activity :
public class MyActivity extends AbstractActivity implements MyView.Presenter {
private List<MyEntityProxy> entities;
private MyView view;
private ClientFactory cf;
private EntityRequest entityRequest;
private AppRequestFactory rf;
#Inject
public ClientsListActivity(ClientsListViewEditor view, ClientFactory clientFactory) {
this.view = view;
this.clientFactory = clientFactory;
rf = clientFactory.getRequestFactory();
}
#Override
public void start(final AcceptsOneWidget panel, EventBus eventBus) {
view.setPresenter(this);
refreshEntities();
}
public void refreshEntities(){
entityRequest = rf.entityRequest();
entityRequest.getAll().with("opt1,"opt2").fire(new Receiver<List<MyEntityProxy>>() {
#Override
public void onSuccess(List<MyEntityProxy> response) {
entities = response;
entityRequest = requestFactory.clientRequest();
}
});
}
public List<MyEntityProxy> getEntities(){
return entities;
}
}
To test it in JUnit I use GwtMockito, so here is the test class MyActivityTest :
#RunWith(GwtMockitoTestRunner.class)
public class ClientListActivityTest{
private MyActivity activity;
private EventBus eventBus;
private AppRequestFactory rf;
#GwtMock
private ClientFactory cf;
#GwtMock
private MyView;
#GwtMock
private AcceptsOneWidget panel;
#Before
public void setUp(){
eventBus = new SimpleEventBus();
rf = RequestFactoryHelper.create(AppRequestFactory.class);
cf = new ClientFactory(eventBus,rf);
activity = new MyActivity(view,cf);
}
#Test
public void testStartActivity(){
List<EntityProxy> result = new ArrayList<EntityProxy>();
EntityProxy expectedClient = mock(EntityProxy.class);
expectedEntity.setNom("Client 1");
EntityProxy expectedClient2 = mock(EntityProxy.class);
expectedEntity.setNom("Client 2");
result.add(expectedEntity);
result.add(expectedEntity2);
//Here I have to change the requestFactory Call, so I try that but without success :
Request<?> req = mock(Request.class);
doReturn(req).when(mock(MyEntityRequest.class)).getAll();
doAnswer(RequestFactoryHelper.ok(result)).when(req).fire(any(Receiver.class));
activity.start(panel, eventBus);
assertEquals(activity.getEntities().size(),2); //This Test fails size = 0
}
}
My RequestFactoryHelper (inspired from here ) :
public class RequestFactoryHelper {
private static class MockServiceLocator implements ServiceLocator {
private final Map<Class<?>, Object> services = new HashMap<Class<?>, Object>();
#Override
public Object getInstance( Class<?> clazz ) {
// Make sure to return always the same mocked instance for each requested type
Object result = services.get( clazz );
if (result == null) {
result = mock( clazz );
services.put( clazz, result );
}
return result;
}
}
private static class MockServiceDecorator extends ServiceLayerDecorator {
#Override
public <T extends ServiceLocator> T createServiceLocator( Class<T> clazz ) {
return (T) serviceLocator;
}
}
private static MockServiceLocator serviceLocator = new MockServiceLocator();
private static ServiceLayer serviceLayer = ServiceLayer.create( new MockServiceDecorator() );
/**
* Creates a {#link RequestFactory}.
*/
public static <T extends RequestFactory> T create( Class<T> requestFactoryClass ) {
SimpleRequestProcessor processor = new SimpleRequestProcessor( serviceLayer );
T factory = RequestFactorySource.create( requestFactoryClass );
factory.initialize( new SimpleEventBus(), new InProcessRequestTransport( processor ) );
return factory;
}
/**
* Returns the same service instance as used by the RequestFactory internals.
*/
public static <T> T getService( Class<T> serviceClass ) {
T result = (T) serviceLocator.getInstance( serviceClass );
reset( result ); // reset mock to avoid side effects when used in multiple tests
return result;
}
/**
* Returns the value passed to {#link Receiver#onSuccess(Object)}
*/
public static <T> T captureResult( Receiver<T> receiver ) {
ArgumentCaptor<Object> captor = ArgumentCaptor.forClass( Object.class );
verify( receiver ).onSuccess( (T) captor.capture() );
return (T) captor.getValue();
}
public static <T> Answer<T> ok(final T result) {
return new Answer<T>() {
#Override
public T answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
Object _receiver = args[args.length - 1];
Receiver<T> receiver = (Receiver<T>)_receiver;
receiver.onSuccess(result);
return null;
}
};
}
}
This is how I tested the Receiver method "onSuccess". I created a custom Answer for Mockito.doAnswer.
The code to test.
public void myMethod(String arg1, String arg2) {
requestFactory.adminRequest().someMethod(arg1, arg2).fire(new Receiver<Void>() {
#Override
public void onSuccess(Void response) {
placeController.goTo(new MyPlace());
}
});
}
The test.
#Test
public void testMyMethod() {
String arg1 = "arg1";
String arg2 = "arg2";
when(requestFactory.adminRequest()).thenReturn(adminRequest);
when(adminRequest.someMethod(arg1, arg2)).thenReturn(request);
doAnswer(new Answer<Void>() {
#Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
Receiver<Void> receiver = (Receiver<Void>) args[0];
receiver.onSuccess(null);
return null;
}
}).when(request).fire(any(Receiver.class));
myActivity.myMethod(arg1, arg2);
verify(adminRequest).someMethod(arg1, arg2);
verify(request).fire(any(Receiver.class));
verify(placeController).goTo(any(myPlace.class));
}
requestFactory, adminRequest, request and placeController are all mocks.

INetworkConnectionEvents Supports what?

I'm trying to use this API; however, I cannot get the events to fire.
So this is using Network List 1.0 Type Library com.
Here is my code:
public class AvailibleWLan : INetworkListManagerEvents, INetworkEvents, INetworkConnectionEvents
{
public NETWORKLIST.INetworkListManager NewWorkList {get;set;}
public List<WirelessNetwork> Connections { get; set; }
public AvailibleWLan()
{
Connections = new List<WirelessNetwork>();
NewWorkList = new NETWORKLIST.NetworkListManager();
foreach (NETWORKLIST.INetwork Network in NewWorkList.GetNetworks(NETWORKLIST.NLM_ENUM_NETWORK.NLM_ENUM_NETWORK_ALL))
{
String Name = Network.GetName();
var Connectivity = Network.GetConnectivity();
var Description = Network.GetDescription();
}
}
//public event NetworkPropertyChanged NetworkConnectivityChanged;
public WirelessNetwork Network { get; set; }
void INetworkListManagerEvents.ConnectivityChanged(NLM_CONNECTIVITY newConnectivity)
{
throw new NotImplementedException();
}
void INetworkConnectionEvents.NetworkConnectionConnectivityChanged(Guid connectionId, NLM_CONNECTIVITY newConnectivity)
{
throw new NotImplementedException();
}
void INetworkConnectionEvents.NetworkConnectionPropertyChanged(Guid connectionId, NLM_CONNECTION_PROPERTY_CHANGE Flags)
{
throw new NotImplementedException();
}
void INetworkEvents.NetworkAdded(Guid networkId)
{
throw new NotImplementedException();
}
void INetworkEvents.NetworkConnectivityChanged(Guid networkId, NLM_CONNECTIVITY newConnectivity)
{
throw new NotImplementedException();
}
void INetworkEvents.NetworkDeleted(Guid networkId)
{
throw new NotImplementedException();
}
void INetworkEvents.NetworkPropertyChanged(Guid networkId, NLM_NETWORK_PROPERTY_CHANGE Flags)
{
throw new NotImplementedException();
}
}
So i have put a break on all the events. and vs is never breaking out.
you defined all necessary callback functions, thats great. But you have to register for these events with calling the network interface method "advise" for the networks of interest.
Here is a code sample for that:
namespace NetworkListSample
{
class TestNetworkEvents : INetworkListManagerEvents, INetworkConnectionEvents
{
private INetworkListManager m_nlm = new NetworkListManager();
private static Guid s_INetworkListManagerEventsGuid = typeof(INetworkListManagerEvents).GUID;
private static Guid s_INetworkConnectionEventsGuid = typeof(INetworkConnectionEvents).GUID;
public void RegisterForEvents()
{
// Here it will only register for events of a network which is connected,
// if you wish to register for events of disconnected networks
// use a different NLM_ENUM_NETWORK enum value
IEnumNetworks Networks = m_nlm.GetNetworks(NLM_ENUM_NETWORK.NLM_ENUM_NETWORK_CONNECTED);
foreach (INetwork item in Networks)
{
IConnectionPoint cp = null;
IConnectionPointContainer icpc = (IConnectionPointContainer)m_nlm;
int cookie = -1;
Guid tempGuid = s_INetworkListManagerEventsGuid;
icpc.FindConnectionPoint(ref tempGuid, out cp);
cp.Advise(this, out cookie);
}
}
public void ConnectivityChanged(NLM_CONNECTIVITY newConnectivity)
{
throw new NotImplementedException();
}
public void NetworkConnectionConnectivityChanged(Guid connectionId, NLM_CONNECTIVITY newConnectivity)
{
throw new NotImplementedException();
}
public void NetworkConnectionPropertyChanged(Guid connectionId, NLM_CONNECTION_PROPERTY_CHANGE Flags)
{
throw new NotImplementedException();
}
}
}
Please don't forget the "unadvise" which takes the integer cookie(s) as parameter.

RavenDB keeps throwing a ConcurrencyException

I keep getting a ConcurrencyException trying to update the same document multiple times in succession. PUT attempted on document '<id>' using a non current etag is the message.
On every save from our UI we publish an event using MassTransit. This event is sent to the subscriberqueues, but I put the Eventhandlers offline (testing offline subscribers). Once the eventhandler comes online the queue is read and the messages are processed as intended.
However since the same object is in the queue multiple times the first write succeeds, the next doesn't and throws this concurrencyexception.
I use a factory class to have a consistent IDocumentStore and IDocumentSession in all my applications. I specifically set the UseOptimisticConcurrency = false in the GetSession() method.
public static class RavenFactory
{
public static IDocumentStore CreateDocumentStore()
{
var store = new DocumentStore() { ConnectionStringName = "RavenDB" };
// Setting Conventions
store.Conventions.RegisterIdConvention<MyType>((db, cmd, e) => e.MyProperty.ToString());
store.Conventions.RegisterAsyncIdConvention<MyType>((db, cmd, e) => new CompletedTask<string>(e.MyProperty.ToString()));
// Registering Listeners
store
.RegisterListener(new TakeNewestConflictResolutionListener())
.RegisterListener(new DocumentConversionListener())
.RegisterListener(new DocumentStoreListener());
// Initialize and return
store.Initialize();
return store;
}
public static IDocumentSession GetSession(IDocumentStore store)
{
var session = store.OpenSession();
session.Advanced.UseOptimisticConcurrency = false;
return session;
}
}
The eventhandler looks like this. The IDocumentSession gets injected using Dependency Injection.
Here is the logic to get an instance of IDocumentSession.
private static void InitializeRavenDB(IUnityContainer container)
{
container.RegisterInstance<IDocumentStore>(RavenFactory.CreateDocumentStore(), new ContainerControlledLifetimeManager());
container.RegisterType<IDocumentSession, DocumentSession>(new PerResolveLifetimeManager(), new InjectionFactory(c => RavenFactory.GetSession(c.Resolve<IDocumentStore>())));
}
And here is the actual EventHandler which has the ConcurrencyException.
public class MyEventHandler:Consumes<MyEvent>.All, IConsumer
{
private readonly IDocumentSession _session;
public MyEventHandler(IDocumentSession session)
{
if (session == null) throw new ArgumentNullException("session");
_session = session;
}
public void Consume(MyEvent message)
{
Console.WriteLine("MyEvent received: Id = '{0}'", message.MyProperty);
try
{
_session.Store(message);
_session.SaveChanges();
}
catch (Exception ex)
{
var exc = ex.ToString();
// Deal with concurrent writes ...
throw;
}
}
}
I want to ignore any concurrencyexception for now until we can sort out with the business on how to tackle concurrency.
So, any ideas why I get the ConcurrencyException? I want the save to happen no matter whether the document has been updated before or not.
I am unfamiliar with configuring Unity, but you always want Singleton of the IDocumentStore. Below, I have coded the Singleton out manually, but I'm sure Unity would support it:
public static class RavenFactory
{
private static IDocumentStore store;
private static object syncLock = new object();
public static IDocumentStore CreateDocumentStore()
{
if(RavenFactory.store != null)
return RavenFactory.store;
lock(syncLock)
{
if(RavenFactory.store != null)
return RavenFactory.store;
var localStore = new DocumentStore() { ConnectionStringName = "RavenDB" };
// Setting Conventions
localStore .Conventions.RegisterIdConvention<MyType>((db, cmd, e) => e.MyProperty.ToString());
localStore .Conventions.RegisterAsyncIdConvention<MyType>((db, cmd, e) => new CompletedTask<string>(e.MyProperty.ToString()));
// Registering Listeners
localStore
.RegisterListener(new TakeNewestConflictResolutionListener())
.RegisterListener(new DocumentConversionListener())
.RegisterListener(new DocumentStoreListener());
// Initialize and return
localStore.Initialize();
RavenFactory.store = localStore;
return RavenFactory.store;
}
}
// As before
// public static IDocumentSession GetSession(IDocumentStore store)
//
}

Play framework 1.2.5 Websocket

Instead using the EventStream instead ArchivedEventStream, when I run command alert(notification) message go to all connected socket except the original sender, how I also can send to original sender.
Here is my model and controller, using WebSocket
EventModel
public class EventModel {
// ~~~~~~~~~ Let's chat!
final EventStream<EventModel.Event> events = new EventStream<EventModel.Event>(100);
/**
* Get the event
*/
public EventStream<EventModel.Event> getEventStream() {
return events;
}
/**
* A user say something on the room
*/
public void _alert(Notification notification){
if(notification == null) return;
events.publish(new EventModel.NotificationEvent(notification));
}
// ~~~~~~~~~ Events
public static abstract class Event {
final public String type;
final public Long timestamp;
public boolean sended;
public Event(String type) {
this.sended = false;
this.type = type;
this.timestamp = System.currentTimeMillis();
}
}
public static class NotificationEvent extends EventModel.Event{
public final Notification notification;
public NotificationEvent(Notification notification) {
super("notification");
this.notification = notification;
}
public User getReceiver(){
return notification.receiver;
}
}
// EventModel factory
static EventModel instance = null;
public static EventModel get() {
if(instance == null) {
instance = new EventModel();
}
return instance;
}
//Alert notification
public static void alert(Notification notification){
get()._alert(notification);
}
}
And here is controller
public class MyWebSocket extends RootController {
public static class WebSocket extends WebSocketController {
public static void echo(Long userId) {
//Security
User user = User.findById(userId);
EventModel eventCentre = EventModel.get();
// Socket connected, join the chat room
EventStream<EventModel.Event> eventStrean = eventCentre.getEventStream();
// Loop while the socket is open
while(inbound.isOpen()) {
// Wait for an event (either something coming on the inbound socket channel, or ChatRoom messages)
Either<WebSocketEvent,EventModel.Event> e = await(Promise.waitEither(
inbound.nextEvent(),
eventStrean.nextEvent()
));
//Handle if get any notification
for(EventModel.NotificationEvent event: ClassOf(EventModel.NotificationEvent.class).match(e._2)) {
if(!event.getReceiver().equals(user)) continue;
outbound.send(event.notification.toJson());
}
// Case: The socket has been closed
for(WebSocketClose closed: SocketClosed.match(e._1)) {
disconnect();
}
}
}
}
}
To send to the original sender as well remove or comment out this line:
if(!event.getReceiver().equals(user)) continue;
one small issue to be aware of
https://github.com/playframework/play1/pull/709