Giter Club home page Giter Club logo

struts2-conversation's People

Watchers

 avatar

struts2-conversation's Issues

NullPointerException when the http session is deserialized and expired

Version: 
--------
1.7.0

Description:
------------

I stop my Tomcat server: the http session is serialized.
I restart my Tomcat server: the http session is deserialized AND expired.
Then the following exception is thrown:

java.lang.NullPointerException
    at com.google.code.rees.scope.util.monitor.ScheduledExecutorTimeoutMonitor.destroy(ScheduledExecutorTimeoutMonitor.java:105)
    at com.google.code.rees.scope.conversation.context.TimeoutConversationContextManager.destroy(TimeoutConversationContextManager.java:97)
    at com.google.code.rees.scope.conversation.context.ConversationCleanupListener.sessionDestroyed(ConversationCleanupListener.java:63)
    at org.apache.catalina.session.StandardSession.expire(StandardSession.java:720)
    at org.apache.catalina.session.StandardSession.isValid(StandardSession.java:587)
    at org.apache.catalina.connector.Request.doGetSession(Request.java:2419)
    at org.apache.catalina.connector.Request.getSessionInternal(Request.java:2339)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:431)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:291)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:662)

Original issue reported on code.google.com by [email protected] on 25 Feb 2013 at 3:56

The binding of a collection of a bean annotated with @ConversationField does not work.

Version: 
--------
1.7.0

Description:
------------

All the properties of my model (annotated with @ConversationField)  are 
correctly updated, except the properties of type 'collection'.

Example:
--------

<sc:form action="myConversationAction">
   <s:textfield name="myBean.myIntegerList[0]" />
   <s:textfield name="myBean.myIntegerList[1]" />
</sc:form>

Workarounds:
------------

Workaround #1:

<sc:form action="myConversationAction">
   <s:textfield name="myBean.myIntegerList" />
   <s:textfield name="myBean.myIntegerList" />
</sc:form>

This is the 'one way' fix: works to post data, but not when the page is 
redisplayed.

Workaround #2:

Add a list to your action, not annotated with @ConversationField.
Tell Struts2 to bind the fields to this list.
Once the action is executed, copy the content of the list to your model.

Original issue reported on code.google.com by [email protected] on 22 Feb 2013 at 4:26

Parent package is not defined: config-browser

What steps will reproduce the problem?
1. Whenenever I include struts2-conversation-config-browser-extension-1.7.4.jar 
in my classpath and 
<%@ taglib uri="/struts-conversation-tags" prefix="sc"%> in my jsp and
Use it afterwards <sc:form action="...">
2. I am getting "Parent package is not defined: config-browser"
My question: is it mandatory to use config-browser-extension for creating 
conversation aware submissions?

Versions used :
struts2-conversation-config-browser-extension-1.7.4.jar
struts2-conversation-scope-plugin-1.7.4.jar
struts2-core-2.3.16.3.jar

Original issue reported on code.google.com by [email protected] on 30 Oct 2014 at 2:31

ScheduledExecutorTimeoutMonitor prevents the webserver from stopping

What steps will reproduce the problem?
1. Start your webapp.
2. Launch a conversation.
3. Stop your webserver

What is the expected output? What do you see instead?
-> The webserver hangs / does not stop (Tomcat in my case)


What version of the product are you using? On what operating system?
-> struts2-conversation-scope-plugin 1.7.0


Please provide any additional information below.
-> It appears that ScheduledExecutorTimeoutMonitor.scheduler.shutdown() is 
never called.


Original issue reported on code.google.com by [email protected] on 11 Apr 2013 at 2:08

acceptableParameterName is calling multi times and it is not working correctly

---------------------------------------------------
Versions:
struts2.version 2.3.15.3
struts2-conversation-scope-plugin.version 1.7.4

---------------------------------------------------
What steps will reproduce the problem?

1- Open the sample application.
2- Change the RegistrationController to implement the ParameterNameAware
3- Add below method:
public boolean acceptableParameterName(String parameterName) {
                System.out.println(parameterName);
        return true;
    }

4- Open the struts.xml.
5- The params interceptor excludeParams needs to be change. (The 
acceptableParameterName will only be called when the parameter is excluded in 
by the interceptor.)

