jaspersoft / jrs-rest-java-client Goto Github PK
View Code? Open in Web Editor NEWJava Rest Client for JasperReports Server
License: GNU Lesser General Public License v3.0
Java Rest Client for JasperReports Server
License: GNU Lesser General Public License v3.0
It would be really useful to be able to retrieve all ClientUser
from an Organisation
It would ease the process to, for instance, add a new ClientUserAttribute
on all users from this Organisation
Among other examples, could be useful to remove a ClientRole
from all users but not removing it from the Organisation
, or only from the users that have certain attribute.
What do you think?
Thanks,
Fran
we need a better way to configure connection: proxy (http, socks, etc.) , timeouts, https
hide jersey complexity
maybe for devops it could be a good idea to use yaml files for your configuration instead
also using http://www.jasypt.org/ for password encryption could be a nice feature
There is a need to get an ErrorDescriptor instance in case of exception.
uploadFile method in SingleResourceAdapter class send post request because of which I am not able to modify an already existing file. Please provide some mechanism to do that. For now i have modified the post to put and works fine for me.
in case of java 6, 7 compatibility
JSClientException, super constructor does not exists, one with many parameters
Like in Camel it would be nice if you could specify the work manager interface, in the case of weblogic we then link it to the executerService on the EE container instead of managing the threads yourself behind the scenes
http://www.oracle.com/technetwork/articles/entarch/parallel-tasks-087492.html
Hello, Paul from QA Automation here.
Here's the code I wrote to check whether the resource was already present:
getRestClient(superuser)
.resourcesService().resource("/qa_automation/SomeSubFolder").details()
.getResponse().getStatus()
I expected this code to return 404 in case the resource was not present, but instead it failed with ResourceNotFoundException.
In my opinion, throwing an exception would be perfectly fine if instead of getResponse()
, getEntity()
was used. But I think that customers will use getResponse()
mostly to check for unhappy/unsure cases, therefore it makes sense not to throw errors in this case (besides, the Jersey client works in similar fashion). Additionally, communicating a perfectly valid state (i.e. no resource) via exceptions is considered bad practice.
Tere is a need to get not unmarshalled content.
I'm trying to get information about my reports' inputs, some of them have inputs but others don't and I won't know ahead of time which do and which don't. When I run the code below on a report with inputs, it works great. However when run on a report without inputs the method returns null. Is there a better way to handle this? Maybe a custom exception or something else? I ran into a similar issue using Visualize.js, which at the time of my writing hasn't been resolved yet. Here is the link to that issue http://community.jaspersoft.com/questions/844608/issue-report-no-inputs
Here is the code I am running:
ReportInputControlsListWrapper inputWrapper1 = session .reportingService() .report(reportWithOutInputs) .reportParameters() .get() .getEntity(); ReportInputControlsListWrapper inputWrapper2 = session .reportingService() .report(reportWithInputs) .reportParameters() .get() .getEntity(); LOGGER.info(inputWrapper2.toString()); LOGGER.info(inputWrapper1.toString()); //Throws null pointer
Any plan to upgrade the jackson dependencies ? We are looking to integrate this, but it uses the older versions, which we would like to avoid if possible.
I found that jasper server support RSA password encryption when logging in. Is it possible to add an autodetection and handle this case?
My program get public key though GetEncryptionKey to encrypt the password, then use the library to login.
I set the encryption.dynamic.key=true under security-config.properties, so the public key is only valid under a session.
How do set the session Id before execute
Session session = client.authenticate("jasperadmin", "jasperadmin");
can u provide a constructor in JasperserverRestClient which accept session id?
Whenever I try to create a user with a tenantId matching an existing organization id in the server, I get the same error saying:
com.jaspersoft.jasperserver.jaxrs.client.core.exceptions.IllegalParameterValueException: The value "Test" for parameter "tenantId" is invalid.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
I'm using "Test" or "1234567890111213" as values for tenantId
I also get the same error when using this id's to create a new Organization.
Thanks in advance and for the great work,
Fran
IMHO, it should be acceptable that end page is the same as start page.
Start page 1 and end page 1 should be taken the same way as "1" for development comfortability purposes. In short, this would then work:
private static ReportExecutionRequest buildReportExecutionRequest(String path, ReportOutputFormat outputFormat, Integer startPage, Integer endPage) {
ReportExecutionRequest request = new ReportExecutionRequest();
if (startPage == null) {
startPage = 1;
}
if (endPage == null) {
endPage = startPage;
}
if (endPage > startPage) {
throw new IllegalArgumentException("End page cannot be greater than start page. Please check and correct the request");
}
request.setReportUnitUri(path);
request.setPages("" + startPage + "-" + endPage);
request.setAsync(false);
request.setOutputFormat(outputFormat.name());
return request;
}
Right now you get a:
com.jaspersoft.jasperserver.jaxrs.client.core.exceptions.ReportStartPageGreaterThenEndPageException: report.start.page.greater.then.end.page
What do you think about it?
Thanks!
i think there is a problem with your callback mechanism
in the run method you should post the ReportExecutionRequest instead of the reqest
=> callback.execute(request.post(request));
should be ==> callback.execute(request.post(reportExecutionRequest));
public <R> RequestExecution asyncNewReportExecutionRequest(final ReportExecutionRequest reportExecutionRequest,
final Callback<OperationResult<ReportExecutionDescriptor>, R> callback) {
final JerseyRequest<ReportExecutionDescriptor> request =
buildRequest(sessionStorage, ReportExecutionDescriptor.class, new String[]{"/reportExecutions"});
RequestExecution task = new RequestExecution(new Runnable() {
@Override
public void run() {
callback.execute(request.post(request));
}
});
ThreadPoolUtil.runAsynchronously(task);
return task;
}
When i set the connectionTimeout and readTimeout Parameters
connectionTimeout=5000
readTimeout=5000
i get this error:
aug 19, 2014 2:49:55 PM org.glassfish.jersey.internal.util.PropertiesHelper convertValue
WARNING: There is no way how to transform value "5000" [java.lang.Long] to type [java.lang.Integer].
Probalby because you handle them as Long and the jersey client uses integers
Long connectionTimeout = configuration.getConnectionTimeout();
if (connectionTimeout != null)
client.property(ClientProperties.CONNECT_TIMEOUT, connectionTimeout);
Long readTimeout = configuration.getReadTimeout();
if (readTimeout != null)
client.property(ClientProperties.READ_TIMEOUT, readTimeout);
JRS provides com.jaspersoft.jasperserver.dto.authority.ClientTenant class while the REST client still uses its own com.jaspersoft.jasperserver.jaxrs.client.dto.authority.Organization, which, basically, contains the same set of fields and is used for the same purpose. Switching to ClientTenant from jasperserver-dto.jar is preferred as it is consistent with other API. OrganizationsListWrapper, which uses ClientTenant instead of Organization, is provided by jasperserver-dto.jar as well.
Also it would benefit to update organization adapters code to be consistent with other adapters (i.e. provide updateOrCreate methods).
exceptions handling, could be better, look at
http://code.jaspersoft.com/svn/repos/jaspersoftstudio/trunk/com.jaspersoft.studio.server/src/com/jaspersoft/studio/server/protocol/restv2/RESTv2ExceptionHandler.java
this one will resolve messages from the server if available, and a lit bit more problems I faced
Problem, i wanted to see what was going on so i debugged it by outputting the responses
// System.out.println("getResponse ==>" + reportExecutionDescriptorOperationResult.getResponse());
// System.out.println("operationResult ==>" + reportExecutionDescriptorOperationResult.getSerializedContent());
ReportExecutionDescriptor reportExecutionDescriptor = reportExecutionDescriptorOperationResult.getEntity();
System.out.println("reportExecutionDescriptor ==>" + reportExecutionDescriptor);
my reportExecutionDescriptor was allways null !
Solution, : probably you are reading multiple methods:
The getSerializedContent() and getEntity() reads the response like this:
response.readEntity(entityClass); and closes the response !
refr javadoc on : public abstract T readEntity(Class entityType);
so i can't read them both, because i have a
"java.lang.IllegalStateException: Entity input stream has already been closed."
exception, so read only one, then it's fixed
also watch out to use a newer jersey version because this also was related to this bug:
https://java.net/jira/i#browse/JERSEY-1526
Hi
I added the dependency and repositories as follows
com.jaspersoft jrs-rest-java-client 5.5.0-SNAPSHOT<repositories>
<repository>
<id>jaspersoft-clients-releases</id>
<name>Jaspersoft clients releases</name>
<url>http://jaspersoft.artifactoryonline.com/jaspersoft/jaspersoft-clients-releases</url>
</repository>
<repository>
<id>jaspersoft-clients-snapshots</id>
<name>Jaspersoft clients snapshots</name>
<url>http://jaspersoft.artifactoryonline.com/jaspersoft/jaspersoft-clients-snapshots</url>
</repository>
</repositories>
And my code is as below
RestClientConfiguration configuration = new RestClientConfiguration("http://localhost:8080/jasperserver");
JasperserverRestClient client = new JasperserverRestClient(configuration);
OperationResult result = client
.authenticate("superuser", "ariveguru")
.reportingService()
.report("/reports/samples/Cascading_multi_select_report")
.prepareForRun(ReportOutputFormat.HTML, 1)
.parameter("project_id", "2")
.run();
result.getEntity();
I got the following error ,Please help me out
javax.ws.rs.ProcessingException: javax.ws.rs.core.Response$Status$Family.familyOf(I)Ljavax/ws/rs/core/Response$Status$Family;
Hi Borys,
I'm trying to update a user assigning a second new role.
When I try to update the user, even when I'm passing in two valid ClientRole objects, I get an IllegalParameterValueException with the message "The value "" for parameter "roleSet" is invalid"
Here is my code:
@Override
public ClientUser updateUser(ClientUser user) {
boolean userExists = findUser(user.getUsername(), user.getTenantId()) != null;
OperationResult<ClientUser> updateResult;
if (userExists) {
updateResult = openAdminSession()
.usersService()
.organization(user.getTenantId())
.username(user.getUsername())
.createOrUpdate(user);
return updateResult.getEntity();
}
return null;
And the values that are passed in:
ClientRole{name='ROLE_MYROLE_ONE', externallyDefined=false, tenantId='COMPANY_ONE'}
ClientRole{name='ROLE_USER', externallyDefined=false, tenantId='null'}
The second one was already assigned as I created the user and before assigning the role I retrieved it from the server
And the error for the ".createOrUpdate(user)" operation:
com.jaspersoft.jasperserver.jaxrs.client.core.exceptions.IllegalParameterValueException: The value "" for parameter "roleSet" is invalid.
User's TenantId is set and available.
Thanks in advance,
Fran
Hello!
Paul Danyliuk from QA Automation team here, I finally got my hands on this client and noticed one minor usability issue with it.
Imagine we are creating a user and an attribute for them:
ClientUser user = new ClientUser()
.setUsername("demoFlowsUser")
.setPassword("demoFlowsUser")
.setEmailAddress("[email protected]")
.setFullName("Demo Flows User")
.setTenantId("organization_1")
.setEnabled(true);
this.getRestClient(jasperadmin)
.usersService()
.organization(user.getTenantId()) // maybe here too
.username(user.getUsername()) // here
.createOrUpdate(user)
.getEntity();
ClientUserAttribute stateAttribute = new ClientUserAttribute()
.setName("State")
.setValue("CA");
this.getRestClient(jasperadmin)
.usersService()
.organization(user.getTenantId())
.username(user.getUsername())
.attribute("State") // here
.createOrUpdate(stateAttribute);
As you might have noticed, we have to pass user ID and attribute name to username()
and attribute()
explicitly even if we are passing the whole object to the following method in chain (createOrUpdate()
). I understand that the former two methods are there solely to build request URL, and createOrUpdate()
sets the body without altering URL. But such redundancy confused me a bit. Wouldn't it be better to have it something like that? :
this.getRestClient(jasperadmin)
.usersService()
.organization(user.getTenantId())
.createOrUpdate(user)
/* or .createOrUpdateUser(user), however it's stated above that it's usersService() */
.getEntity();
/* BUT */
this.getRestClient(jasperadmin)
.usersService()
.organization(user.getTenantId())
.username(user.getUsername())
.get()
.getEntity();
Not much of a concern, but for your review and consideration.
It seems that the client is licensed under AGPL โ which (IIRC) means the client can be used within / linked to only those applications that are AGPL themselves (i.e. a customer with non-AGPL back-end cannot use this client to get reports from JRS and then serve them to customers).
Please consult your management about a better license choice. I'd personally suggest a permissive license like MIT or BSD, or LGPL in case *GPL is a requirement.
Hi,
My report contains some Date type parameters. When my program run the report in jasper server, for example:
OperationResult result = client
.authenticate("jasperadmin", "jasperadmin")
.reportingService()
.report("/reports/samples/Cascading_multi_select_report")
.prepareForRun(ReportOutputFormat.HTML, 1)
.parameter("Cascading_name_single_select", "A & U Stalker Telecommunications, Inc")
.run();
InputStream report = result.getEntity();
I found that only String type data can be assigned. Can you add more data type support? Or is there any way to make the report receive Date Type parameters etc?
I am not sure why, but the following:
ClientDomainTopic resourceCopy = (ClientDomainTopic) session
.resourcesService()
.resource(parentFolder.getUri())
.copyFrom(resource.getUri())
.getEntity();
returns null (resource is a DomainTopic itself). For domains and reports this seems to work fine. Underlying exception is NPE in com.jaspersoft.jasperserver.jaxrs.client.core.operationresult.OperationResult#getEntity - entityClass is null for some reason (and could not debug deeper - the code is very tangled ;) )
I have a Report with 1 Parameter that takes a string value. It looks like the value is not getting to the server. It shows as NULL in the Job that's returned from scheduling and the report that's returned is empty like there was no parameter value.
Map<String, Object> reportParameters = new HashMap<String, Object>();
reportParameters.put("po",(Object) new ArrayList<String(Arrays.asList("WAKE")));
JobSource jobSource = new JobSource();
jobSource.setReportUnitURI("/Production_Reports/MonthlyCleanup/monthly_cleanup");
jobSource.setParameters(reportParameters);
I can see the parameters in the JobSource before the schedule.
System.out.println("Built JobSource=" + jobSource);
Built JobSource=JobSource=JobSource{reportUnitURI='/Production_Reports/MonthlyCleanup/monthly_cleanup', parameters={po=[WAKE]}}
But the value comes back as NULL after scheduling.
OperationResult<Job> result = session.jobsService().scheduleReport(job);
Job sJob = result.getEntity();
System.out.println("\nScheduled JobSource=" + sJob.getSource());
Scheduled JobSource=JobSource{reportUnitURI='/Production_Reports/MonthlyCleanup/monthly_cleanup', parameters={po=[~NULL~]}}
I'm using the latest snapshot jar from the 16th, with Jasper 5.5.0. The job executes without any errors. It just doesn't return any output.
I am trying to test using this framework, using jetty to start a web-app, and after I've added the dependency, I get this error:
java.lang.AbstractMethodError: javax.ws.rs.core.UriBuilder.uri(Ljava/lang/String;)Ljavax/ws/rs/core/UriBuilder;
After some digging it turns out that this is due to a mismatch between the jersey api and the implementation. The dependencies of the project has a dependency to jersey api 2.x (org.glassfish.jersey.core:jersey-client:jar:2.5 -> javax.ws.rs:javax.ws.rs-api:jar:2.0), and also a dependency to jax-rs 1.0 implementation com.sun.jersey:jersey-json:jar:1.18. Will this ever work?
Hello,
Any idea how to enable the DELETE rest command on the jasperserver?
when i try to delete a created folder via the api i get this response.. or i'm missing something?
The user used is the admin so..
InboundJaxrsResponse{
ClientResponse{method=DELETE, uri=http://path_to_server/jasperserver/rest_v2/resources, status=403, reason=Forbidden}}
Hi,
To poll report execution in jasperserver 5.5, we could do that :
session.reportingService()
.reportExecutionRequest(requestId)
.export(outputFormat)
.status()
for some reasons the exportId was equal to the outputformat (pdf, xlsx, ...)
in 5.6 version the url has to contain a randomly generated exportId instead of the outputFormat
http://<host>:<port>/jasperserver[-pro]/rest_v2/reportExecutions/requestID/exports/exportID/status
I tried to get the exportId by quering the details after requesting the report execution asynchronously, but I was unable to do so.
Either the documentation is missing some tips or the methods to achieve this are missing.
What do you think ?
Regards,
nicolas
Running this code gives me the ReportExecutionDescriptor, however in the ExportDescriptor it states id="pdf" ... i guess this should be outputFormat?
=> exports=[ExportDescriptor{id='pdf', status='execution', pages='null', attachmentsPrefix='null', outputResource=null, attachments=null}]}
ReportExecutionRequest request = new ReportExecutionRequest();
request.setReportUnitUri("/reports/samples/StandardChartsReport");
request
.setAsync(true)
.setFreshData(true)
.setParameters(new ReportParameters(params))
.setIgnorePagination(true)
.setOutputFormat("pdf");
OperationResult<ReportExecutionDescriptor> operationResult =
session
.reportingService()
.newReportExecutionRequest(request);
ReportExecutionDescriptor reportExecutionDescriptor = operationResult.getEntity();
System.out.println(reportExecutionDescriptor.getRequestId());
ReportExecutionDescriptor{currentPage=null, reportURI='/reports/samples/StandardChartsReport', requestId='909127166_1408649034809_24', status='ready', totalPages=1, exports=[ExportDescriptor{id='pdf', status='execution', pages='null', attachmentsPrefix='null', outputResource=null, attachments=null}]}
Could it be that this dependency is broken on the development version.
I get:
Caused by: org.eclipse.aether.transfer.ArtifactNotFoundException: Could not find artifact com.jaspersoft.jasperserver:jasperserver-dto:jar:5.6.0-SNAPSHOT in jaspersoft-clients-snapshots (http://jaspersoft.artifactoryonline.com/jaspersoft/jaspersoft-clients-snapshots)
at org.eclipse.aether.connector.wagon.WagonRepositoryConnector$6.wrap(WagonRepositoryConnector.java:1012)
at org.eclipse.aether.connector.wagon.WagonRepositoryConnector$6.wrap(WagonRepositoryConnector.java:1004)
at org.eclipse.aether.connector.wagon.WagonRepositoryConnector$GetTask.run(WagonRepositoryConnector.java:725)
at org.eclipse.aether.util.concurrency.RunnableErrorForwarder$1.run(RunnableErrorForwarder.java:67)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
I tried to configure it in the settings.xml, in the master pom file of the project and also as a proxied repo on our artifactory server. Three all with no luck.
Any idea?
I am quite a noob sorry. I tried both to use maven and to add the dependencies manually but no luck. The maven snippet supplied to integrate in the project fails and manually finding the dependencies it's a nightmare.
Thanks.
Maybe we should move all DTOs into the single jar file? It would be useful for testing.
Maybe a good idea would be to add a get method on the parameters in the batch adapter
so at least i can build in a lock to evict that a person removes resources where i don't want it..
public MultivaluedMap<String, String> getParams() {
return params;
}
BatchResourcesAdapter request = session.resourcesService().resources();
request.parameter(ResourceSearchParameter.RESOURCE_URI, "/aa/reports/testFolder");
request.parameter(ResourceSearchParameter.RESOURCE_URI, "/bb/reports");
MultivaluedMap<String, String> params = request.getParams();
for (String entry : params.get(ResourceSearchParameter.RESOURCE_URI.getName())) {
if (!entry.contains(Root.INTEGRATION.toString()))
throw new UnsupportedOperationException("You are only allowed to " +
"delete resources in /"+ Root.INTEGRATION.toString());
}
// request.delete();
When I get a report from the server, the images I guess that are immediately removed from the server and therefore not available when you need to use the exported HTML to embed it into a iFrame/Page/Fragment
Would there be anyway to achieve to keep the images?
Thanks
Deploying in WildFly 8.1 (JBoss community AS) fails with
"{"JBAS014671: Failed services" => {"jboss.deployment.unit.\"lending-platform.war\".WeldStartService" =>
"org.jboss.msc.service.StartException in service jboss.deployment.unit.\"lending-platform.war\".WeldStartService: Failed to start service
Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type ServiceLocator with qualifiers @default
at injection point [BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedConstructor] @Inject private org.jvnet.hk2.internal.DynamicConfigurationServiceImpl(ServiceLocator)
at org.jvnet.hk2.internal.DynamicConfigurationServiceImpl.(DynamicConfigurationServiceImpl.java:0)
"}}"
There is a need to add multitenancy support.
api is good but it's synchronous, in real live we need a progress monitor, and cancel button, look at
http://code.jaspersoft.com/svn/repos/jaspersoftstudio/trunk/com.jaspersoft.studio.server/src/com/jaspersoft/studio/server/protocol/restv2/JSSApacheConnector.java
run all with async, and check in a thread if monitor is canceled , cancel the connection
there are many cases when connection block ui (slow connection, over vpn, if server is not available, etc.) user should always have the possibility to stop/cancel connection, for any call
Is there any way to get the server's encryption key with the library?
to be able to reflect all my parameters used in the getResourceDetails method please add also the resource_uri enum to the ResourceServiceParameter class
/**
* Specifies a resource to find.
* Type/Value: String
*/
RESOURCE_URI("resourceUri"),
For more information please follow this link https://jersey.java.net/documentation/latest/async.html#d0e8611 (ยง 10.2. Client API)
We could improve client by adding logging functionality. For example, user can activate two different modes. The first one is without logging. And the second is for logging into the file or console.
There is a need to manually configure entire client or separate requests to work with either type.
long story short, don't mix 2 jersey versions..
(classloader problems, +swagger uses the same versions, + weblogic also uses 1.18.., etc)
instead of
org.glassfish.jersey.core jersey-client 2.5
com.sun.jersey jersey-json 1.18
com.sun.jersey.contribs jersey-multipart 1.17
org.glassfish.jersey.media jersey-media-json-jackson 2.5.1
use 2.13
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${jersey.version}</version>
</dependency>
most of the time you'll need to change the classes of another group id
and change the implementation in the single- and batchjobs adapter:
private String prepareJsonForUpdate(Organization organization){
ObjectMapper mapper = new ObjectMapper();
AnnotationIntrospector introspector = new JaxbAnnotationIntrospector(mapper.getTypeFactory());
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.setAnnotationIntrospector(introspector);
you could add swagger https://github.com/wordnik/swagger-spec
as a rest endpoint to document and test your rest api
then this can be "consumed" by https://github.com/wordnik/swagger-ui
refr: http://swagger.io/
/**
* Filters the results by access events: viewed (by current user) or modified (by
* current user). By default, no access event filter is applied.
*
* Type/Value: viewed|modified
*/
ACCES_TYPE("accessType"),
I'm trying to schedule a job. In the Readme it shows passing a Job to the ScheduleReport Method of the JobService. This wants a JobExtension not a Job.
How do I schedule a job with your library? I'm using a com.jaspersoft.jasperserver.jaxrs.client.dto.jobs.Job.
For example, there is no way to perform copy/move/update with overwrite=true or createFolders=false parameters, whereas the REST API allows it.
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.