The latest news for CDI 4.x can be found in the GitHub pages
The main branch contains the work-in-progress on CDI.next specification (5.0)
Check out the cdi-spec.org for more info on CDI 2.0 and CDI 1.2
CDI specification
License: Apache License 2.0
The latest news for CDI 4.x can be found in the GitHub pages
The main branch contains the work-in-progress on CDI.next specification (5.0)
Check out the cdi-spec.org for more info on CDI 2.0 and CDI 1.2
There are many open issues under the legacy CDI issues tracker at issues.redhat.com. They can be seen by browsing the following:
https://issues.redhat.com/projects/CDI/issues/CDI-726?filter=allopenissues
We need to triage this list and link to those that should be tracked going forward.
Blog post you should read - www.cdi-spec.org/news/2020/09/15/CDI_Lite_extension/
PR with API proposal - #451
For hands-on playing with API, use this fork - https://github.com/Ladicek/quarkus-fork/tree/experiment-cdi-lite-ext
This is a proposal on how Build Compatible Extensions ( e.g. CDI Lite extensions) could look like. Various discussions in the past showed that regardless of what would CDI Lite look like, it will need some form of extensions because the existing ones are not suitable for build-time and extension are an important factor for integration of various frameworks.
This issue and the PR linked to it (#451) come with a WIP proposition that we would like to gather feedback on.
There is a blog post on CDI website that you should check out. It goes deeper into what Build Compatible Extensions Proposal is and how it works. Please do give it a read.
This proposal does not aim to cover what CDI Lite should/shouldn't contain and focuses solely on how could the Lite extension API look like.
The linked PR gives you a glimpse of what the API draft looks like right now. However, that's just API - it's nice but you cannot try it out in action, right?
That's why we have also created a simple implementation for the annotation transformation part of API inside Quarkus. It uses none of Quarkus-specific APIs, just what we presented here and having tried that in Quarkus proves its viability for build-time environments (although it doesn't limit it for just that). For the sake of simplicity it right now contains a copy of the APIs inside the fork.
Intructions on how to try it out are in the blog post.
Got an idea how to improve it? What's missing or what's superfluous? We'd love to hear what you think of this API!
In order to keep it all in a readable and traceable format, please provide your feedback in form of separate GH issue on this repo with label lite-extension-api
.
Rework portable extension so that they can be found at build time instead of runtime.
As a developer, I want to use cdi extension to:
Providing its own beans, interceptors and decorators to the container
Injecting dependencies into its own objects using the dependency injection service
Providing a context implementation for a custom scope
Augmenting or overriding the annotation-based metadata with metadata from some other source
The changes made in #445 means that a manually set configuredProvider can be lost for good if it ever returns null and it is registered in the ServiceLoader.
Missing 'b' on this line:
eans_3_0.xsd schema file has changed from
This also affects the "The BeanContainer
object" chapter:
It also affects the "Modularity" chapter:
There's a lot of mentions of passivation concepts in the CDI Lite specification part. We need to decide what to do with them: move to Full, leave them where they are?
List of places:
Similiar to Spring IOC, for a component managed by CDI, if there is only one constructor with parameters, it should be injected automatically without an explicit @Inject
.
private final OrderRepository orders; // OrderRepository is a CDI bean
public class OrderService(OrderRepository orders){ //OrderRepository should be injected automatically here.
this.orders = orders;
}
Similarly the methods of a component should be handled automatically.
I'm aware of the fact that it's still work in progress but it wouldn't hurt to update at least some key parts.
https://issues.redhat.com/browse/CDI-414
To me, this example from JIRA issue perfectly describes what one would want to achieve:
public class TimedMethodBean {
@Timed(name = "timedMethod")
public void timedMethod() {
}
public void selfInvocationTimedMethod() {
timedMethod(); //this method call will not be timed :(
}
}
There are certain bits in the specification that have been carried over as deprecated legacy for years.
I think for future versions we can easily shake them off.
I discovered the following deprecated parts that I think we can remove:
@New
qualifier
@Dependent
Bean.isNullable()
method
BeanManager.fireEvent()
method
BeanManager.getEvent()
BeanManager.createInjectionTarget(AnnotatedType)
method
BeanManager.getInjectionTargetFactory(AnnotatedType)
BeforeBeanDiscovery.addAnnotatedType(AnnotatedType)
method
BeforeBeanDiscovery.addAnnotatedType(AnnotatedType, String)
beans.xml
For compatibility with Contexts and Dependency 1.0, products must contain an option to cause an archive to be ignored by the container when no beans.xml is present.
Obviously, for all of the above changes might be needed in both, API and specification text.
I added a TODO "are implementations required to support Full?" into the CDI SE chapter, because I think this should be spelled out explicitly. The answer is probably yes, but we may need to debate it a little (because I think Micronaut is trying to implement some parts of the SE API, and I don't see anything particularly wrong with that, even though they won't support Full).
Could you please confirm whether you intend to implement SeContainer
etc., @graemerocher?
There is https://repo.maven.apache.org/maven2/jakarta/enterprise/jakarta.enterprise.cdi-api/3.0.0/ published.
May I ask to tag the version that was used to produce this release, please?
There was a discussion on observer resolution concerns 10.3.1. Assignability of type variables, raw and parameterized types tracked in https://issues.redhat.com/browse/CDI-736, which is unclear about the if assigning a non-parameterized subclass
to a parameterized superclass
should work or not:
public interface QualifiedEvent<T> {
// some methods
}
public class EventImpl implements QualifiedEvent { //NOTE - implements raw type
// some method impls
}
observer code:
void listenForChildEvent(@Observes QualifiedEvent<Bar> foo) {
// stuff going on here...
}
event type:
new EventImpl(clazz);
In this scenario, the spec is IMO unclear on what should happen in this particular case
Looking at other parts of spec, we already have this covered in, for instance, delegate injection point assignability, where it says:
A raw bean type is considered assignable to a parameterized delegate type if the raw types are identical and all type parameters of the delegate type are either unbounded type variables or java.lang.Object.
I think we should add a similar sentence to 10.3.1. Assignability of type variables, raw and parameterized types. That way the spec will behave coherently and the above observer/event assignability should not work.
Side note - for the sample above to work, you would need to change the observed types to QualifiedEvent<?>
.
Since working group agreed to make CDI Lite a subset of CDI core, we need to organize the spec to introduce CDI Lite in it.
New organization should split the current core part in CDI Lite and CDI Full subparts.
In light of this discussion on allowing widely adopted by compile-time runtimes, the following use case is requried.
As a implementor of CDI spec, I would like to support the CDI parts, which can be determained at compile time so that my end users can benefit from CDI and AOT.
There currently exists an issue where if a event is fired from within an JPA EntityListener (@PostUpdate
for example) the event may not be reliably observed via an @Observes(during = TransactionPhase.AFTER_SUCCESS)
The issue comes down to what state Transaction is in when the entityManager.flush is called (trigging the post update for example). If the entityManager.flush is called manually then the @PostUpdate
is run while the transaction is active and things will work fine. If however, the flush is automatically called via the ending of an @Transactional
method then when the @PostUpdate
is run the transaction has moved past the ACTIVE status and the synchronization cannot be added to the transaction. No error is thrown and the event will silently not be observed.
Possible thoughts were having the the CDI event registered with an TransactionSynchronizationRegistry#registerInterposedSynchronization
It appears that you could do something like
@PostUpdate
public void postUpdate(Ticket entity) {
try {
TransactionSynchronizationRegistry registery = (TransactionSynchronizationRegistry) new InitialContext().lookup("java:comp/TransactionSynchronizationRegistry");
registery.registerInterposedSynchronization(new MySyncronization());
}
catch (NamingException e) {
throw new RuntimeException(e);
}
}
public class MySyncronization implements javax.transaction.Synchronization {
static final Logger log = Logger.getLogger(MySyncronization.class);
@Override
public void beforeCompletion() {
}
@Override
public void afterCompletion(int status) {
if (status==3){
CDI.current().getBeanManager().fireEvent(EntityEvent.updated(entity));
}
}
}
This appears to accomplish what we want, but obviously is not friendly to use.
The current thought is to potentially clarify in the spec that CDI events should use an Interposed Synchronization either all the time or only if a standard synchronization cannot be obtained, but that may have ramifications that I am not considering.
This jumps off from https://issues.redhat.com/browse/WELD-2444
Instructions
Details are
here
We should create a new BM interface containing methods supported by lite only.
The current BM would be accessible by extending this lighter BM and add the missing methods for Full.
Create/Update CONTRIBUTING files
Per input from the Eclipse EMO, each Specification Project needs to ensure that a CONTRIBUTING.md or CONTRIBUTING.adoc file exists in each specification-related repository maintained by Specification Projects.
In addition, the CONTRIBUTING.md or CONTRIBUTING.adoc file needs to include the following text:
## Eclipse Development Process
This Eclipse Foundation open project is governed by the Eclipse Foundation
Development Process and operates under the terms of the Eclipse IP Policy.
The Jakarta EE Specification Committee has adopted the Jakarta EE Specification
Process (JESP) in accordance with the Eclipse Foundation Specification Process
v1.2 (EFSP) to ensure that the specification process is complied with by all
Jakarta EE specification projects.
* https://eclipse.org/projects/dev_process
* https://www.eclipse.org/org/documents/Eclipse_IP_Policy.pdf
* https://jakarta.ee/about/jesp/
* https://www.eclipse.org/legal/efsp_non_assert.php
Please do this at your earliest convenience.
Thank you!
-- EE4J PMC ([email protected])
Section 11.5.4 says:
The container must fire an event after it has validated that there are no deployment problems and before creating contexts or processing requests [emphasis mine].
Section 11.3 indicates that it is legal to call BeanManager#getReference(Bean, Type, CreationalContext)
in an AfterDeploymentValidation
observer method.
In order to get contextual references, such as those returned by getReference()
, you need a context.
Is this a bug in the specification? Does section 11.5.4 need to be amended in some way?
There's a lot of mentions of Portable Extensions concepts in the CDI Lite specification part. We need to decide what to do with them: move to Full, leave them where they are and amend by mentions of new extension API?
List of places:
Per the discussions on the Spec Committee and Platform Dev mailing lists, it's been discovered that many of the Javadoc and Spec references to the EFSL need updating. Please reference the following required updates and keep them in mind as your Spec Project is updating the files for Jakarta EE 9.
Note: Some Spec Projects have already started or even completed these updates. If so, just kindly return/close this Issue. Thanks!
Required EFSL updates for Javadoc
For javadoc, the EFSL.html located in src/main/javadoc/doc-files should be modified as follows:
<<url to this license>>
needs to be replaced with efsl.php link[1][title and URI of the Eclipse Foundation specification document]
needs to be replaced with the Specification Name and URL (Reference [2] for an example.)Required EFSL updates for Specifications
For specification, the license-efsl.adoc located in src/main/asciidoc should be modified as follows:
<<url to this license>>
needs to be replaced with efsl.php link[1][title and URI of the Eclipse Foundation specification document]
needs to be replaced with the Specification Name and URL (Reference [2] for an example.)[1] https://www.eclipse.org/legal/efsl.php
[2] https://jakarta.ee/specifications/enterprise-beans/4.0/
I'm not really happy with the RequestContextController. And it appears to me that the spec is broken.
Here is the important part from the spec:
6.5.2. Activating Built In Contexts
Certain built in contexts support the ability to be activated and deactivated. This allows developers to control built-in contexts in ways that they could also manage custom built contexts.
When activating and deactivating built in contexts, it is important to realize that they can only be activated if not already active within a given thread.
6.5.2.1. Activating a Request Context
Request contexts can be managed either programmatically or via interceptor.
To programmatically manage request contexts, the container provides a built in bean that is @dependent scoped and of type RequestContextController that allows you to activate and deactivate a request context on the current thread. The object should be considered stateful, invoking the same instance on different threads may not work properly, non-portable behavior may occur.
public interface RequestContextController {
boolean activate();
void deactivate() throws ContextNotActiveException;
}
When the activate() method is called, if the request context is not already active on the current thread then it will be activated and the method returns true. Otherwise, the method returns false.
When the deactivate() method is called, if this controller started the request context then the request context is stopped. The method does nothing if this controller did not activate the context
The problem is that there are 2 ways to use that part
a.)
boolean didActivate = reqCtxCtrl.activate();
...
if (didActivate) reqCtxCrl.deactivate();
b.)
try {
reqCtxCtrl.activate();
...
} finally {
reqCtxCrl.deactivate();
}
The problematic part is nesting.
In case a) we got maybe 7 calls to activate() but only 1 to deactivate.
In case b) we got 7 calls to activate and 7 to deactivate();
There is simply no way to implement this in a clean way. A simple boolean flag does not help because of concurrency. A ThreadLocal does not help much either. If we use a ThreadLocal we potentially leak memory in case of a). If we close immediately we potentially close way too early in case b).
When bridging between synchronous and event-driven APIs, there comes a situation when a synchronous method sends a request in the form of a CDI event and then needs to wait until a responding CDI event was received (i. e. it shall not just wait for the request event to be sent but really wait for an answering event was received). After that, the synchronous method can read that responding event and provide its own return value to the caller.
Unfortunately I have not found any easy way to write code for such a situation in CDI (maybe I missed something). I could imagine passing a Future around in the CDI event payload where the orignal thread waits for and where an observer method would fulfil - but that sounds pretty complex.
What I could imagine would be something like "temporary observers", i. e. before the synchronous method sends the original request CDI event, it registeres a lambda function as a CDI event observer for the expected answer. Once that lamba event fires, it unregisters itself before it returns the result to the blocked caller. I know that programmatic global observers are aready possible as extensions, but those cannot interact with the waiting thread inside of the synchronous caller method.
Is this already possible or is it planned for the future or is there another simple solution how to make a synchronous non-static method wait for an event in such a dynamic way?
The issue in MicroProfile was reported for a potential security vulnerability. Please comment if you disagree with the security vulnerability claim.
I noticed the el-api dependency was optional in CDI 1.0, but from CDI 1.1, the EL-API dependency is mandatory. Can someone explain why? Is it possible to make the dependency optional?
(copied from CDI.Next doc, as there was no issue yet to track this)
Currently CDI does not have a concept of a bean method that can be executed from another bean with parameter binding.
Such a concept is used in other specs, such as JAX-RS, where resource methods are executed at runtime with the need to bind their parameters, and provide the support for interceptors and other CDI features.
The CDI spec should add API for such a feature, so other specs do not need to define a custom solution.
The following should be possible:
Pseudocode:
Let’s consider the following bean:
@RequestScoped
@Path("/greet")
public class Resource {
@GET
String helloWorld(@HeaderParam("HEADER") String header) {
}
}
@Qualifier
@Target(ElementType.PARAMETER)
public @interface HeaderParam {
String value();
}
Now we could create a parameter binder:
@Singleton
@Binder(HeaderParam.class)
public class HeaderParamBinder implements ParamBinder {
// HttpHeaders is a request scoped bean
private final HttpHeaders headers;
private final Converter converter;
@Inject
HeaderParamBinder(HttpHeaders headers, Converter converter) {
this.headers = headers;
this.converter = converter;
}
public <T> T bind(HeaderParam annotation, GenericType<T> type) {
return converter.convert(headers.getRequestHeader(annotation.value()), type);
}
}
And the execution of this method would be something like:
@MethodHandler(Path.class)
public class JaxRsExecutor implements ExecMethodHandler<Object, Object> {
private final ParameterBinder binder;
private final Container container;
@Inject
JaxRsExecutor(ArgumentBinder binder) {
this.binder = binder;
}
@Override
public void processMethod(ExecutableMethod<Object, Object> method) {
// process registration with web server
}
private void executeMethod(ExecutableMethod<Object, Object> method) {
// start request scope
Object beanInstance = container.select(method.getDeclaringType()).get();
method.invoke(beanInstance, binder.bind(method));
}
}
The "Inter-module injection in CDI Full" chapter in the specification has a TODO for deciding whether the chapter should extend rules from CDI Lite and add few more (current state, somewhat hard to read), or completely override the CDI Lite rules (would require some duplication, but might be easier to read).
CDI extensions allow us to add a new annotated type.
A typical use case is to programmatically add or remove annotations to/from existing types, which makes the usage of wrappers necessary. CDI does not provide default wrappers, so projects often need to recreate these. While not difficult, it's tedious and error prone.
Just like APIs like e.g. Servlet and Faces, it would be good if CDI provided a few default wrappers here.
When wanting to delete a bean instance from the HTTP session that hasn't been accessed via Contex#get in that request, destroy doesn't do anything when using Weld.
Is that intended?
I debugged and it seems to be due to the session context being lazy.
As seen with the effort to complete the CDI updates for EE9, while CDI has a wave 3 API dependency, the TCK includes integration tests that belong in the web and full profiles. These tests should be moved into separate integration tests that can be incorporated into the platform TCKs.
There's a couple of mentions of other Full concepts in the CDI Lite specification part, specifically in "Container invocations and interception" and "Built-in annotation literals". We need to decide what to do with them: move to Full, leave them where they are?
List of places:
=> no license nor notice file found. These files are required to be present in the main distribution jar as well as source jar, see https://www.eclipse.org/projects/handbook/#legaldoc-distribution for details
https://jakarta.ee/specifications/cdi/3.0/cdi-spec-3.0.0-M4.html
eg, https://jakarta.ee/specifications/cdi/3.0/cdi-spec-3.0.0-M4.html#trimmed_bean_archive
It should use the new jakarta namespace.
In CDI spec, the context propagation was not addressed in the spec. The original ticket was raised:
Key: CDI-587
URL: https://issues.jboss.org/browse/CDI-587
Project: CDI Specification Issues
Issue Type: Epic
Components: Contexts
Affects Versions: 1.2.Final
Reporter: Romain Manni-BucauThe overall idea is to ensure that it is not cause the code becomes asynchronous/reactive/... that we loose the instances or get another context.
An example is starting an AsyncContext in a servlet.
One proposal is to add a flag to ask for propagation of the context in async managed threads: @RequestScoped(inherited = true) which would reuse the same instances for these "new" threads.
Note however this issue is not only bound to servlets even if it is the easiest example.
The original thread disucssion on the list: http://cdi-development-mailing-list.1064426.n5.nabble.com/RequestScope-Life-Cycle-td5712701.html
In MicroProfile Context Propagation, some effort was made to address the context propagation and the implementation was made in Weld. However, it has a some issues, such as eclipse/microprofile-context-propagation#167
Javadoc generation requires Xdoclint to be turned deactivated:
mvn javadoc:javadoc -DadditionalJOption=-Xdoclint:none
We should review all Javadoc to fix issue preventing the use of Xdoclint
Currently when adding a Bean<T>
using jakarta.enterprise.inject.spi.AfterBeanDiscovery.addBean()
or jakarta.enterprise.inject.spi.AfterBeanDiscovery.addBean(Bean<?>)
any decorators declared or programatically added for the types of the Bean<T>
are not automatically applied.
Not only is this perhaps surprising, there actually is no portable way to achieve this behaviour. Someone adding a bean must resort to SPIs and implementation specific code. For instance Soteria uses the following code:
afterBeanDiscovery.addBean(
decorator.decorateBean(authenticationMechanismBean, HttpAuthenticationMechanism.class, beanManager));
Where decorator.decorateBean
is an SPI, that for Weld uses code such as the following:
public class DecorableWeldBeanWrapper<T> extends RIBean<T> implements Bean<T>, PassivationCapable {
private final Bean<T> bean;
private final CurrentInjectionPoint currentInjectionPoint;
private final boolean isProxyable;
private Class<T> type;
private List<Decorator<?>> decorators;
private Class<T> proxyClass;
private boolean proxyRequired;
private boolean isPassivationCapableBean;
private boolean isPassivationCapableDependency;
public DecorableWeldBeanWrapper(Bean<T> bean, Class<T> type, BeanManagerImpl beanManager) {
super(
bean,
new StringBeanIdentifier(BeanIdentifiers.forBuiltInBean(beanManager, type, null)),
beanManager);
this.bean = bean;
this.type = type;
this.currentInjectionPoint = beanManager.getServices().get(CurrentInjectionPoint.class);
this.isProxyable = Proxies.isTypesProxyable(getTypes(), beanManager.getServices());
}
@Override
public void initializeAfterBeanDiscovery() {
decorators = beanManager.resolveDecorators(getTypes(), getQualifiers());
if (!decorators.isEmpty()) {
proxyClass = new ProxyFactory<T>(getBeanManager().getContextId(), getType(), getTypes(), this).getProxyClass();
}
}
@Override
protected void internalInitialize(BeanDeployerEnvironment environment) {
proxyRequired = getScope() != null && isNormalScoped();
isPassivationCapableBean = Serializable.class.isAssignableFrom(type);
isPassivationCapableDependency = isNormalScoped() || (isDependent() && isPassivationCapableBean());
}
@Override
public T create(CreationalContext<T> creationalContext) {
T instance = bean.create(creationalContext);
if (decorators.isEmpty()) {
return instance;
}
return getOuterDelegate(this, instance, creationalContext, proxyClass, currentInjectionPoint.peek(), getBeanManager(), decorators);
}
This code is difficult to come up with, difficult to maintain and error prone. The user must also make sure the right companion SPI implementation is available on the class path.
To simplify this, I'd like to propose a method for BeanConfigurator
to signal to the runtime that enabled decorators should be applied to the instance returned from the Bean.create
(`Contextual.create') method, just like happens for beans which implement the bean types directly and are discovered by CDI.
For instance:
public void afterBean(final @Observes AfterBeanDiscovery afterBeanDiscovery) {
afterBeanDiscovery
.addBean()
.scope(ApplicationScoped.class)
.types(MyBean.class)
.id("Created by " + CdiExtension.class)
.enabledDecorators()
.createWith(e -> new MyBeanImpl("Hi!"));
}
Several variants could be considered, like e.g.:
I would like to propose a new scope called @SessionCacheScoped
with an optional cache name. The purpose of the scope is, that data is associated with a session without using the HttpSession
as storage. I often associate some data that I loaded from the database with a user session and using @SessionScoped
is usually fine, but in a clustered setup this becomes a problem due to session replication overhead. To avoid these issue, I would like to put the beans into a local cache instead which is associated with the session.
One might think that this kind of scope should be provided by JCache(JSR 107), but since it is not part of Jakarta EE (yet), I wanted to post it here and maybe start a discussion about the possible inclusion of the JCache API.
This is an umbrella issue to track the work on eliminating all TODO comments from the CDI specification Asciidoc sources, added in the initial Lite/Full split PR (#470). More sub-issues will be created and this issue will list them (and their status) to provide an overview.
EventMetadata
interface"Personal opinion: I have added the TODO comments instead of just Asciidoc admonitions, because that allows easy tracking of the number of remaining open items (single grep
command). I don't mind putting the content of the TODO comments into admonitions (and leaving an empty TODO comment alongside), but I believe this should all be primarily present directly in the Asciidoc source, so that context is immediately obvious. Tracking in GitHub issues is, in my opinion, secondary.
Is your feature request related to a problem? Please describe.
Jakarta EE 9 is the next major release, with the main focus of moving from the javax
namespace to the jakarta
namespace.
Describe the solution you'd like
This issue will be used to track the progress of this work effort via the Jakarta EE 9 Project board.
Additional context
Jakarta EE Specification Process
Eclipse Project Handbook
Eclipse Release Record for Jakarta EE 9
ToDo
The "Unsatisfied and ambiguous dependencies" chapter has a TODO for deciding if we have to mention that the alternatives must be selected, similarly to the "Ambiguous names" chapter.
I added a TODO saying "we might be able to make @Singleton
a bean defining annotation in Lite? depending on how we decide on the beans.xml thing". Later, I realized that this would make Lite a not-a-strict-subset of Full, so this is a bad idea. The TODO should be removed without action.
Linking to this previous
https://issues.redhat.com/browse/CDI-535
Description
We should allow ordering of bean instance injection using the Instance when an instance injection is used.
A frequent request for CDI is to replace EJB as CDI is becoming more and more popular and widely adopted. CDI covers many EJB functionalities with a much easier framework. However, there are some gaps to be filled. I would like to use this issue to address the gaps where CDI has no counterpart functionalities. This includes:
startup
Timer
I think the useful feature of EJB is startup, so in CDI, we should provide this equivalent feature. As for Timer support, I think it can be supplied by other specs.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.