[ 
https://issues.apache.org/jira/browse/JAMES-3581?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

René Cordier closed JAMES-3581.
-------------------------------
    Resolution: Done

> As a JMAP extension writer, I want to PUSH state changes for my extensions
> --------------------------------------------------------------------------
>
>                 Key: JAMES-3581
>                 URL: https://issues.apache.org/jira/browse/JAMES-3581
>             Project: James Server
>          Issue Type: Improvement
>          Components: JMAP
>    Affects Versions: 3.6.0
>            Reporter: Benoit Tellier
>            Assignee: Antoine Duprat
>            Priority: Major
>             Fix For: 3.7.0
>
>          Time Spent: 1.5h
>  Remaining Estimate: 0h
>
> h2. Why?
> JMAP specifications defines the minimal features to get a basic email 
> reading/writing experience.
> However, as part of our job at Linagora, writing a collaborative email suite, 
> we need advanced collaborative features that uses custom, off-spec, JMAP 
> extensions.
> We thus want to implement these collaborative features as JMAP extensions 
> (because JMAP is so much of a nice protocol!).
> We were able to:
>  - Write custom methods pretty much directly.
>  - We needed to contribute modular definition of session "capabilities" to be 
> advertising our custom ones.
> But we are missing the push for custom extensions.
> h2. What?
> As an extension developper I want to be able to register my type states and 
> have states matching my format:
> {code:java}
> object IntState {
>   def parse(string: String): Either[IllegalArgumentException, IntState] = 
> Try(Integer.parseInt(string))
>     .toEither
>     .map(IntState(_))
>     .left.map(new IllegalArgumentException(_))
> }
> case class IntState(i: Int) extends State {
>   override def serialize: String = i.toString
> }
> case object CustomTypeName extends TypeName {
>   override val asString: String = "MyTypeName"
>   override def parse(string: String): Option[TypeName] = string match {
>     case CustomTypeName.asString => Some(CustomTypeName)
>     case _ => None
>   }
>   override def parseState(string: String): Either[IllegalArgumentException, 
> IntState] = IntState.parse(string)
> }
> {code}
> Given this, I want to be injecting my extensions to the push in the guice 
> module definition:
> {code:java}
>     Multibinder.newSetBinder(binder(), classOf[TypeName])
>       .addBinding()
>       .toInstance(CustomTypeName)
>     Multibinder.newSetBinder(binder(), classOf[GuiceProbe])
>       .addBinding()
>       .to(classOf[JmapEventBusProbe])
> {code}
> Doing so should allow me to emit 'custon' state change push notifications:
> {code:java}
>     val stateChangeEvent: StateChangeEvent = StateChangeEvent(eventId = 
> CustomMethodContract.eventId, username = BOB, map = Map(CustomTypeName -> 
> intState))
>     SMono(jmapEventBus.dispatch(stateChangeEvent, 
> AccountIdRegistrationKey(accountId))).block()
> {code}
> Which allows generating state change events PUSH notifications carried over 
> via webSocket or SSE for your extensions :-)
> h2. How?
> Modularize the definition of State (extensions might not want to have it 
> backed by a UUID), allow creating custom type states (parse them, and from 
> them be able to parse the associated state). We also need to transport these 
> additional type states as part of our event system.
> h2. Definition of done
> Write an integration test where you emit a custom type state with an exotic 
> state implementation (meaning not backed by a UUID) and have the StateChange 
> event carried over to the client, for instance using WebSocket.
> h2. Proof of concept
> Quan had been putting this PR together: 
> https://github.com/apache/james-project/pull/391



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to