The struts.xml should be as below(Same as sample, just copy and paste 
defultStack and change the param as below:
<interceptor-ref name="params">
                    <param name="excludeParams">\w+((\.\w+)|(\[\d+\])|(\(\d+\))|(\['\w+'\])|(\('\w+'\)))*</param>
                </interceptor-ref>

The complete struts.xml (attached):

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>

    <!-- This is helpful for debugging but should be turned off for production 
        deployments for performance and security reasons -->
    <constant name="struts.devMode" value="true" />

    <!-- Tell Struts where to find our messages. Go here for more about message 
        bundles: http://struts.apache.org/2.x/docs/message-resource-files.html -->
    <constant name="struts.custom.i18n.resources" value="applicationResources" />

    <!-- Tell freemarker to cache its templates for better performance -->
    <constant name="struts.freemarker.templatesCache" value="true" />

    <!-- tell struts filter to ignore static content access -->
    <constant name="struts.action.excludePattern" value="/static/.*" />

    <!-- Needed to inspect class files properly on startup on WebLogic for some 
        versions <constant name="struts.convention.action.fileProtocols" value="jar,zip" 
        /> <constant name="struts.convention.action.includeJars" value=".*_wl_cls_gen.*" 
        /> Fortunately, even if not found on startup, the classes will be parsed 
        the first time its action are executed, its just nicer if its done up front. -->

    <!-- Set this to help the Conversation Plugin find actions on startup (the 
        default is 'Action', I just prefer 'Controller') -->
    <constant name="struts.convention.action.suffix" value="Controller" />

    <!-- These constants can be used to configure the Conversation Plugin -->
    <!-- see also: http://code.google.com/p/struts2-conversation/wiki/NestingConversations -->
    <!-- see also: http://code.google.com/p/struts2-conversation/wiki/UsageGuide#Memory_Management -->
    <constant name="conversation.package.nesting" value="false" />
    <constant name="conversation.monitoring.frequency" value="10000" />
    <constant name="conversation.idle.timeout" value="90000" />
    <constant name="conversation.max.instances" value="4" />
    <constant name="conversation.monitoring.thread.pool.size"
        value="4" />

    <bean type="org.byars.struts2.example.services.RegistrationService"
        class="org.byars.struts2.example.services.RegistrationServiceImpl" />

    <package name="registration" namespace="/registration"
        extends="struts-conversation-default">
        <interceptors>
            <interceptor-stack name="myStack">
            <interceptor-ref name="sessionField" />         
            <interceptor-ref name="conversation" />
                <interceptor-ref name="exception" />
                <interceptor-ref name="alias" />
                <interceptor-ref name="servletConfig" />
                <interceptor-ref name="i18n" />
                <interceptor-ref name="prepare" />
                <interceptor-ref name="chain" />
                <interceptor-ref name="debugging" />
                <interceptor-ref name="scopedModelDriven" />
                <interceptor-ref name="modelDriven" />
                <interceptor-ref name="fileUpload" />
                <interceptor-ref name="checkbox" />
                <interceptor-ref name="multiselect" />
                <interceptor-ref name="staticParams" />
                <interceptor-ref name="actionMappingParams" />
                <interceptor-ref name="params">
                    <param name="excludeParams">\w+((\.\w+)|(\[\d+\])|(\(\d+\))|(\['\w+'\])|(\('\w+'\)))*</param>
                </interceptor-ref>
                <interceptor-ref name="conversionError" />
                <interceptor-ref name="validation">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
                <interceptor-ref name="workflow">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                </interceptor-ref>
            </interceptor-stack>
        </interceptors>
            <default-interceptor-ref name="myStack" />

        <global-results>
            <!-- This is the result if a user submits a request for an expired or 
                dead conversation -->
            <result name="struts.conversation.invalid.id" type="redirectAction">
                <param name="actionName">begin</param>
                <!-- This makes use of the ConversationErrorAware interface to pass error 
                    message for a redirect -->
                <param name="conversationError">${conversationError}</param>
            </result>
        </global-results>

        <action name="*"
            class="org.byars.struts2.example.actions.RegistrationController"
            method="{1}">
            <!-- best to put jsps in web-inf so that they must be accessed only thru 
                Struts2 filter -->
            <result name="success">/WEB-INF/content/registration/{1}-success.jsp
            </result>
        </action>

    </package>

</struts>


---------------------------------------
What happens:

The output of print as below, as you can see the parameters are duplicated. (in 
my real application each parameter is printed tree times!)

contact.addressLine1
contact.addressLine2
contact.city
contact.firstName
contact.lastName
contact.postalCode
contact.state
contact
contact
addressLine1
addressLine1
contact
contact
addressLine2
addressLine2
contact
contact
city
city
contact
contact
firstName
firstName
contact
contact
lastName
lastName
contact
contact
postalCode
postalCode
contact
contact
state
state
It should be:
contact.addressLine1
contact.addressLine2
contact.city
contact.firstName
contact.lastName
contact.postalCode
contact.state

-------------------------
The bad news is that it is not working at all
Consider you only want the address line 1 to be acceptable:
public boolean acceptableParameterName(String parameterName) {
        if (parameterName.equals("contact.addressLine1"))
            return true;
        else if (parameterName.equals("contact"))
            return true;

        return false;
}
This will not work and the addressLine1 is never accepted.

Original issue reported on code.google.com by [email protected] on 18 Nov 2013 at 7:34

Attachments:

Custom implementation of ConversationProcecessor

Hi,

thank you for this plugin which really suits my needs. Just a question:
Is there an easy away to replace the implementation of the 
ConversationProcessor?
I've tried to place the following configuration to my struts.xml:

<bean name="struts.conversation.conversationProcessor"
      type="com.google.code.rees.scope.conversation.processing.ConversationProcessor"
      class="com.google.code.rees.scope.conversation.processing.DefaultInjectionConversationProcessor" />

But it didn't work because the redefinition of a bean is not allowed.
The reason why I want to modify the default implementation:
- if I call a action method and there is no conversation yet then it should 
automatically start a new conversation
- with this new conversation a custom field should be initialized (every action 
class has this field)

This behaviour means that I don't need to define/annotate a 
"beginConversation"-method.

Thanks in advance.

Original issue reported on code.google.com by [email protected] on 5 Mar 2013 at 6:25

Configuration question (struts.mapper.alwaysSelectFullNamespace)

Hi,

it's been a while since I've posted an issue :) This time I've got a simple 
question.

