├── GCP1.png
├── GCP2.png
├── GCP3.png
├── GCP4.png
├── .gitignore
├── NOTICE
├── presence-client
├── src
│ ├── eclipse
│ │ └── launch
│ │ │ ├── GetUsers.launch
│ │ │ ├── GetUsers4.launch
│ │ │ ├── PutUsers4.launch
│ │ │ └── FetchUsers.launch
│ └── main
│ │ ├── java
│ │ └── org
│ │ │ └── symphonyoss
│ │ │ └── s2
│ │ │ └── canon
│ │ │ └── example
│ │ │ └── presence
│ │ │ ├── PresenceConstants.java
│ │ │ ├── facade
│ │ │ ├── PresenceJwtGenerator.java
│ │ │ ├── IPresenceModelEntity.java
│ │ │ ├── IPresence.java
│ │ │ └── Presence.java
│ │ │ ├── GetUsers4.java
│ │ │ ├── FetchUsers.java
│ │ │ ├── PutUsers4.java
│ │ │ └── GetUsers.java
│ │ └── canon
│ │ └── presence.json
└── pom.xml
├── presence-server
├── src
│ ├── eclipse
│ │ └── launch
│ │ │ └── PresenceServer.launch
│ └── main
│ │ └── java
│ │ └── org
│ │ └── symphonyoss
│ │ └── s2
│ │ └── canon
│ │ └── example
│ │ └── presence
│ │ └── server
│ │ ├── UsersUserIdTestHandler.java
│ │ ├── UsersAsyncFetchHandler.java
│ │ ├── UsersUserIdHandler.java
│ │ ├── UsersUpdateHandler.java
│ │ ├── UsersFetchHandler.java
│ │ ├── UsersAsyncHandler.java
│ │ ├── UsersUpdateAsyncHandler.java
│ │ ├── UsersHandler.java
│ │ └── PresenceServer.java
└── pom.xml
├── pom.xml
├── LICENSE
└── README.md
/GCP1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/symphonyoss/canon-example/master/GCP1.png
--------------------------------------------------------------------------------
/GCP2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/symphonyoss/canon-example/master/GCP2.png
--------------------------------------------------------------------------------
/GCP3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/symphonyoss/canon-example/master/GCP3.png
--------------------------------------------------------------------------------
/GCP4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/symphonyoss/canon-example/master/GCP4.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.ear
17 | *.zip
18 | *.tar.gz
19 | *.rar
20 |
21 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
22 | hs_err_pid*
23 |
24 | **/*.log
25 | **/nohup.out
26 |
27 | .DS_Store
28 | .idea/**
29 | **/target/**
30 | target/**
31 |
32 | # Eclipse
33 | .metadata/**
34 | .settings/**
35 | **/.settings/**
36 | **/*.prefs
37 | **/*.project
38 | **/*.classpath
39 |
40 | workspace/**
41 | /.recommenders/
42 |
43 | **/*.yaml
44 |
45 | */.gitignore
46 |
--------------------------------------------------------------------------------
/NOTICE:
--------------------------------------------------------------------------------
1 | Symphony Canon
2 | Copyright 2017-2018 Symphony Communication Services, LLC.
3 | http://symphony.com/
4 |
5 | ========================================================================
6 | List of Category B Licenses
7 | ========================================================================
8 | CDDL + GPLv2 with classpath exception javax.servlet-api(javax.servlet)
9 | CDDL-GPLv2+CE mailapi(javax.mail)
10 | Mozilla Public License, Version 2.0 rhino(org.mozilla)
11 | Common Development and Distribution License (CDDL) v1.0 activation(javax.activation)
12 | ========================================================================
13 | Eclipse Public License 1.0
14 | ========================================================================
15 | The following components are provided under the Eclipse Public License 1.0. See project link for details.
16 |
17 | Eclipse Public License - v 1.0-GNU Lesser General Public license logback-classic(ch.qos.logback)
18 | Eclipse Public License - v 1.0-GNU Lesser General Public License logback-core(ch.qos.logback)
19 |
--------------------------------------------------------------------------------
/presence-client/src/eclipse/launch/GetUsers.launch:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/presence-client/src/eclipse/launch/GetUsers4.launch:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/presence-client/src/eclipse/launch/PutUsers4.launch:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/presence-client/src/eclipse/launch/FetchUsers.launch:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/presence-server/src/eclipse/launch/PresenceServer.launch:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/presence-client/src/main/java/org/symphonyoss/s2/canon/example/presence/PresenceConstants.java:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | *
4 | * Copyright 2019 Symphony Communication Services, LLC.
5 | *
6 | * Licensed to The Symphony Software Foundation (SSF) under one
7 | * or more contributor license agreements. See the NOTICE file
8 | * distributed with this work for additional information
9 | * regarding copyright ownership. The ASF licenses this file
10 | * to you under the Apache License, Version 2.0 (the
11 | * "License"); you may not use this file except in compliance
12 | * with the License. You may obtain a copy of the License at
13 | *
14 | * http://www.apache.org/licenses/LICENSE-2.0
15 | *
16 | * Unless required by applicable law or agreed to in writing,
17 | * software distributed under the License is distributed on an
18 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19 | * KIND, either express or implied. See the License for the
20 | * specific language governing permissions and limitations
21 | * under the License.
22 | */
23 |
24 | package org.symphonyoss.s2.canon.example.presence;
25 |
26 | public class PresenceConstants
27 | {
28 | public static final int SERVER_PORT = 8083;
29 | public static final String SERVER_HOST = "localhost";
30 | public static final String SERVER_URL = "http://" + SERVER_HOST + ":" + SERVER_PORT;
31 | }
32 |
--------------------------------------------------------------------------------
/presence-client/src/main/java/org/symphonyoss/s2/canon/example/presence/facade/PresenceJwtGenerator.java:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | *
4 | * Copyright 2018 Symphony Communication Services, LLC.
5 | *
6 | * Licensed to The Symphony Software Foundation (SSF) under one
7 | * or more contributor license agreements. See the NOTICE file
8 | * distributed with this work for additional information
9 | * regarding copyright ownership. The ASF licenses this file
10 | * to you under the Apache License, Version 2.0 (the
11 | * "License"); you may not use this file except in compliance
12 | * with the License. You may obtain a copy of the License at
13 | *
14 | * http://www.apache.org/licenses/LICENSE-2.0
15 | *
16 | * Unless required by applicable law or agreed to in writing,
17 | * software distributed under the License is distributed on an
18 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19 | * KIND, either express or implied. See the License for the
20 | * specific language governing permissions and limitations
21 | * under the License.
22 | */
23 |
24 | package org.symphonyoss.s2.canon.example.presence.facade;
25 |
26 | import org.symphonyoss.s2.canon.runtime.jjwt.Hs256JwtGenerator;
27 |
28 | public class PresenceJwtGenerator extends Hs256JwtGenerator
29 | {
30 | public PresenceJwtGenerator()
31 | {
32 | super("Njl5qoxJAGmcOcRfDdhqe+/FP3BFV7p39htaB9Tv8hE=");
33 | withTTL(360000);
34 | withSubject(System.getProperty("user.name"));
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/presence-client/src/main/java/org/symphonyoss/s2/canon/example/presence/facade/IPresenceModelEntity.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2018 Symphony Communication Services, LLC.
3 | *
4 | * Licensed to The Symphony Software Foundation (SSF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | *
21 | *----------------------------------------------------------------------------------------------------
22 | * Proforma generated from
23 | * Template groupId org.symphonyoss.s2.canon
24 | * artifactId canon-template-java
25 | * Template name proforma/java/Model/I_ModelEntity.java.ftl
26 | * Template version 1.0
27 | * At 2018-02-14 18:20:04 GMT-08:00
28 | *----------------------------------------------------------------------------------------------------
29 | */
30 |
31 | package org.symphonyoss.s2.canon.example.presence.facade;
32 |
33 |
34 | import org.symphonyoss.s2.canon.runtime.IEntity;
35 |
36 | public interface IPresenceModelEntity extends IEntity
37 | {
38 | }
39 | /*----------------------------------------------------------------------------------------------------
40 | * End of template proforma/java/Model/I_ModelEntity.java.ftl
41 | * End of code generation
42 | *------------------------------------------------------------------------------------------------- */
--------------------------------------------------------------------------------
/presence-server/src/main/java/org/symphonyoss/s2/canon/example/presence/server/UsersUserIdTestHandler.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2018 Symphony Communication Services, LLC.
3 | *
4 | * Licensed to The Symphony Software Foundation (SSF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | *
21 | */
22 |
23 | package org.symphonyoss.s2.canon.example.presence.server;
24 |
25 | import javax.annotation.concurrent.Immutable;
26 |
27 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresence;
28 | import org.symphonyoss.s2.canon.example.presence.canon.UserId;
29 | import org.symphonyoss.s2.canon.example.presence.canon.UsersUserIdTestPathHandler;
30 | import org.symphonyoss.s2.canon.example.presence.facade.IPresence;
31 | import org.symphonyoss.s2.canon.runtime.exception.CanonException;
32 | import org.symphonyoss.s2.canon.runtime.http.IRequestAuthenticator;
33 | import org.symphonyoss.s2.fugue.core.trace.ITraceContext;
34 |
35 | /**
36 | * Facade for Path name=UsersUserIdTest
37 | *
38 | * Manipulate a single user's presence.
39 | *
40 | * Path /users/{userId}/test
41 | * Bind Path users/
42 | */
43 | @Immutable
44 | public class UsersUserIdTestHandler extends UsersUserIdTestPathHandler
45 | {
46 | private IPresence presenceModel_;
47 |
48 | public UsersUserIdTestHandler(IPresence presenceModel, IRequestAuthenticator authenticator)
49 | {
50 | super(authenticator);
51 |
52 | presenceModel_ = presenceModel;
53 | }
54 |
55 | @Override
56 | public IUserPresence handleGet(String canonAuth, ITraceContext canonTrace, UserId userId) throws CanonException
57 | {
58 | return presenceModel_.getUser(userId);
59 | }
60 | }
--------------------------------------------------------------------------------
/presence-server/src/main/java/org/symphonyoss/s2/canon/example/presence/server/UsersAsyncFetchHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | *
4 | * Copyright 2018 Symphony Communication Services, LLC.
5 | *
6 | * Licensed to The Symphony Software Foundation (SSF) under one
7 | * or more contributor license agreements. See the NOTICE file
8 | * distributed with this work for additional information
9 | * regarding copyright ownership. The ASF licenses this file
10 | * to you under the Apache License, Version 2.0 (the
11 | * "License"); you may not use this file except in compliance
12 | * with the License. You may obtain a copy of the License at
13 | *
14 | * http://www.apache.org/licenses/LICENSE-2.0
15 | *
16 | * Unless required by applicable law or agreed to in writing,
17 | * software distributed under the License is distributed on an
18 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19 | * KIND, either express or implied. See the License for the
20 | * specific language governing permissions and limitations
21 | * under the License.
22 | */
23 |
24 | package org.symphonyoss.s2.canon.example.presence.server;
25 |
26 | import java.util.concurrent.ExecutorService;
27 |
28 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresence;
29 | import org.symphonyoss.s2.canon.example.presence.canon.UserId;
30 | import org.symphonyoss.s2.canon.example.presence.canon.UsersFetchAsyncPathHandler;
31 | import org.symphonyoss.s2.canon.example.presence.facade.IPresence;
32 | import org.symphonyoss.s2.canon.runtime.exception.CanonException;
33 | import org.symphonyoss.s2.canon.runtime.http.IRequestAuthenticator;
34 | import org.symphonyoss.s2.fugue.core.trace.ITraceContext;
35 | import org.symphonyoss.s2.fugue.pipeline.IConsumer;
36 |
37 | public class UsersAsyncFetchHandler extends UsersFetchAsyncPathHandler
38 | {
39 | private IPresence presenceModel_;
40 |
41 | public UsersAsyncFetchHandler(IPresence presenceModel, ExecutorService processExecutor, ExecutorService responseExecutor, IRequestAuthenticator authenticator)
42 | {
43 | super(processExecutor, responseExecutor, authenticator);
44 |
45 | presenceModel_ = presenceModel;
46 | }
47 |
48 | @Override
49 | public void handlePost(UserId canonPayload, IConsumer canonConsumer, String canonAuth, ITraceContext canonTrace)
50 | throws CanonException
51 | {
52 | canonConsumer.consume(presenceModel_.getUser(canonPayload), canonTrace);
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/presence-client/src/main/java/org/symphonyoss/s2/canon/example/presence/facade/IPresence.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2018 Symphony Communication Services, LLC.
3 | *
4 | * Licensed to The Symphony Software Foundation (SSF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | *
21 | *----------------------------------------------------------------------------------------------------
22 | * Proforma generated from
23 | * Template groupId org.symphonyoss.s2.canon
24 | * artifactId canon-template-java
25 | * Template name proforma/java/Model/I_.java.ftl
26 | * Template version 1.0
27 | * At 2018-01-14 16:40:50 GMT-08:00
28 | *----------------------------------------------------------------------------------------------------
29 | */
30 |
31 | package org.symphonyoss.s2.canon.example.presence.facade;
32 |
33 |
34 | import java.util.Collection;
35 |
36 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresence;
37 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresenceInfo;
38 | import org.symphonyoss.s2.canon.example.presence.canon.UserId;
39 | import org.symphonyoss.s2.canon.runtime.exception.ServerErrorException;
40 |
41 | public interface IPresence
42 | {
43 |
44 | Collection getAllUsers();
45 |
46 | IUserPresence getUser(UserId userId);
47 | void setUser(UserId userId, IUserPresenceInfo userPresenceInfo) throws ServerErrorException;
48 | }
49 | /*----------------------------------------------------------------------------------------------------
50 | * End of template proforma/java/Model/I_.java.ftl
51 | * End of code generation
52 | *------------------------------------------------------------------------------------------------- */
--------------------------------------------------------------------------------
/presence-server/src/main/java/org/symphonyoss/s2/canon/example/presence/server/UsersUserIdHandler.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2018 Symphony Communication Services, LLC.
3 | *
4 | * Licensed to The Symphony Software Foundation (SSF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | *
21 | */
22 |
23 | package org.symphonyoss.s2.canon.example.presence.server;
24 |
25 | import javax.annotation.concurrent.Immutable;
26 |
27 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresence;
28 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresenceInfo;
29 | import org.symphonyoss.s2.canon.example.presence.canon.UserId;
30 | import org.symphonyoss.s2.canon.example.presence.canon.UsersUserIdPathHandler;
31 | import org.symphonyoss.s2.canon.example.presence.facade.IPresence;
32 | import org.symphonyoss.s2.canon.runtime.exception.ServerErrorException;
33 | import org.symphonyoss.s2.canon.runtime.http.IRequestAuthenticator;
34 | import org.symphonyoss.s2.fugue.core.trace.ITraceContext;
35 |
36 | /**
37 | * Facade for Path name=UsersUserId
38 | *
39 | * Manipulate a single user's presence.
40 | *
41 | * Path /users/{userId}
42 | * Bind Path users/
43 | */
44 | @Immutable
45 | public class UsersUserIdHandler extends UsersUserIdPathHandler
46 | {
47 | private IPresence presenceModel_;
48 |
49 | public UsersUserIdHandler(IPresence presenceModel, IRequestAuthenticator authenticator)
50 | {
51 | super(authenticator);
52 |
53 | presenceModel_ = presenceModel;
54 | }
55 |
56 | @Override
57 | public IUserPresence handleGet(String canonAuth, ITraceContext canonTrace, UserId userId)
58 | {
59 | IUserPresence result = presenceModel_.getUser(userId);
60 |
61 | return result;
62 | }
63 |
64 | @Override
65 | public void handlePut(IUserPresenceInfo canonPayload, String canonAuth, ITraceContext canonTrace, UserId userId) throws ServerErrorException
66 | {
67 | presenceModel_.setUser(userId, canonPayload);
68 | }
69 | }
--------------------------------------------------------------------------------
/presence-server/src/main/java/org/symphonyoss/s2/canon/example/presence/server/UsersUpdateHandler.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2018 Symphony Communication Services, LLC.
3 | *
4 | * Licensed to The Symphony Software Foundation (SSF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | *
21 | */
22 |
23 | package org.symphonyoss.s2.canon.example.presence.server;
24 |
25 | import javax.annotation.concurrent.Immutable;
26 |
27 | import org.slf4j.Logger;
28 | import org.slf4j.LoggerFactory;
29 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresence;
30 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresenceList;
31 | import org.symphonyoss.s2.canon.example.presence.canon.UserPresenceInfo;
32 | import org.symphonyoss.s2.canon.example.presence.canon.UsersUpdatePathHandler;
33 | import org.symphonyoss.s2.canon.example.presence.facade.IPresence;
34 | import org.symphonyoss.s2.canon.runtime.exception.ServerErrorException;
35 | import org.symphonyoss.s2.canon.runtime.http.IRequestAuthenticator;
36 | import org.symphonyoss.s2.fugue.core.trace.ITraceContext;
37 |
38 | /**
39 | * Facade for Path name=UsersUpdate
40 | *
41 | * Manipulate a batch of users' presence.
42 | *
43 | * Path /users/update
44 | * Bind Path users/update
45 | */
46 | @Immutable
47 | public class UsersUpdateHandler extends UsersUpdatePathHandler
48 | {
49 | private static final Logger log_ = LoggerFactory.getLogger(UsersUpdateHandler.class);
50 |
51 | private IPresence presenceModel_;
52 |
53 | public UsersUpdateHandler(IPresence presenceModel, IRequestAuthenticator authenticator)
54 | {
55 | super(authenticator);
56 |
57 | presenceModel_ = presenceModel;
58 | }
59 |
60 | @Override
61 | public void handlePost(IUserPresenceList canonPayload, String canonAuth, ITraceContext canonTrace) throws ServerErrorException
62 | {
63 | for(IUserPresence userPresence : canonPayload.getData())
64 | {
65 | presenceModel_.setUser(userPresence.getUserId(),
66 | new UserPresenceInfo.Builder()
67 | .withStatus(userPresence.getStatus())
68 | .withText(userPresence.getText())
69 | .build()
70 | );
71 | }
72 | }
73 |
74 | }
--------------------------------------------------------------------------------
/presence-server/src/main/java/org/symphonyoss/s2/canon/example/presence/server/UsersFetchHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | *
4 | * Copyright 2018 Symphony Communication Services, LLC.
5 | *
6 | * Licensed to The Symphony Software Foundation (SSF) under one
7 | * or more contributor license agreements. See the NOTICE file
8 | * distributed with this work for additional information
9 | * regarding copyright ownership. The ASF licenses this file
10 | * to you under the Apache License, Version 2.0 (the
11 | * "License"); you may not use this file except in compliance
12 | * with the License. You may obtain a copy of the License at
13 | *
14 | * http://www.apache.org/licenses/LICENSE-2.0
15 | *
16 | * Unless required by applicable law or agreed to in writing,
17 | * software distributed under the License is distributed on an
18 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19 | * KIND, either express or implied. See the License for the
20 | * specific language governing permissions and limitations
21 | * under the License.
22 | */
23 |
24 | package org.symphonyoss.s2.canon.example.presence.server;
25 |
26 | import java.util.LinkedList;
27 | import java.util.List;
28 |
29 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresence;
30 | import org.symphonyoss.s2.canon.example.presence.canon.UserId;
31 | import org.symphonyoss.s2.canon.example.presence.canon.UsersFetchPathHandler;
32 | import org.symphonyoss.s2.canon.example.presence.facade.IPresence;
33 | import org.symphonyoss.s2.canon.runtime.exception.CanonException;
34 | import org.symphonyoss.s2.canon.runtime.http.IRequestAuthenticator;
35 | import org.symphonyoss.s2.fugue.core.trace.ITraceContext;
36 |
37 | public class UsersFetchHandler extends UsersFetchPathHandler
38 | {
39 | private IPresence presenceModel_;
40 |
41 | public UsersFetchHandler(IPresence presenceModel, IRequestAuthenticator authenticator)
42 | {
43 | super(authenticator);
44 |
45 | presenceModel_ = presenceModel;
46 | }
47 |
48 | @Override
49 | public List handlePost(List canonPayload, String canonAuth, ITraceContext canonTrace) throws CanonException
50 | {
51 | List result = new LinkedList<>();
52 |
53 | for(UserId userId : canonPayload)
54 | result.add(presenceModel_.getUser(userId));
55 |
56 | return result;
57 | }
58 |
59 | // public UsersFetchHandler(IPresence presenceModel, ExecutorService processExecutor, ExecutorService responseExecutor, IRequestAuthenticator authenticator)
60 | // {
61 | // super(processExecutor, responseExecutor, authenticator);
62 | //
63 | // presenceModel_ = presenceModel;
64 | // }
65 | //
66 | // @Override
67 | // public void handlePost(UserId canonPayload, IConsumer canonConsumer, String canonAuth, ITraceContext canonTrace)
68 | // throws CanonException
69 | // {
70 | // canonConsumer.consume(presenceModel_.getUser(canonPayload), canonTrace);
71 | // }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/presence-server/src/main/java/org/symphonyoss/s2/canon/example/presence/server/UsersAsyncHandler.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2018 Symphony Communication Services, LLC.
3 | *
4 | * Licensed to The Symphony Software Foundation (SSF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | *
21 | */
22 |
23 | package org.symphonyoss.s2.canon.example.presence.server;
24 |
25 | import java.util.ArrayList;
26 | import java.util.concurrent.ExecutorService;
27 |
28 | import javax.annotation.concurrent.Immutable;
29 |
30 | import org.symphonyoss.s2.canon.example.presence.canon.Cursor;
31 | import org.symphonyoss.s2.canon.example.presence.canon.CursorLimit;
32 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresence;
33 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresencePage;
34 | import org.symphonyoss.s2.canon.example.presence.canon.UserPresencePage;
35 | import org.symphonyoss.s2.canon.example.presence.canon.UsersAsyncPathHandler;
36 | import org.symphonyoss.s2.canon.example.presence.facade.IPresence;
37 | import org.symphonyoss.s2.canon.runtime.exception.CanonException;
38 | import org.symphonyoss.s2.canon.runtime.http.IRequestAuthenticator;
39 | import org.symphonyoss.s2.fugue.core.trace.ITraceContext;
40 | import org.symphonyoss.s2.fugue.pipeline.IConsumer;
41 |
42 | /**
43 | * Facade for Path name=Users
44 | *
45 | * Fetch all users' presence.
46 | *
47 | * Path /users
48 | * Bind Path users
49 | */
50 | @Immutable
51 | public class UsersAsyncHandler extends UsersAsyncPathHandler
52 | {
53 | private IPresence presenceModel_;
54 |
55 | public UsersAsyncHandler(IPresence presenceModel, ExecutorService processExecutor, ExecutorService responseExecutor, IRequestAuthenticator authenticator)
56 | {
57 | super(processExecutor, responseExecutor, authenticator);
58 | presenceModel_ = presenceModel;
59 | }
60 |
61 | @Override
62 | public void handleGet(IConsumer canonConsumer, String canonAuth, ITraceContext canonTrace, Cursor cursor,
63 | CursorLimit limit) throws CanonException
64 | {
65 | System.err.println("Authenticated caller is " + canonAuth);
66 | UserPresencePage.Builder builder = new UserPresencePage.Builder();
67 |
68 | builder.withData(new ArrayList(presenceModel_.getAllUsers()));
69 |
70 | canonConsumer.consume(builder.build(), canonTrace);
71 | canonConsumer.close();
72 | }
73 |
74 | @Override
75 | public void handlePut(String canonAuth, ITraceContext canonTrace, Cursor cursor, CursorLimit limit) throws CanonException
76 | {
77 | // TODO Auto-generated method stub
78 |
79 | }
80 | }
--------------------------------------------------------------------------------
/presence-client/src/main/java/org/symphonyoss/s2/canon/example/presence/GetUsers4.java:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | *
4 | * Copyright 2018 Symphony Communication Services, LLC.
5 | *
6 | * Licensed to The Symphony Software Foundation (SSF) under one
7 | * or more contributor license agreements. See the NOTICE file
8 | * distributed with this work for additional information
9 | * regarding copyright ownership. The ASF licenses this file
10 | * to you under the Apache License, Version 2.0 (the
11 | * "License"); you may not use this file except in compliance
12 | * with the License. You may obtain a copy of the License at
13 | *
14 | * http://www.apache.org/licenses/LICENSE-2.0
15 | *
16 | * Unless required by applicable law or agreed to in writing,
17 | * software distributed under the License is distributed on an
18 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19 | * KIND, either express or implied. See the License for the
20 | * specific language governing permissions and limitations
21 | * under the License.
22 | */
23 |
24 | package org.symphonyoss.s2.canon.example.presence;
25 |
26 | import java.io.IOException;
27 |
28 | import org.apache.http.impl.client.BasicCookieStore;
29 | import org.apache.http.impl.client.CloseableHttpClient;
30 | import org.apache.http.impl.client.HttpClients;
31 | import org.slf4j.Logger;
32 | import org.slf4j.LoggerFactory;
33 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresence;
34 | import org.symphonyoss.s2.canon.example.presence.canon.PresenceHttpModelClient;
35 | import org.symphonyoss.s2.canon.example.presence.canon.PresenceModel;
36 | import org.symphonyoss.s2.canon.example.presence.canon.UserId;
37 | import org.symphonyoss.s2.canon.example.presence.canon.UsersUserIdGetHttpRequest;
38 | import org.symphonyoss.s2.canon.example.presence.facade.PresenceJwtGenerator;
39 | import org.symphonyoss.s2.canon.runtime.IModelRegistry;
40 | import org.symphonyoss.s2.canon.runtime.ModelRegistry;
41 |
42 | /**
43 | * Fetch user 4 using the REST endpoint.
44 | *
45 | * @author Bruce Skingle
46 | *
47 | */
48 | public class GetUsers4
49 | {
50 | private static final Logger log_ = LoggerFactory.getLogger(GetUsers4.class);
51 |
52 | /**
53 | * Main.
54 | *
55 | * @param argv Command line args - ignored.
56 | *
57 | * @throws Exception If something goes wrong. This is just an example.
58 | */
59 | public static void main(String[] argv) throws Exception
60 | {
61 | IModelRegistry registry = new ModelRegistry().withFactories(PresenceModel.FACTORIES);
62 | PresenceHttpModelClient client = new PresenceHttpModelClient(registry, PresenceConstants.SERVER_URL, null, new PresenceJwtGenerator());
63 |
64 | UsersUserIdGetHttpRequest request = client.newUsersUserIdGetHttpRequestBuilder()
65 | .withUserId(UserId.newBuilder().build(4L))
66 | .build();
67 |
68 | BasicCookieStore cookieStore = new BasicCookieStore();
69 | CloseableHttpClient httpclient = HttpClients.custom()
70 | .setDefaultCookieStore(cookieStore)
71 | .build();
72 | try {
73 | IUserPresence p = request.execute(httpclient);
74 |
75 | System.err.printf("%10d %-20s %s%n", p.getUserId().getValue(), p.getStatus(), p.getText());
76 | }
77 | finally
78 | {
79 | try
80 | {
81 | httpclient.close();
82 | }
83 | catch (IOException e)
84 | {
85 | log_.error("Unable to close httpClient", e);
86 | }
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/presence-server/src/main/java/org/symphonyoss/s2/canon/example/presence/server/UsersUpdateAsyncHandler.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2018 Symphony Communication Services, LLC.
3 | *
4 | * Licensed to The Symphony Software Foundation (SSF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | *
21 | */
22 |
23 | package org.symphonyoss.s2.canon.example.presence.server;
24 |
25 | import java.util.concurrent.ExecutorService;
26 |
27 | import javax.annotation.concurrent.Immutable;
28 |
29 | import org.slf4j.Logger;
30 | import org.slf4j.LoggerFactory;
31 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresence;
32 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresenceList;
33 | import org.symphonyoss.s2.canon.example.presence.canon.UserPresenceInfo;
34 | import org.symphonyoss.s2.canon.example.presence.canon.UsersUpdateAsyncPathHandler;
35 | import org.symphonyoss.s2.canon.example.presence.facade.IPresence;
36 | import org.symphonyoss.s2.canon.runtime.exception.CanonException;
37 | import org.symphonyoss.s2.canon.runtime.exception.ServerErrorException;
38 | import org.symphonyoss.s2.canon.runtime.http.IRequestAuthenticator;
39 | import org.symphonyoss.s2.fugue.core.trace.ITraceContext;
40 |
41 | /**
42 | * Facade for Path name=UsersUpdate
43 | *
44 | * Manipulate a batch of users' presence.
45 | *
46 | * Path /users/update
47 | * Bind Path users/update
48 | */
49 | @Immutable
50 | public class UsersUpdateAsyncHandler extends UsersUpdateAsyncPathHandler
51 | {
52 | private static final Logger log_ = LoggerFactory.getLogger(UsersUpdateAsyncHandler.class);
53 |
54 | private IPresence presenceModel_;
55 |
56 | public UsersUpdateAsyncHandler(IPresence presenceModel, ExecutorService processExecutor, ExecutorService responseExecutor, IRequestAuthenticator authenticator)
57 | {
58 | super(processExecutor, responseExecutor, authenticator);
59 |
60 | presenceModel_= presenceModel;
61 | }
62 |
63 | /**
64 | * post /users/update
65 | * No summary given.
66 | *
67 | * @param canonPayload The request payload.
68 | * @param canonTrace A trace context.
69 | *
70 | * @throws CanonException If the method cannot be called
71 | */
72 |
73 | @Override
74 | public void handlePost(IUserPresenceList canonPayload, String canonAuth, ITraceContext canonTrace) throws CanonException
75 | {
76 | for(IUserPresence userPresence : canonPayload.getData())
77 | {
78 | presenceModel_.setUser(userPresence.getUserId(),
79 | new UserPresenceInfo.Builder()
80 | .withStatus(userPresence.getStatus())
81 | .withText(userPresence.getText())
82 | .build()
83 | );
84 |
85 | throw new ServerErrorException("BROKEN FOR TEST");
86 | }
87 | }
88 |
89 | }
--------------------------------------------------------------------------------
/presence-server/src/main/java/org/symphonyoss/s2/canon/example/presence/server/UsersHandler.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2018 Symphony Communication Services, LLC.
3 | *
4 | * Licensed to The Symphony Software Foundation (SSF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | *
21 | */
22 |
23 | package org.symphonyoss.s2.canon.example.presence.server;
24 |
25 | import java.util.ArrayList;
26 |
27 | import javax.annotation.Nonnull;
28 | import javax.annotation.Nullable;
29 | import javax.annotation.concurrent.Immutable;
30 |
31 | import org.symphonyoss.s2.canon.example.presence.canon.Cursor;
32 | import org.symphonyoss.s2.canon.example.presence.canon.CursorLimit;
33 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresence;
34 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresencePage;
35 | import org.symphonyoss.s2.canon.example.presence.canon.UserPresencePage;
36 | import org.symphonyoss.s2.canon.example.presence.canon.UsersPathHandler;
37 | import org.symphonyoss.s2.canon.example.presence.facade.IPresence;
38 | import org.symphonyoss.s2.canon.runtime.exception.CanonException;
39 | import org.symphonyoss.s2.canon.runtime.http.IRequestAuthenticator;
40 | import org.symphonyoss.s2.fugue.core.trace.ITraceContext;
41 |
42 | /**
43 | * Facade for Path name=Users
44 | *
45 | * Fetch all users' presence.
46 | *
47 | * Path /users
48 | * Bind Path users
49 | */
50 | @Immutable
51 | public class UsersHandler extends UsersPathHandler
52 | {
53 | private IPresence presenceModel_;
54 |
55 | public UsersHandler(IPresence presenceModel, IRequestAuthenticator authenticator)
56 | {
57 | super(authenticator);
58 |
59 | presenceModel_ = presenceModel;
60 | }
61 |
62 | /**
63 | * get /users
64 | * No summary given.
65 | *
66 | * @param cursor No summary given.
67 | * @param limit No summary given.
68 | * @return A UserPresencePage
69 | * @throws CanonException If the method cannot be called
70 | */
71 | @Override
72 | public @Nonnull IUserPresencePage handleGet(
73 | String canonAuth,
74 | ITraceContext traceContext,
75 | @Nullable Cursor cursor,
76 | @Nullable CursorLimit limit
77 | )
78 | throws CanonException
79 | {
80 | System.err.println("Authenticated caller is " + canonAuth);
81 | UserPresencePage.Builder builder = new UserPresencePage.Builder();
82 |
83 | builder.withData(new ArrayList(presenceModel_.getAllUsers()));
84 |
85 | return builder.build();
86 | }
87 |
88 | @Override
89 | public void handlePut(
90 | String canonAuth, ITraceContext traceContext, Cursor cursor, CursorLimit limit) throws CanonException
91 | {
92 | // TODO Auto-generated method stub
93 |
94 | }
95 |
96 |
97 | }
--------------------------------------------------------------------------------
/presence-client/src/main/java/org/symphonyoss/s2/canon/example/presence/FetchUsers.java:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | *
4 | * Copyright 2018 Symphony Communication Services, LLC.
5 | *
6 | * Licensed to The Symphony Software Foundation (SSF) under one
7 | * or more contributor license agreements. See the NOTICE file
8 | * distributed with this work for additional information
9 | * regarding copyright ownership. The ASF licenses this file
10 | * to you under the Apache License, Version 2.0 (the
11 | * "License"); you may not use this file except in compliance
12 | * with the License. You may obtain a copy of the License at
13 | *
14 | * http://www.apache.org/licenses/LICENSE-2.0
15 | *
16 | * Unless required by applicable law or agreed to in writing,
17 | * software distributed under the License is distributed on an
18 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19 | * KIND, either express or implied. See the License for the
20 | * specific language governing permissions and limitations
21 | * under the License.
22 | */
23 |
24 | package org.symphonyoss.s2.canon.example.presence;
25 |
26 | import java.io.IOException;
27 | import java.util.List;
28 |
29 | import org.apache.http.impl.client.BasicCookieStore;
30 | import org.apache.http.impl.client.CloseableHttpClient;
31 | import org.apache.http.impl.client.HttpClients;
32 | import org.slf4j.Logger;
33 | import org.slf4j.LoggerFactory;
34 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresence;
35 | import org.symphonyoss.s2.canon.example.presence.canon.PresenceHttpModelClient;
36 | import org.symphonyoss.s2.canon.example.presence.canon.PresenceModel;
37 | import org.symphonyoss.s2.canon.example.presence.canon.UserId;
38 | import org.symphonyoss.s2.canon.example.presence.canon.UsersFetchPostHttpRequest;
39 | import org.symphonyoss.s2.canon.example.presence.facade.PresenceJwtGenerator;
40 | import org.symphonyoss.s2.canon.runtime.IModelRegistry;
41 | import org.symphonyoss.s2.canon.runtime.ModelRegistry;
42 |
43 | /**
44 | * Fetch all users by calling a POST method.
45 | *
46 | * @author Bruce Skingle
47 | *
48 | */
49 | public class FetchUsers
50 | {
51 | private static final Logger log_ = LoggerFactory.getLogger(FetchUsers.class);
52 |
53 | /**
54 | * Main.
55 | *
56 | * @param argv Command line args - ignored.
57 | *
58 | * @throws Exception If something goes wrong. This is just an example.
59 | */
60 | public static void main(String[] argv) throws Exception
61 | {
62 | IModelRegistry registry = new ModelRegistry().withFactories(PresenceModel.FACTORIES);
63 | PresenceHttpModelClient client = new PresenceHttpModelClient(registry, PresenceConstants.SERVER_URL, null, new PresenceJwtGenerator());
64 |
65 |
66 | UsersFetchPostHttpRequest request = client.newUsersFetchPostHttpRequestBuilder()
67 | .withCanonPayload(UserId.newBuilder().build(1L))
68 | .withCanonPayload(UserId.newBuilder().build(2L))
69 | .withCanonPayload(UserId.newBuilder().build(3L))
70 | .build();
71 |
72 | BasicCookieStore cookieStore = new BasicCookieStore();
73 | CloseableHttpClient httpclient = HttpClients.custom()
74 | .setDefaultCookieStore(cookieStore)
75 | .build();
76 | try {
77 | List result = request.execute(httpclient);
78 |
79 | for(IUserPresence p : result)
80 | {
81 | System.err.printf("%10d %-20s %s%n", p.getUserId().getValue(), p.getStatus(), p.getText());
82 | }
83 | }
84 | finally
85 | {
86 | try
87 | {
88 | httpclient.close();
89 | }
90 | catch (IOException e)
91 | {
92 | log_.error("Unable to close httpClient", e);
93 | }
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/presence-server/src/main/java/org/symphonyoss/s2/canon/example/presence/server/PresenceServer.java:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | *
4 | * Copyright 2017 Symphony Communication Services, LLC.
5 | *
6 | * Licensed to The Symphony Software Foundation (SSF) under one
7 | * or more contributor license agreements. See the NOTICE file
8 | * distributed with this work for additional information
9 | * regarding copyright ownership. The SSF licenses this file
10 | * to you under the Apache License, Version 2.0 (the
11 | * "License"); you may not use this file except in compliance
12 | * with the License. You may obtain a copy of the License at
13 | *
14 | * http://www.apache.org/licenses/LICENSE-2.0
15 | *
16 | * Unless required by applicable law or agreed to in writing,
17 | * software distributed under the License is distributed on an
18 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19 | * KIND, either express or implied. See the License for the
20 | * specific language governing permissions and limitations
21 | * under the License.
22 | */
23 |
24 | package org.symphonyoss.s2.canon.example.presence.server;
25 |
26 | import java.io.IOException;
27 | import java.util.concurrent.ExecutorService;
28 | import java.util.concurrent.Executors;
29 |
30 | import org.symphonyoss.s2.canon.example.presence.PresenceConstants;
31 | import org.symphonyoss.s2.canon.example.presence.canon.PresenceModel;
32 | import org.symphonyoss.s2.canon.example.presence.facade.Presence;
33 | import org.symphonyoss.s2.canon.example.presence.facade.PresenceJwtGenerator;
34 | import org.symphonyoss.s2.canon.runtime.ModelRegistry;
35 | import org.symphonyoss.s2.canon.runtime.ModelServlet;
36 | import org.symphonyoss.s2.canon.runtime.jjwt.JwtSubjectAuthenticator;
37 | import org.symphonyoss.s2.fugue.FugueServer;
38 | import org.symphonyoss.s2.fugue.core.trace.log.LoggerTraceContextTransactionFactory;
39 |
40 | public class PresenceServer extends FugueServer
41 | {
42 |
43 |
44 | public PresenceServer()
45 | {
46 | super("PresenceServer", PresenceConstants.SERVER_PORT);
47 | }
48 |
49 |
50 | public static void main(String[] argv) throws IOException
51 | {
52 | PresenceServer server = new PresenceServer();
53 | Presence model = new Presence();
54 | ExecutorService executor = Executors.newFixedThreadPool(50);
55 | PresenceJwtGenerator generator = new PresenceJwtGenerator();
56 | JwtSubjectAuthenticator authenticator = new JwtSubjectAuthenticator(generator.getKey(), 3600000L, "unknown", generator.getSignatureAlgorithm().toString());
57 |
58 | ModelServlet servlet = new ModelServlet(new LoggerTraceContextTransactionFactory(), new ModelRegistry().withFactories(PresenceModel.FACTORIES))
59 | .withHandler(new UsersUserIdHandler(model, authenticator))
60 | .withHandler(new UsersUserIdTestHandler(model, authenticator))
61 | .withHandler(new UsersAsyncHandler(model, executor, executor, authenticator))
62 | .withHandler(new UsersFetchHandler(model, authenticator))
63 | // .withHandler(new UsersFetchAsyncHandler(model, executor, executor, authenticator))
64 | // .withHandler(new UsersUpdateHandler(model, authenticator))
65 | .withHandler(new UsersUpdateAsyncHandler(model, executor, executor, authenticator))
66 | ;
67 |
68 | server.withComponents(model, servlet)
69 | .start();
70 |
71 | try
72 | {
73 | server.join();
74 | }
75 | catch (InterruptedException e)
76 | {
77 | // TODO Auto-generated catch block
78 | e.printStackTrace();
79 | }
80 | // System.out.println("Server started, press RETURN to terminate");
81 | // System.in.read();
82 | //
83 | // System.out.println("Stopping...");
84 | //
85 | // server.stop();
86 | //
87 | // System.out.println("Finished.");
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/presence-client/src/main/java/org/symphonyoss/s2/canon/example/presence/PutUsers4.java:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | *
4 | * Copyright 2018 Symphony Communication Services, LLC.
5 | *
6 | * Licensed to The Symphony Software Foundation (SSF) under one
7 | * or more contributor license agreements. See the NOTICE file
8 | * distributed with this work for additional information
9 | * regarding copyright ownership. The ASF licenses this file
10 | * to you under the Apache License, Version 2.0 (the
11 | * "License"); you may not use this file except in compliance
12 | * with the License. You may obtain a copy of the License at
13 | *
14 | * http://www.apache.org/licenses/LICENSE-2.0
15 | *
16 | * Unless required by applicable law or agreed to in writing,
17 | * software distributed under the License is distributed on an
18 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19 | * KIND, either express or implied. See the License for the
20 | * specific language governing permissions and limitations
21 | * under the License.
22 | */
23 |
24 | package org.symphonyoss.s2.canon.example.presence;
25 |
26 | import java.io.IOException;
27 |
28 | import org.apache.http.impl.client.BasicCookieStore;
29 | import org.apache.http.impl.client.CloseableHttpClient;
30 | import org.apache.http.impl.client.HttpClients;
31 | import org.slf4j.Logger;
32 | import org.slf4j.LoggerFactory;
33 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresenceInfo;
34 | import org.symphonyoss.s2.canon.example.presence.canon.PresenceHttpModelClient;
35 | import org.symphonyoss.s2.canon.example.presence.canon.PresenceModel;
36 | import org.symphonyoss.s2.canon.example.presence.canon.PresenceStatus;
37 | import org.symphonyoss.s2.canon.example.presence.canon.UserId;
38 | import org.symphonyoss.s2.canon.example.presence.canon.UserPresenceInfo;
39 | import org.symphonyoss.s2.canon.example.presence.canon.UsersUserIdPutHttpRequest;
40 | import org.symphonyoss.s2.canon.example.presence.facade.PresenceJwtGenerator;
41 | import org.symphonyoss.s2.canon.runtime.IModelRegistry;
42 | import org.symphonyoss.s2.canon.runtime.ModelRegistry;
43 |
44 | /**
45 | * Create user 4 from hard coded values using the REST endpoint.
46 | *
47 | * @author Bruce Skingle
48 | *
49 | */
50 | public class PutUsers4
51 | {
52 | private static final Logger log_ = LoggerFactory.getLogger(PutUsers4.class);
53 |
54 | /**
55 | * Main.
56 | *
57 | * @param argv Command line args - ignored.
58 | *
59 | * @throws Exception If something goes wrong. This is just an example.
60 | */
61 | public static void main(String[] argv) throws Exception
62 | {
63 | IModelRegistry registry = new ModelRegistry().withFactories(PresenceModel.FACTORIES);
64 | PresenceHttpModelClient client = new PresenceHttpModelClient(registry, PresenceConstants.SERVER_URL, null, new PresenceJwtGenerator());
65 |
66 | IUserPresenceInfo japiPayload = new UserPresenceInfo.Builder()
67 | .withStatus(PresenceStatus.DoNotDisturb)
68 | .withText("I am on the phone")
69 | .build();
70 |
71 | UsersUserIdPutHttpRequest request = client.newUsersUserIdPutHttpRequestBuilder()
72 | .withUserId(UserId.newBuilder().build(4L))
73 | .withCanonPayload(japiPayload)
74 | .build();
75 |
76 | BasicCookieStore cookieStore = new BasicCookieStore();
77 | CloseableHttpClient httpclient = HttpClients.custom()
78 | .setDefaultCookieStore(cookieStore)
79 | .build();
80 | try {
81 | request.execute(httpclient);
82 |
83 | System.err.printf("Done\n");
84 | }
85 | finally
86 | {
87 | try
88 | {
89 | httpclient.close();
90 | }
91 | catch (IOException e)
92 | {
93 | log_.error("Unable to close httpClient", e);
94 | }
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/presence-client/src/main/java/org/symphonyoss/s2/canon/example/presence/GetUsers.java:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | *
4 | * Copyright 2018 Symphony Communication Services, LLC.
5 | *
6 | * Licensed to The Symphony Software Foundation (SSF) under one
7 | * or more contributor license agreements. See the NOTICE file
8 | * distributed with this work for additional information
9 | * regarding copyright ownership. The ASF licenses this file
10 | * to you under the Apache License, Version 2.0 (the
11 | * "License"); you may not use this file except in compliance
12 | * with the License. You may obtain a copy of the License at
13 | *
14 | * http://www.apache.org/licenses/LICENSE-2.0
15 | *
16 | * Unless required by applicable law or agreed to in writing,
17 | * software distributed under the License is distributed on an
18 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19 | * KIND, either express or implied. See the License for the
20 | * specific language governing permissions and limitations
21 | * under the License.
22 | */
23 |
24 | package org.symphonyoss.s2.canon.example.presence;
25 |
26 | import java.io.IOException;
27 |
28 | import org.apache.http.impl.client.BasicCookieStore;
29 | import org.apache.http.impl.client.CloseableHttpClient;
30 | import org.apache.http.impl.client.HttpClients;
31 | import org.slf4j.Logger;
32 | import org.slf4j.LoggerFactory;
33 | import org.symphonyoss.s2.canon.example.presence.canon.Cursor;
34 | import org.symphonyoss.s2.canon.example.presence.canon.CursorLimit;
35 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresence;
36 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresencePage;
37 | import org.symphonyoss.s2.canon.example.presence.canon.PresenceHttpModelClient;
38 | import org.symphonyoss.s2.canon.example.presence.canon.PresenceModel;
39 | import org.symphonyoss.s2.canon.example.presence.canon.UsersGetHttpRequest;
40 | import org.symphonyoss.s2.canon.example.presence.facade.PresenceJwtGenerator;
41 | import org.symphonyoss.s2.canon.runtime.IModelRegistry;
42 | import org.symphonyoss.s2.canon.runtime.ModelRegistry;
43 | import org.symphonyoss.s2.common.immutable.ImmutableByteArray;
44 |
45 | /**
46 | * Fetch all users by calling the REST endpoint.
47 | *
48 | * @author Bruce Skingle
49 | *
50 | */
51 | public class GetUsers
52 | {
53 | private static final Logger log_ = LoggerFactory.getLogger(GetUsers.class);
54 |
55 | /**
56 | * Main.
57 | *
58 | * @param argv Command line args - ignored.
59 | *
60 | * @throws Exception If something goes wrong. This is just an example.
61 | */
62 | public static void main(String[] argv) throws Exception
63 | {
64 | IModelRegistry registry = new ModelRegistry().withFactories(PresenceModel.FACTORIES);
65 | PresenceHttpModelClient client = new PresenceHttpModelClient(registry, PresenceConstants.SERVER_URL, null, new PresenceJwtGenerator());
66 |
67 | UsersGetHttpRequest request = client.newUsersGetHttpRequestBuilder()
68 | .withCursor(Cursor.newBuilder().build(ImmutableByteArray.newInstance("Hello".getBytes())))
69 | .withLimit(CursorLimit.newBuilder().build(20))
70 | .build();
71 |
72 | BasicCookieStore cookieStore = new BasicCookieStore();
73 | CloseableHttpClient httpclient = HttpClients.custom()
74 | .setDefaultCookieStore(cookieStore)
75 | .build();
76 | try {
77 | IUserPresencePage result = request.execute(httpclient);
78 |
79 | for(IUserPresence p : result.getData())
80 | {
81 | System.err.printf("%10d %-20s %s%n", p.getUserId().getValue(), p.getStatus(), p.getText());
82 | }
83 | }
84 | finally
85 | {
86 | try
87 | {
88 | httpclient.close();
89 | }
90 | catch (IOException e)
91 | {
92 | log_.error("Unable to close httpClient", e);
93 | }
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/presence-client/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
24 |
25 | 4.0.0
26 |
27 | org.symphonyoss.s2.canon.example
28 | canon-example
29 | 0.2.1-SNAPSHOT
30 |
31 | presence-client
32 |
33 |
34 |
35 |
36 |
37 | org.symphonyoss.s2.fugue
38 | fugue-core
39 |
40 |
41 | org.symphonyoss.s2.canon
42 | canon-template-java
43 |
44 |
45 |
46 | org.symphonyoss.s2.canon
47 | canon-runtime-java
48 |
49 |
50 | org.symphonyoss.s2.canon
51 | canon-jjwt
52 |
53 |
54 |
55 | ch.qos.logback
56 | logback-classic
57 |
58 |
59 |
60 | junit
61 | junit
62 | test
63 |
64 |
65 |
66 |
67 |
68 |
69 | org.symphonyoss.s2.canon
70 | canon-maven-plugin
71 | ${canon.version}
72 |
73 |
74 | generate-sources
75 |
76 | generate-sources
77 |
78 |
79 | src/main
80 |
81 |
82 |
83 | ${canon.template.groupid}
84 | ${canon.template.java}
85 | ${canon.template.version}
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | org.codehaus.mojo
95 | build-helper-maven-plugin
96 |
97 |
98 | add-source
99 | generate-sources
100 |
101 | add-source
102 |
103 |
104 |
105 | target/generated-sources/java
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/presence-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
24 |
25 | 4.0.0
26 |
27 | org.symphonyoss.s2.canon.example
28 | canon-example
29 | 0.2.1-SNAPSHOT
30 |
31 | presence-server
32 |
33 |
34 |
35 | ${project.groupId}
36 | presence-client
37 | ${project.version}
38 |
39 |
40 |
41 | org.symphonyoss.s2.canon
42 | canon-template-java
43 |
44 |
45 |
46 | org.symphonyoss.s2.canon
47 | canon-runtime-java
48 |
49 |
50 | org.symphonyoss.s2.canon
51 | canon-jjwt
52 |
53 |
54 |
55 | org.symphonyoss.s2.fugue
56 | fugue-core
57 |
58 |
59 |
60 | org.symphonyoss.s2.common
61 | S2-common-http
62 |
63 |
64 |
65 | ch.qos.logback
66 | logback-classic
67 |
68 |
69 |
70 | junit
71 | junit
72 | test
73 |
74 |
75 |
76 |
77 |
78 |
79 | io.fabric8
80 | docker-maven-plugin
81 |
82 |
83 |
84 | gcr.io/${gcp.project}/presence-server:${project.version}
85 | presence-server
86 |
87 | openjdk:latest
88 |
89 | artifact-with-dependencies
90 |
91 | java -cp "maven/*" com.symphony.s2.presence.PresenceServer
92 |
93 |
94 |
95 | 8080:8080
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 | docker:build
104 | package
105 |
106 | build
107 |
108 |
109 | true
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
--------------------------------------------------------------------------------
/presence-client/src/main/java/org/symphonyoss/s2/canon/example/presence/facade/Presence.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2018 Symphony Communication Services, LLC.
3 | *
4 | * Licensed to The Symphony Software Foundation (SSF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the
9 | * "License"); you may not use this file except in compliance
10 | * with the License. You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing,
15 | * software distributed under the License is distributed on an
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 | * KIND, either express or implied. See the License for the
18 | * specific language governing permissions and limitations
19 | * under the License.
20 | *
21 | *----------------------------------------------------------------------------------------------------
22 | * Proforma generated from
23 | * Template groupId org.symphonyoss.s2.japigen
24 | * artifactId canon-template-java
25 | * Template name proforma/java/Model/_.java.ftl
26 | * Template version 1.0
27 | * At 2018-01-14 16:40:50 GMT-08:00
28 | *----------------------------------------------------------------------------------------------------
29 | */
30 |
31 | package org.symphonyoss.s2.canon.example.presence.facade;
32 |
33 |
34 | import java.util.Collection;
35 | import java.util.TreeMap;
36 |
37 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresence;
38 | import org.symphonyoss.s2.canon.example.presence.canon.IUserPresenceInfo;
39 | import org.symphonyoss.s2.canon.example.presence.canon.PresenceStatus;
40 | import org.symphonyoss.s2.canon.example.presence.canon.UserId;
41 | import org.symphonyoss.s2.canon.example.presence.canon.UserPresence;
42 | import org.symphonyoss.s2.canon.example.presence.canon.UserPresenceEntity.Builder;
43 | import org.symphonyoss.s2.canon.runtime.exception.ServerErrorException;
44 | import org.symphonyoss.s2.fugue.IFugueComponent;
45 |
46 | public class Presence implements IPresence, IFugueComponent
47 | {
48 | private TreeMap presenceMap_ = new TreeMap<>();
49 |
50 | @Override
51 | public synchronized Collection getAllUsers()
52 | {
53 | return presenceMap_.values();
54 | }
55 |
56 | @Override
57 | public synchronized IUserPresence getUser(UserId userId)
58 | {
59 | return presenceMap_.get(userId);
60 | }
61 |
62 | @Override
63 | public synchronized void setUser(UserId userId, IUserPresenceInfo userPresenceInfo) throws ServerErrorException
64 | {
65 | presenceMap_.put(userId, new UserPresence.Builder()
66 | .withUserId(userId)
67 | .withStatus(userPresenceInfo.getStatus())
68 | .withText(userPresenceInfo.getText())
69 | .build());
70 | }
71 |
72 | @Override
73 | public void start()
74 | {
75 | /* Load presence data for known users */
76 |
77 | Builder presenceBuilder = new UserPresence.Builder();
78 | UserId userId;
79 |
80 | userId = UserId.newBuilder().build((long) 1);
81 |
82 | presenceBuilder.withUserId(userId);
83 | presenceBuilder.withStatus(PresenceStatus.Available);
84 | presenceBuilder.withText("I'm Free!");
85 |
86 | presenceMap_.put(userId, presenceBuilder.build());
87 |
88 | userId = UserId.newBuilder().build((long) 2);
89 |
90 | presenceBuilder.withUserId(userId);
91 | presenceBuilder.withStatus(PresenceStatus.Available);
92 | presenceBuilder.withText("Talk to me!");
93 |
94 | presenceMap_.put(userId, presenceBuilder.build());
95 |
96 |
97 | userId = UserId.newBuilder().build((long) 3);
98 |
99 | presenceBuilder.withUserId(userId);
100 | presenceBuilder.withStatus(PresenceStatus.Busy);
101 | presenceBuilder.withText("");
102 |
103 | presenceMap_.put(userId, presenceBuilder.build());
104 | }
105 |
106 | @Override
107 | public void stop()
108 | {
109 | }
110 | }
111 | /*----------------------------------------------------------------------------------------------------
112 | * End of template proforma/java/Model/_.java.ftl
113 | * End of code generation
114 | *------------------------------------------------------------------------------------------------- */
--------------------------------------------------------------------------------
/presence-client/src/main/canon/presence.json:
--------------------------------------------------------------------------------
1 | {
2 | "canon": "0.0.1",
3 | "info": {
4 | "title": "Japigen Simple RPC Test Case",
5 | "license": {
6 | "name": "Apache2"
7 | }
8 | },
9 | "id": "org.symphonyoss.s2.canon.example.presence",
10 | "version": "0.1",
11 | "basePath": "/presence/v2",
12 | "model": {
13 | "javaGenPackage": "org.symphonyoss.s2.canon.example.presence.canon",
14 | "javaFacadePackage": "org.symphonyoss.s2.canon.example.presence.facade"
15 | },
16 | "methods": {
17 | "/users": {
18 | "description": "Fetch all users' presence.",
19 | "parameterSets": [
20 | "#/components/parameterSets/pagination"
21 | ],
22 | "get": {
23 | "response": {
24 | "schema": {
25 | "$ref": "#/components/schemas/UserPresencePage"
26 | }
27 | }
28 | },
29 | "put": {
30 | "description": "A weird no payload and no response mehod."
31 | }
32 | },
33 | "/users/{userId}": {
34 | "description": "Manipulate a single user's presence.",
35 | "parameters": {
36 | "userId": {
37 | "in": "path",
38 | "required": true,
39 | "schema": {
40 | "$ref": "#/components/schemas/UserId"
41 | }
42 | }
43 | },
44 | "get": {
45 | "description": "Fetch a single user's presence.",
46 | "response": {
47 | "required": false,
48 | "schema": {
49 | "$ref": "#/components/schemas/UserPresence"
50 | }
51 | }
52 | },
53 | "put": {
54 | "description": "Set a single user's presence.",
55 | "payload": {
56 | "required": true,
57 | "schema": {
58 | "$ref": "#/components/schemas/UserPresenceInfo"
59 | }
60 | }
61 | }
62 | },
63 | "/users/{userId}/test": {
64 | "description": "Manipulate a single user's presence.",
65 | "parameters": {
66 | "userId": {
67 | "in": "path",
68 | "required": true,
69 | "schema": {
70 | "$ref": "#/components/schemas/UserId"
71 | }
72 | }
73 | },
74 | "get": {
75 | "description": "Fetch a single user's presence.",
76 | "response": {
77 | "schema": {
78 | "$ref": "#/components/schemas/UserPresence"
79 | }
80 | }
81 | }
82 | },
83 | "/users/update": {
84 | "description": "Manipulate a batch of users' presence.",
85 | "post": {
86 | "payload": {
87 | "required": true,
88 | "schema": {
89 | "$ref": "#/components/schemas/UserPresenceList"
90 | }
91 | }
92 | }
93 | },
94 | "/users/fetch": {
95 | "description": "Fetch a batch of users' presence.",
96 | "post": {
97 | "payload": {
98 | "required": true,
99 | "multiple": true,
100 | "schema": {
101 | "$ref": "#/components/schemas/UserId"
102 | }
103 | },
104 | "response": {
105 | "required": false,
106 | "multiple": true,
107 | "schema": {
108 | "$ref": "#/components/schemas/UserPresence"
109 | }
110 | }
111 | }
112 | }
113 | },
114 | "components": {
115 | "schemas": {
116 | "UserId": {
117 | "description": "A Symphony external user ID.",
118 | "type": "integer",
119 | "format": "int64",
120 | "minimum": 0
121 | },
122 | "Cursor": {
123 | "description": "An opaque token returned by the server to allow the next page to be requested.",
124 | "type": "string",
125 | "format": "byte"
126 | },
127 | "CursorLimit": {
128 | "description": "A cursor limit, the max number of records to return.",
129 | "type": "integer",
130 | "format": "int32",
131 | "minimum": 0,
132 | "maximum": 50
133 | },
134 | "CursorInfo": {
135 | "description": "Links to the next and prev pages.",
136 | "type": "object",
137 |
138 | "properties": {
139 | "previous": {
140 | "$ref": "#/components/schemas/Cursor"
141 | },
142 | "next": {
143 | "$ref": "#/components/schemas/Cursor"
144 | }
145 | }
146 | },
147 | "PresenceStatus": {
148 | "description": "A presence status.",
149 | "type": "string",
150 | "enum": [
151 | "Offline",
152 | "Available",
153 | "Busy",
154 | "DoNotDisturb",
155 | "OnThePhone"
156 | ]
157 | },
158 | "UserPresenceInfo": {
159 | "type": "object",
160 | "properties": {
161 | "status": {
162 | "$ref": "#/components/schemas/PresenceStatus"
163 | },
164 | "text": {
165 | "description": "A short message set by the user.",
166 | "type": "string"
167 | }
168 | }
169 | },
170 | "UserPresence": {
171 | "type": "object",
172 | "properties": {
173 | "userId": {
174 | "$ref": "#/components/schemas/UserId"
175 | },
176 | "status": {
177 | "$ref": "#/components/schemas/PresenceStatus"
178 | },
179 | "text": {
180 | "description": "A short message set by the user.",
181 | "type": "string"
182 | }
183 | }
184 | },
185 | "UserPresenceList": {
186 | "type": "object",
187 | "properties": {
188 | "data": {
189 | "description": "A list of user status records.",
190 | "type": "array",
191 | "x-canon-cardinality": "LIST",
192 | "items": {
193 | "$ref": "#/components/schemas/UserPresence"
194 | }
195 | }
196 | }
197 | },
198 | "UserPresencePage": {
199 | "type": "object",
200 | "properties": {
201 | "data": {
202 | "description": "A list of user status records.",
203 | "type": "array",
204 | "x-canon-cardinality": "LIST",
205 | "items": {
206 | "$ref": "#/components/schemas/UserPresence"
207 | }
208 | },
209 | "cursors": {
210 | "$ref": "#/components/schemas/CursorInfo"
211 | }
212 | }
213 | }
214 | },
215 | "parameterSets": {
216 | "pagination": {
217 | "cursor": {
218 | "description": "Cursor position",
219 | "in": "query",
220 | "required": false,
221 | "schema": {
222 | "$ref": "#/components/schemas/Cursor"
223 | }
224 | },
225 | "limit": {
226 | "description": "max records to return",
227 | "in": "query",
228 | "required": false,
229 | "schema": {
230 | "$ref": "#/components/schemas/CursorLimit"
231 | }
232 | }
233 | }
234 | }
235 | }
236 | }
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
15 |
16 | 4.0.0
17 |
18 |
19 | org.symphonyoss.s2
20 | S2-super-pom
21 | 0.2.4
22 |
23 |
24 | org.symphonyoss.s2.canon.example
25 | canon-example
26 | 0.2.1-SNAPSHOT
27 | JSON API Generation Tooling Example Application
28 | https://github.com/symphonyoss/canon-example
29 | pom
30 |
31 |
32 | presence-client
33 | presence-server
34 |
35 |
36 |
37 |
38 | Apache License, Version 2.0
39 | https://www.apache.org/licenses/LICENSE-2.0.txt
40 |
41 |
42 |
43 |
44 | scm:git:git://github.com/symphonyoss/canon-example.git
45 | scm:git:git@github.com:symphonyoss/canon-example.git
46 | https://github.com/symphonyoss/canon-example
47 | canon-example-0.0.1
48 |
49 |
50 |
51 |
52 | bruceskingle
53 | Bruce Skingle
54 | bruce.skingle@symphony.com
55 | http://github.com/bruceskingle
56 | Symphony Communication Services LLC
57 | http://symphony.com
58 |
59 | Chief Architect
60 |
61 |
62 |
63 |
64 |
65 | UTF-8
66 | 1.8
67 | 1.8
68 | 0.2.8
69 | 0.2.22
70 | org.symphonyoss.s2.canon
71 | canon-template-java
72 | ${canon.version}
73 |
74 | 0.2.53
75 | sym-dev-arch
76 |
77 |
78 |
79 |
80 | sonatype-oss-public
81 | https://oss.sonatype.org/content/groups/public/
82 |
83 | true
84 |
85 |
86 | true
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | org.symphonyoss.s2.common
95 | S2-common-core
96 | ${s2.common.version}
97 |
98 |
99 | org.symphonyoss.s2.common
100 | S2-common-http
101 | ${s2.common.version}
102 |
103 |
104 | org.symphonyoss.s2.common
105 | S2-common-dom
106 | ${s2.common.version}
107 |
108 |
109 | org.symphonyoss.s2.common
110 | S2-common-dom-jackson
111 | ${s2.common.version}
112 |
113 |
114 |
115 | org.symphonyoss.s2.canon
116 | canon-template-java
117 | ${canon.template.version}
118 |
119 |
120 |
121 | org.symphonyoss.s2.canon
122 | canon-runtime-java
123 | ${canon.version}
124 |
125 |
126 | org.symphonyoss.s2.canon
127 | canon-jjwt
128 | ${canon.version}
129 |
130 |
131 |
132 |
133 | org.symphonyoss.s2.fugue
134 | fugue-core
135 | ${fugue.version}
136 |
137 |
138 |
139 | com.google.code.findbugs
140 | jsr305
141 | 3.0.2
142 |
143 |
144 |
145 | ch.qos.logback
146 | logback-classic
147 | 1.0.13
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 | org.slf4j
157 | slf4j-api
158 |
159 |
160 |
161 |
162 |
163 |
164 | io.fabric8
165 | docker-maven-plugin
166 | 0.23.0
167 |
168 |
170 |
171 | org.eclipse.m2e
172 | lifecycle-mapping
173 | 1.0.0
174 |
175 |
176 |
177 |
178 |
179 |
180 | org.symphonyoss.s2.canon
181 |
182 |
183 | canon-maven-plugin
184 |
185 |
186 | [0.0.1-SNAPSHOT,)
187 |
188 |
189 |
190 | generate-sources
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # canon-example
2 | An example service based on japigen code generation
3 |
4 | In order to follow these instructions all the way through you will need access to a Google Cloud project, which your tech lead should be able to give you. If you do not have access to Google Cloud and wish to follow the local parts of these instructions then use the default name **sym-dev-arch** where a project name is required.
5 |
6 | Point your web browser to the [Google Cloud Platform Console](https://console.cloud.google.com), look near the top left corner of the page for the project selector, the project name shown in this screen shot is **sym-dev-arch**.
7 |
8 | 
9 |
10 | If the correct project is not listed then talk to your project lead to have yourself added to the project.
11 |
12 | If the name of the project is globally unique (as it is in the screen shot) then the project ID will be the same as the project name, if not then the project ID will have additional digits added to the name to make it unique. The Project ID is shown in the dashboard section of the GCP Console as shown in the screen shot above. Make a note of the Project ID.
13 |
14 | In order to build the sample application you will need a local Docker container. If you do not have a Docker container installed then you can download the Community Edition from [The Docker Store](https://www.docker.com/community-edition).
15 |
16 | ## Clone the Repo and Set Environment Variables
17 | Clone this repo into a convenient location:
18 |
19 | ```
20 | $ mkdir /tmp/git
21 | $ cd /tmp/git
22 | $ git clone https://github.com/SymphonyOSF/canon-example.git
23 | Cloning into 'canon-example'...
24 | remote: Counting objects: 118, done.
25 | remote: Compressing objects: 100% (57/57), done.
26 | remote: Total 118 (delta 45), reused 91 (delta 22), pack-reused 0
27 | Receiving objects: 100% (118/118), 33.69 KiB | 11.23 MiB/s, done.
28 | Resolving deltas: 100% (45/45), done.
29 | $ cd canon-example/
30 | $ ls
31 | LICENSE README.md S2-presence-client S2-presence-server pom.xml
32 | $
33 | ```
34 |
35 | Set the ID of the project you will be using as the variable **$PROJECT** with the following commands **N.B. replace the name "sym-dev-arch" with the ID of the project you will be using**
36 |
37 | ```
38 | $ export PROJECT=sym-dev-arch
39 | $ echo $PROJECT
40 | sym-dev-arch
41 | $
42 | ```
43 |
44 | Edit the project pom (the file pom.xml in the current directory), search for the definition of the
45 | property **gcp.project** and replace the name **sym-dev-arch** with the name of your Google Cloud project.
46 |
47 | ```
48 | sym-dev-arch
49 |
50 | ```
51 |
52 | Set the variable **$VERSION** to the current version for this project, you can do this with the following command:
53 |
54 | ```
55 | $ export VERSION=`mvn help:evaluate -Dexpression=project.version | grep -v "^[[]"`
56 | $ echo $VERSION
57 | 0.0.1-SNAPSHOT
58 | $
59 | ```
60 |
61 | ## Build and Run the PresenceServer locally
62 | Build the application by executing the command:
63 |
64 | ```
65 | $ mvn clean package
66 | [INFO] Scanning for projects...
67 | [INFO] ------------------------------------------------------------------------
68 | [INFO] Reactor Build Order:
69 | [INFO]
70 | [INFO] JAPIgen Example Application
71 | [INFO] S2-presence-client
72 | [INFO] S2-presence-server
73 | [INFO]
74 | [INFO] ------------------------------------------------------------------------
75 | [INFO] Building JAPIgen Example Application 0.0.1-SNAPSHOT
76 | [INFO] ------------------------------------------------------------------------
77 | ```
78 | _Many lines of output omitted_
79 |
80 | ```
81 | [INFO] --- maven-jar-plugin:3.0.1:jar (default-jar) @ S2-presence-server ---
82 | [INFO] Building jar: /Users/bruce/symphony/git-SymphonyOSF/canon-example/S2-presence-server/target/S2-presence-server-0.0.1-SNAPSHOT.jar
83 | [INFO]
84 | [INFO] --- docker-maven-plugin:0.23.0:build (docker:build) @ S2-presence-server ---
85 | [INFO] Copying files to /Users/bruce/symphony/git-SymphonyOSF/canon-example/S2-presence-server/target/docker/presence-server/0.0.1-SNAPSHOT/build/maven
86 | [INFO] Building tar: /Users/bruce/symphony/git-SymphonyOSF/canon-example/S2-presence-server/target/docker/presence-server/0.0.1-SNAPSHOT/tmp/docker-build.tar
87 | [INFO] DOCKER> [presence-server:0.0.1-SNAPSHOT] "presence-server": Created docker-build.tar in 557 milliseconds
88 | [INFO] DOCKER> [presence-server:0.0.1-SNAPSHOT] "presence-server": Built image sha256:00261
89 | [INFO] DOCKER> [presence-server:0.0.1-SNAPSHOT] "presence-server": Removed old image sha256:3a02b
90 | [INFO] ------------------------------------------------------------------------
91 | [INFO] Reactor Summary:
92 | [INFO]
93 | [INFO] JAPIgen Example Application ........................ SUCCESS [ 0.581 s]
94 | [INFO] S2-presence-client ................................. SUCCESS [ 3.568 s]
95 | [INFO] S2-presence-server ................................. SUCCESS [ 2.808 s]
96 | [INFO] ------------------------------------------------------------------------
97 | [INFO] BUILD SUCCESS
98 | [INFO] ------------------------------------------------------------------------
99 | [INFO] Total time: 7.139 s
100 | [INFO] Finished at: 2018-01-23T13:48:50-08:00
101 | [INFO] Final Memory: 36M/754M
102 | [INFO] ------------------------------------------------------------------------
103 | $
104 | ```
105 |
106 | The build generates a docker image for the server process including all the dependencies. We can execute the process directly with the following command:
107 |
108 | ```
109 | $ java -cp "S2-presence-server/target/docker/gcr.io/$PROJECT/presence-server/$VERSION/build/maven/*" com.symphony.s2.presence.PresenceServer
110 |
111 | ```
112 |
113 | This starts a server which listens for HTTP requests on port 8080, you will see a large number of log messages on stdout. You can test the server from another terminal window with the following command:
114 |
115 | ```
116 | $ curl http://127.0.0.1:8080/presence/v2/users
117 | {"_type":"https://github.com/bruceskingle/canon/blob/master/canon-test/src/main/resources/test/presence.json#/components/schemas/UserPresencePage","data":[{"_type":"https://github.com/bruceskingle/canon/blob/master/canon-test/src/main/resources/test/presence.json#/components/schemas/UserPresence","status":"Available","text":"I'm Free!","userId":1},{"_type":"https://github.com/bruceskingle/canon/blob/master/canon-test/src/main/resources/test/presence.json#/components/schemas/UserPresence","status":"Available","text":"Talk to me!","userId":2},{"_type":"https://github.com/bruceskingle/canon/blob/master/canon-test/src/main/resources/test/presence.json#/components/schemas/UserPresence","status":"Busy","text":"","userId":3}]}
118 | $
119 | ```
120 |
121 | The GET /presence/v2/users method returns a list of the presence satus for all users in the system. The example implementation initializes its data set with three users, note that the data array in the response contains the status for users with userId 1, 2, and 3 and the response ends **"userId":3}]}**
122 |
123 | Kill the locally running server by typing Ctrl-C in the window where you started it.
124 |
125 | ## Deploy to Your Local Docker Container
126 | You can see what containers are running with the command
127 |
128 | ```
129 | $ docker ps
130 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
131 | $
132 | ```
133 |
134 | You can start a local copy of the application with the command:
135 |
136 | ```
137 | $ mvn docker:start
138 | [INFO] Scanning for projects...
139 | [INFO] ------------------------------------------------------------------------
140 | [INFO] Reactor Build Order:
141 | [INFO]
142 | [INFO] JAPIgen Example Application
143 | [INFO] S2-presence-client
144 | [INFO] S2-presence-server
145 | [INFO]
146 | [INFO] ------------------------------------------------------------------------
147 | [INFO] Building JAPIgen Example Application 0.0.1-SNAPSHOT
148 | [INFO] ------------------------------------------------------------------------
149 | [INFO]
150 | [INFO] --- docker-maven-plugin:0.23.0:start (default-cli) @ canon-example ---
151 | [INFO]
152 | [INFO] ------------------------------------------------------------------------
153 | [INFO] Building S2-presence-client 0.0.1-SNAPSHOT
154 | [INFO] ------------------------------------------------------------------------
155 | [INFO]
156 | [INFO] --- docker-maven-plugin:0.23.0:start (default-cli) @ S2-presence-client ---
157 | [INFO]
158 | [INFO] ------------------------------------------------------------------------
159 | [INFO] Building S2-presence-server 0.0.1-SNAPSHOT
160 | [INFO] ------------------------------------------------------------------------
161 | [INFO]
162 | [INFO] --- docker-maven-plugin:0.23.0:start (default-cli) @ S2-presence-server ---
163 | [INFO] DOCKER> [gcr.io/sym-dev-arch/presence-server:0.0.1-SNAPSHOT] "presence-server": Start container c38211433373
164 | [INFO] ------------------------------------------------------------------------
165 | [INFO] Reactor Summary:
166 | [INFO]
167 | [INFO] JAPIgen Example Application ........................ SUCCESS [ 0.939 s]
168 | [INFO] S2-presence-client ................................. SUCCESS [ 0.021 s]
169 | [INFO] S2-presence-server ................................. SUCCESS [ 0.628 s]
170 | [INFO] ------------------------------------------------------------------------
171 | [INFO] BUILD SUCCESS
172 | [INFO] ------------------------------------------------------------------------
173 | [INFO] Total time: 2.125 s
174 | [INFO] Finished at: 2018-01-23T15:39:54-08:00
175 | [INFO] Final Memory: 25M/411M
176 | [INFO] ------------------------------------------------------------------------
177 | $ docker ps
178 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
179 | c38211433373 gcr.io/sym-dev-arch/presence-server:0.0.1-SNAPSHOT "/bin/sh -c 'java -c…" 1 second ago Up 4 seconds 0.0.0.0:8080->8080/tcp epic_snyder
180 | $
181 | ```
182 |
183 | As you can see from the **docker ps** output, port 8080 in the container is mapped to the same port on the host machine, so you can use the same command as before to check that the server is running:
184 |
185 | ```
186 | $ curl http://127.0.0.1:8080/presence/v2/users
187 | {"_type":"https://github.com/bruceskingle/canon/blob/master/canon-test/src/main/resources/test/presence.json#/components/schemas/UserPresencePage","data":[{"_type":"https://github.com/bruceskingle/canon/blob/master/canon-test/src/main/resources/test/presence.json#/components/schemas/UserPresence","status":"Available","text":"I'm Free!","userId":1},{"_type":"https://github.com/bruceskingle/canon/blob/master/canon-test/src/main/resources/test/presence.json#/components/schemas/UserPresence","status":"Available","text":"Talk to me!","userId":2},{"_type":"https://github.com/bruceskingle/canon/blob/master/canon-test/src/main/resources/test/presence.json#/components/schemas/UserPresence","status":"Busy","text":"","userId":3}]}
188 | $
189 | ```
190 |
191 | To stop the container you can use the command:
192 |
193 | ```
194 | $ mvn docker:stop
195 | [INFO] Scanning for projects...
196 | [INFO] ------------------------------------------------------------------------
197 | [INFO] Reactor Build Order:
198 | [INFO]
199 | [INFO] JAPIgen Example Application
200 | [INFO] S2-presence-client
201 | [INFO] S2-presence-server
202 | [INFO]
203 | [INFO] ------------------------------------------------------------------------
204 | [INFO] Building JAPIgen Example Application 0.0.1-SNAPSHOT
205 | [INFO] ------------------------------------------------------------------------
206 | [INFO]
207 | [INFO] --- docker-maven-plugin:0.23.0:stop (default-cli) @ canon-example ---
208 | [INFO]
209 | [INFO] ------------------------------------------------------------------------
210 | [INFO] Building S2-presence-client 0.0.1-SNAPSHOT
211 | [INFO] ------------------------------------------------------------------------
212 | [INFO]
213 | [INFO] --- docker-maven-plugin:0.23.0:stop (default-cli) @ S2-presence-client ---
214 | [INFO]
215 | [INFO] ------------------------------------------------------------------------
216 | [INFO] Building S2-presence-server 0.0.1-SNAPSHOT
217 | [INFO] ------------------------------------------------------------------------
218 | [INFO]
219 | [INFO] --- docker-maven-plugin:0.23.0:stop (default-cli) @ S2-presence-server ---
220 | [INFO] DOCKER> [gcr.io/sym-dev-arch/presence-server:0.0.1-SNAPSHOT] "presence-server": Stop and removed container c38211433373 after 0 ms
221 | [INFO] ------------------------------------------------------------------------
222 | [INFO] Reactor Summary:
223 | [INFO]
224 | [INFO] JAPIgen Example Application ........................ SUCCESS [ 0.936 s]
225 | [INFO] S2-presence-client ................................. SUCCESS [ 0.019 s]
226 | [INFO] S2-presence-server ................................. SUCCESS [ 10.615 s]
227 | [INFO] ------------------------------------------------------------------------
228 | [INFO] BUILD SUCCESS
229 | [INFO] ------------------------------------------------------------------------
230 | [INFO] Total time: 12.088 s
231 | [INFO] Finished at: 2018-01-23T15:45:16-08:00
232 | [INFO] Final Memory: 25M/410M
233 | [INFO] ------------------------------------------------------------------------
234 | $
235 |
236 | ```
237 |
238 | If you re-run docker ps you can confirm that the container was terminated:
239 |
240 | ```
241 | $ docker ps
242 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
243 | $
244 | ```
245 |
246 | ## Setup Your Google Cloud Development Environment
247 | You need to be given access to the Google Project for your service, and to install the Google SDK.
248 |
249 |
250 | If you do not already have it installed, download the gcloud SDK from [https://cloud.google.com/sdk/downloads](https://cloud.google.com/sdk/downloads)
251 |
252 | Next install **kubectl** (it is safe to execute this command if it is already installed) and set values for various configuration parameters:
253 |
254 | ```
255 | $ gcloud components install kubectl
256 |
257 | All components are up to date.
258 | $ gcloud config set project $PROJECT
259 | Updated property [core/project].
260 | $ gcloud config set compute/region us-central1
261 | Updated property [compute/region].
262 | $ gcloud config set compute/zone us-central1-b
263 | Updated property [compute/zone].
264 | $ gcloud config list
265 | [compute]
266 | region = us-central1
267 | zone = us-central1-b
268 | [core]
269 | account = your.name@your.domain
270 | disable_usage_reporting = True
271 | project = sym-dev-arch
272 |
273 | Your active configuration is: [default]
274 | $
275 |
276 | ```
277 |
278 | ## Setup A Google Cloud Kubernetes Cluster
279 | This would normally be done once, by the tech lead, for any given service.
280 |
281 | Choose a name for the cluster and set it as $CLUSTER and then create a cluster with the following commands:
282 |
283 | ```
284 | $ export CLUSTER=your-cluster-name
285 | $ echo $CLUSTER
286 | your-cluster-name
287 | $ gcloud container clusters create $CLUSTER
288 | Creating cluster your-cluster-name.../
289 | $
290 | ```
291 |
292 | This process may take several minutes. Once it completes, verify that you have connectivity to the cluster as follows:
293 |
294 | ```
295 | $ gcloud container clusters list
296 | NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS
297 | your-cluster-name us-central1-b 1.7.11-gke.1 130.211.131.169 n1-standard-1 1.7.11-gke.1 3 RUNNING
298 | $ gcloud container clusters get-credentials $CLUSTER
299 | Fetching cluster endpoint and auth data.
300 | kubeconfig entry generated for your-cluster-name.
301 | $ kubectl get services
302 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
303 | kubernetes ClusterIP 10.31.240.1 443/TCP 14h
304 | $
305 | ```
306 |
307 | Also check that you can see the cluster in the Google Cloud Console, select **Kubernetes Engine** in the left nav:
308 |
309 | 
310 |
311 | and then you should see the cluster, like this:
312 |
313 | 
314 |
315 |
316 | You can see the generated docker image in your local docker registry by executing the command:
317 |
318 | ```
319 | $ docker images
320 | REPOSITORY TAG IMAGE ID CREATED SIZE
321 | gcr.io/sym-dev-arch/presence-server 0.0.1-SNAPSHOT fddefc59a7f5 19 minutes ago 753MB
322 | $
323 | ```
324 |
325 | We now need to push this image to the Docker registry in your Google Project:
326 |
327 | ```
328 | $ gcloud docker -- push gcr.io/$PROJECT/presence-server:$VERSION
329 | The push refers to repository [gcr.io/sym-dev-arch/presence-server]
330 | bb4a67556d99: Pushed
331 | 875b1eafb4d0: Layer already exists
332 | 7ce1a454660d: Layer already exists
333 | d3b195003fcc: Layer already exists
334 | 92bd1433d7c5: Layer already exists
335 | f0ed7f14cbd1: Layer already exists
336 | b31411566900: Layer already exists
337 | 06f4de5fefea: Layer already exists
338 | 851f3e348c69: Layer already exists
339 | e27a10675c56: Layer already exists
340 | 0.0.1-SNAPSHOT: digest: sha256:d91bfe8c5a1a8d83b62dc1d7e6182ef319fc82798268834f3a4aa12b65b3fcfa size: 2423
341 | $
342 |
343 | ```
344 |
345 | The image is visible in the **Container Registry** section of the GCP Console:
346 |
347 | 
348 |
349 | Now we can deploy the image:
350 |
351 | ```
352 | $ kubectl run presence-server --image gcr.io/$PROJECT/presence-server:$VERSION --port 8080
353 | deployment "presence-server" created
354 | $
355 | ```
356 |
357 | We can find the ID of the running instance (known as a pod in Kubernetes) like this:
358 |
359 | ```
360 | $ kubectl get pods
361 | NAME READY STATUS RESTARTS AGE
362 | presence-server-775063857-mbqw8 1/1 Running 0 39s
363 | ```
364 |
365 | ...and see the log output for a given pod like this:
366 |
367 | ```
368 | $ kubectl logs presence-server-775063857-mbqw8
369 | 00:14:38.677 [main] DEBUG org.eclipse.jetty.util.log - Logging to Logger[org.eclipse.jetty.util.log] via org.eclipse.jetty.util.log.Slf4jLog
370 | ```
371 | _Many lines of log output omitted_
372 |
373 | ```
374 | 00:14:39.292 [main] INFO o.e.jetty.server.AbstractConnector - Started ServerConnector@694e1548{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
375 | 00:14:39.298 [main] DEBUG o.e.j.u.component.AbstractLifeCycle - STARTED @1264ms ServerConnector@694e1548{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
376 | 00:14:39.299 [main] INFO org.eclipse.jetty.server.Server - Started @1264ms
377 | 00:14:39.299 [main] DEBUG o.e.j.u.component.AbstractLifeCycle - STARTED @1265ms org.eclipse.jetty.server.Server@7791a895[9.4.8.v20171121]
378 | ```
379 |
380 | As we can see, the servers embedded Jetty server is listening on port 8080.
381 | Now we can expose the servers service port with the following command:
382 |
383 | ```
384 | $ kubectl expose deployment presence-server --target-port=8080 --type=LoadBalancer
385 | service "presence-server" exposed
386 | $ kubectl get services
387 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
388 | kubernetes ClusterIP 10.31.240.1 443/TCP 21h
389 | presence-server LoadBalancer 10.31.255.10 8080:31018/TCP 2s
390 | ```
391 |
392 | It takes some time for the load balancer to be configured, so if you don't see an EXTERNAL-IP address first time you run the get services command then just wait a minute and try again.
393 |
394 | ```
395 | $ kubectl get services
396 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
397 | kubernetes ClusterIP 10.31.240.1 443/TCP 21h
398 | presence-server LoadBalancer 10.31.250.123 35.188.28.109 8080:31825/TCP 1m
399 | $
400 | ```
401 |
402 |
403 | The external IP address is shown on the last line of output above (**35.188.28.109** in this case), and we can use the same curl command to check that the server is actually working:
404 |
405 | ```
406 | $ curl http://35.188.28.109:8080/presence/v2/users
407 | {"_type":"https://github.com/bruceskingle/canon/blob/master/canon-test/src/main/resources/test/presence.json#/components/schemas/UserPresencePage","data":[{"_type":"https://github.com/bruceskingle/canon/blob/master/canon-test/src/main/resources/test/presence.json#/components/schemas/UserPresence","status":"Available","text":"I'm Free!","userId":1},{"_type":"https://github.com/bruceskingle/canon/blob/master/canon-test/src/main/resources/test/presence.json#/components/schemas/UserPresence","status":"Available","text":"Talk to me!","userId":2},{"_type":"https://github.com/bruceskingle/canon/blob/master/canon-test/src/main/resources/test/presence.json#/components/schemas/UserPresence","status":"Busy","text":"","userId":3}]}
408 | $
409 | ```
410 |
411 | Note again that the response ends the response ends **"userId":3}]}**.
412 |
413 | ## Make a code change
414 | Now we will make a change to the application and re-deploy. Find the class UsersAsyncHandler.java. The method handleGet is where the business logic of the GET request we are making is implemented and the line which beging **builder.withData(** is where the presence status of all known users is added to the response.
415 |
416 | Comment out that line by inserting two slashes at the start of the line:
417 |
418 | ```
419 | @Override
420 | public void handleGet(IConsumer _consumer, Cursor cursor, CursorLimit limit) throws JapiException
421 | {
422 | Builder builder = getModel().getUserPresencePageFactory().newBuilder();
423 |
424 | //builder.withData(new ArrayList(getModel().getAllUsers()));
425 |
426 | _consumer.consume(builder.build());
427 | _consumer.close();
428 | }
429 | ```
430 |
431 | Rebuild the application by executing the command:
432 |
433 | ```
434 | $ mvn clean package
435 | ```
436 |
437 | When the build is complete, push the updated Docker image:
438 |
439 | ```
440 | $ gcloud docker -- push gcr.io/$PROJECT/presence-server:$VERSION
441 | The push refers to repository [gcr.io/sym-dev-arch/presence-server]
442 | e700695e60f6: Pushed
443 | 875b1eafb4d0: Layer already exists
444 | 7ce1a454660d: Layer already exists
445 | d3b195003fcc: Layer already exists
446 | 92bd1433d7c5: Layer already exists
447 | f0ed7f14cbd1: Layer already exists
448 | b31411566900: Layer already exists
449 | 06f4de5fefea: Layer already exists
450 | 851f3e348c69: Layer already exists
451 | e27a10675c56: Layer already exists
452 | 0.0.1-SNAPSHOT: digest: sha256:de009b313484913b60a588a3f76b385e6d9abf3532105466547471063ee183e2 size: 2423
453 |
454 | ```
455 |
456 | The delete the currently running pod, which will force a re-deploy:
457 |
458 | ```
459 | $ kubectl get pods
460 | NAME READY STATUS RESTARTS AGE
461 | presence-server-775063857-3gk4b 1/1 Running 0 10m
462 | $ kubectl delete pod presence-server-775063857-3gk4b
463 | pod "presence-server-775063857-3gk4b" deleted
464 | $
465 |
466 | ```
467 |
468 | An immediate get pods will show the old pod being terminated and a new one being created:
469 |
470 | ```
471 | $ kubectl get pods
472 | NAME READY STATUS RESTARTS AGE
473 | presence-server-775063857-2wn04 0/1 ContainerCreating 0 5s
474 | presence-server-775063857-3gk4b 1/1 Terminating 0 11m
475 | $
476 |
477 | ```
478 |
479 | Once the new pod has started, re-run the curl command:
480 |
481 | ```
482 |
483 | $ kubectl get pods
484 | NAME READY STATUS RESTARTS AGE
485 | presence-server-775063857-2wn04 1/1 Running 0 56s
486 | $ curl http://35.202.182.219:8080/presence/v2/users
487 | {"_type":"https://github.com/bruceskingle/canon/blob/master/canon-test/src/main/resources/test/presence.json#/components/schemas/UserPresencePage","data":[]}
488 | $
489 |
490 | ```
491 |
492 | Note that the response now contains no UserPresence objects and now ends ** "data":[]}**
493 |
494 |
495 |
--------------------------------------------------------------------------------