I've discovered in the struts-plugin.xml of this conversation plugin that the 
following configuration is set to "true".

<constant name="struts.mapper.alwaysSelectFullNamespace" value="true" />

But the default value in Struts 2 is "false". Now, I have a project which needs 
this variable set to "false" (otherwise the action links wouldn't work anymore).

My question:
Are there any problems with the conversation plugin if I set this to "false" in 
the struts.xml? If there no problems then I would suggest to remove this from 
the struts-plugin.xml.





Original issue reported on code.google.com by [email protected] on 19 Aug 2013 at 6:52

Conversation IDs are not excluded from further parameter processing

Currently, the param interceptor tries to evaluate the conversation IDs against 
the value stack.  In dev mode, this evaluation causes considerable logging of 
exceptions and warnings.

This IDs should be removed by the conversation interceptor before reaching the 
param interceptor in order to prevent any unnecessary processing and/or logging.


Original issue reported on code.google.com by [email protected] on 21 Mar 2013 at 12:45

Automatic creation of conversation

Hi,

I have another suggestion to improve your neat plugin.

In order to start a conversation I have to write a "begin"-Method. Therefore 
all my links on the html page have to point to this method. After calling this 
link I make a redirect to the intended method with the logic. The redirect is 
neccessary because I want the possibility to refresh the site in the browser 
(instead of creating a new conversation).

Here's an example how I solved it now:

@ConversationController
public class ExampleAction extends MyBaseAction {

    private String number;

    @ConversationField
    private ExampleModel exampleModel;

    @BeginConversation
    public String startConversation() {
        exampleModel = new ExampleModel();
        return "refresh";
    }

    @ConversationAction
    public String doSomething() {
        //do something with the data
        return SUCCESS;
    }

    // ...
}

in my struts.xml:
<result type="conversationRedirectAction" name="refresh">
  <param name="namespace">...</param>
  <param name="actionName">...</param>
  <param name="method">doSomething</param>
  <param name="number">${number}</param>
</result>

That means, that a link

/example.action!startConversation?number=123

redirects to

/example.action!doSomething?number=123&example-action_conversation=0


As you can see, there is a lot of boilerplate configuration in the struts.xml.

It would be nice if I can do something like that:

@ConversationController
public class ExampleAction extends MyBaseAction {

    private String number;

    @ConversationField
    private ExampleModel exampleModel;

    @BeginConversationIfNotExist // just a name :)
    public String doSomething() {
        //do something with the data
        return SUCCESS;
    }

    @InitConversation // optional
    private initConversation()
    {
      // similar to the Preparable-Interface
      exampleModel = new ExampleModel();
    }

    // ...
}

When I try to access

/example.action!doSomething?number=123

then the ConversationInterceptor should see that there's no conversation id 
yet. Because of the annotation @BeginConversationIfNotExist it knows that a 
conversation is needed. The interceptor or processor calls the 
initConversation() method to initialize my conversation fields if needed. 
Afterwards it should send a redirect to the browser with all the parameters 
inclusive the new conversation id (it is important that the doSomething method 
isn't called):

/example.action!doSomething?number=123&example-action_conversation=0

This time the interceptor sees that there's a valid conversation id and the 
following process is as usual.

Benefits:
- no redirect configuration for the "begin"-Method is needed (if I want to 
allow a refresh on thesite)
- the link on the page remains the same (bookmarkable, no refactoring if 
conversation is not needed anymore)

My questions:
Do you think it's a good enhancement for conversation plugin?
If yes, do you think it can be implemented/introduced in the near future? 
Otherwise I would implement it myself because I want to ease the use of this 
plugin.

Original issue reported on code.google.com by [email protected] on 21 Mar 2013 at 10:00

The invalid conversation ID message incorrectly defaults to the conversation specific message key

The message that is retrieved for invlaid conversation IDs (which is then 
placed on the ValueStack and, if possible, set on the ConversationErrorAware 
setter) correctly tries first to retrieve a conversation-specific message using 
the format struts.conversation.invalid.id.${conversation.name}.  The problem is 
that, if no conversation-specific message is found, it should then try to find 
a message using the key "struts.conversation.invalid.id", but instead it sets 
the message to be the key itself instead of any of the message (so the error 
message will display to the user something like 
"struts.conversation.invalid.id.registration_conversation".

A fix has been committed to the trunk and will be a part of the next release.  
Sense this is not considered a show-stopper at this point, no immediate release 
is being made for this issue.

If anyone requires or desires a fix before this time, please provide feedback 
to that effect.

Projected fix version:  v1.8.0

Original issue reported on code.google.com by [email protected] on 29 Jun 2012 at 5:30

Field annotated with @ConversationField is not retaining value

What steps will reproduce the problem?
1. I have few fields annotated with @ConversationField in my 
@ConversationController class 
e.g. 
    @ConversationField
    private File wsdlFile;
    @ConversationField
    private String wsdlFileFileName;
        ...
2. Page navigation is first.jsp > second.jsp > finish.jsp
3. I can see values in second.jsp. But values are set to null in finish.jsp

What is the expected output? What do you see instead?
I anticipated the values to be retained for entire conversation.

What version of the product are you using? On what operating system?
struts2-conversation-scope-plugin-1.7.4.jar

Please provide any additional information below.

N/A

Original issue reported on code.google.com by [email protected] on 30 Oct 2014 at 2:07

DefaultConversationArbitrator doesn't determine all conversation methods correctly

Hello,

it's me again. I think there's a bug in the class DefaultConversationArbitrator 
of the current version (1.7.3).

The method getCandidateConversationMethods() doesn't seem to deliver all 
conversation method candidates as stated in the method name.

If the action class is NOT annotated with @ConversationController then this 
method only returns action methods which has the @ConversationAction 
annotation. Otherwise (i.e. action class IS annotated with 
@ConversationController) it returns all type of conversation methods (begin, 
intermediate, end).

The consequence is that the method processClass() in 
DefaultConversationConfigurationProvider doesn't find any "begin conversation" 
methods if the action doesn't have the @ConversationController annotation.

Please verify. Thank you.

Original issue reported on code.google.com by [email protected] on 13 Apr 2013 at 4:20

End conversation removes conversation id/name when catching exceptions but returning to INPUT on Struts2 framework

What steps will reproduce the problem?

// An example action
class MyAction extends ActionSupport {

  @ConversationField(conversations="convoA")
  private MyObject object;

  @BeginConversation(conversations="convoA")
  public String start() throws Exception {
    /* load MyObject from the database */
    return SUCCESS;
  }

  @EndConversation(conversations="convoA")
  public String stop() throws Exception {
    try {
      /* attempt to update MyObject */
      return SUCCESS;
    }
    catch(VersionMismatchException ex) {
      LOG.info("Record modified by another user.", ex);
      addActionError(ERROR_VERSION_MISMATCH);
      return INPUT;
    }
  }
}

What is the expected output? What do you see instead?

When the 'stop()' method is called and a VersionMismatchException is caught, 
the problem is that processConversation inside 
DefaultInjectionConversationProcessor branches to not add the conversation 
name/id to the view context when an end action is seen. 

I would prefer to see that @EndConversation perhaps be ammended either with 
configurable result codes or somehow split the logic so that the struts 
interceptor is capable of removing the name/id from the view context only if 
the invocation of the action perhaps returns INPUT or the result code matches a 
list of result codes from a new annotation specifically for struts?

The end result should be that if the method returns the user to INPUT because 
something failed, the conversation id/name shouldn't be thrown away just 
because the action invocation didn't throw an exception.

What version of the product are you using? On what operating system?
latest

Please provide any additional information below.


Original issue reported on code.google.com by [email protected] on 4 Apr 2014 at 1:42

Simple Example failed

What steps will reproduce the problem?
1. Set up and deploy this example:
http://struts2-conversation.googlecode.com/svn/trunk/examples/simple-conversatio
n-support-example/

2. After deploy: access .../registration/begin.action 

3. Click submit button on the screen

What is the expected output? What do you see instead?
Expect contact.action screen displayed with no errors.  But got stacktrace:

Messages: Class cannot be casted to array 

File: com/google/code/rees/scope/util/RequestContextUtil.java 
Line number: 29 


--------------------------------------------------------------------------------

Stacktraces
java.lang.ClassCastException: Class cannot be casted to array 
    com.google.code.rees.scope.util.RequestContextUtil.getRequestContext(RequestContextUtil.java:29)
    com.google.code.rees.scope.struts2.StrutsConversationAdapter.getRequestContext(StrutsConversationAdapter.java:66)
    com.google.code.rees.scope.conversation.SimpleConversationManager.processConversation(SimpleConversationManager.java:56)
    com.google.code.rees.scope.conversation.SimpleConversationManager.processConversations(SimpleConversationManager.java:44)
    com.google.code.rees.scope.struts2.ConversationInterceptor.doIntercept(ConversationInterceptor.java:91)
    com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
    com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
    org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:52)
    org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:498)
    org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
    org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)
    weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
    gov.usdoj.ojp.bvp.servlet.LoginFilter.doFilter(LoginFilter.java:114)
    weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
    gov.usdoj.ojp.bvp.servlet.CrossScriptingFilter.doFilter(CrossScriptingFilter.java:37)
    weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
    weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3592)
    weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
    weblogic.security.service.SecurityManager.runAs(SecurityManager.java:121)
    weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2202)
    weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2108)
    weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1432)
    weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
    weblogic.work.ExecuteThread.run(ExecuteThread.java:173)


What version of the product are you using? On what operating system?
struts2-conversation-scope-plugin-1.4.0.jar (I think same error with
1.4.1)



Original issue reported on code.google.com by [email protected] on 25 Apr 2012 at 8:22

Struts 2 Conversation Scope Plugin with no @EndConversation

Consider below example, which I think is a very common sample of step forms.
I have a three step form which want to transfer money from an account to other :

    First  page gets user source account
    Second page shows source account and gets destination account and the amount
    Last   page shows a confirmation which mention source account + destination account + amount

As you can see I need the model information in the last page too. So I use 
`@BeginConversation` for first action and `@ConversationAction` for second and 
last page.

The question is none of my actions are annotated with `@EndConversation`. Is it 
OK?!
Will the model resides in memory or it will be auto cleaned? I could not find 
when it is auto cleaned.

Original issue reported on code.google.com by [email protected] on 8 Nov 2013 at 9:04

@ConversationField Security Hole

I am annotating two field with @ConversationField as below:

@ConversationField
private UserInput userInput;

@ConversationField
private CriticalInfo criticalInfo;

The criticalInfo should not been accessible by user and not automaticly set, so 
it does not have any getter (The getCriticalInfo() is not defined). It is 
annotated so the plugin saves it in memory during conversation.

The strange thing is that user can change the criticalInfo by submits a form 
like below

<input type="text" name="CriticalInfo.amount">

If you remove the @ConversationField this will not happen and user can not 
tweak the CriticalInfo bean from the client by passing the property name and 
value! 


Original issue reported on code.google.com by [email protected] on 8 Nov 2013 at 8:30

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.