--- title: Tutorial - Token Tagging with AdaptNLP keywords: fastai sidebar: home_sidebar summary: "Using EasyTokenTagger to quickly perform POS tagging" description: "Using EasyTokenTagger to quickly perform POS tagging" nb_path: "nbs/05a_tutorial.token_tagging.ipynb" ---
We'll import the adaptnlp
EasyTokenTagger
class:
from adaptnlp import EasyTokenTagger
from pprint import pprint
Let's write some simple example text, and instantiate an EasyTokenTagger
:
example_text = '''Novetta Solutions is the best. Albert Einstein used to be employed at Novetta Solutions.
The Wright brothers loved to visit the JBF headquarters, and they would have a chat with Albert.'''
tagger = EasyTokenTagger()
First we will use some Transformers
models, specifically bert
.
We'll search HuggingFace
for the model we want, in this case we want to use sshleifer
's tiny-dbmdz-bert
model:
from adaptnlp import HFModelHub
hub = HFModelHub()
model = hub.search_model_by_name('sshleifer/tiny-dbmdz-bert', user_uploaded=True)[0]; model
Next we'll use our tagger
to generate some sentences:
sentences = tagger.tag_text(text=example_text, model_name_or_path = model)
type(model)
And then look at some of our results:
print("List string outputs of tags:\n")
for sen in sentences:
pprint(sen)
With Flair we can follow a similar setup to earlier, searching HuggingFace for valid ner
models. In our case we'll use Flair
's ner-english-ontonotes-fast
model
from adaptnlp import FlairModelHub
hub = FlairModelHub()
model = hub.search_model_by_name('ontonotes-fast')[0]; model
Then we'll tag the string:
model.name
tagger.token_taggers[model.name]
sentences = tagger.tag_text(text = example_text, model_name_or_path = model)
And look at our results, either the tagged strings themselves:
print("List string outputs of tags:\n")
for sen in sentences:
print(sen.to_tagged_string())
The entities and their spans:
print("List entities tagged:\n")
for sen in sentences:
for entity in sen.get_spans("ner"):
print(entity)
Or all of the raw tagged information:
print("Get json of tagged information:\n")
for sen in sentences:
pprint(sen.to_dict(tag_type="ner"))
We can simply pass in "pos"
, but let's use our search API to find an english POS tagger:
hub.search_model_by_task('pos')
We'll use the pos-english-fast
model
model = hub.search_model_by_name('pos-english-fast')[0]; model
sentences = tagger.tag_text(text = example_text, model_name_or_path = model)
Then just as before, we can look at our results. Either as a sentence with tags:
print("List string outputs of tags:\n")
for sen in sentences:
print(sen.to_tagged_string())
With a list of tagged entities:
print("List text/entities tagged:\n")
for sen in sentences:
for entity in sen.get_spans("pos"):
print(entity)
Or the raw JSON of information:
print("Get json of tagged information:\n")
for sen in sentences:
pprint(sen.to_dict(tag_type="pos"))
models = hub.search_model_by_task('chunk'); models
We'll use the fast
model again:
model = models[0]; model
sentences = tagger.tag_text(text = example_text, model_name_or_path = model)
Let's view our results.
Tagged string:
print("List string outputs of tags:\n")
for sen in sentences:
print(sen.to_tagged_string())
Tagged entities:
print("List text/entities tagged:\n")
for sen in sentences:
for entity in sen.get_spans("np"):
print(entity)
models = hub.search_model_by_task("frame"); models
Again we will use the "fast" model:
model = models[0]; model
sentences = tagger.tag_text(text = example_text, model_name_or_path = model)
And look at our tagged string:
print("List string outputs of tags:\n")
for sen in sentences:
print(sen.to_tagged_string())
Notice:Pay attention to the "fast" versus regular naming. "fast" models are designed to be extremely efficient on the CPU, and are worth checking out
As different taggers are loaded into memory, we can tag with all of them at once, for example we'll make a new EasyTokenTagger
and load in a ner
and pos
tagger:
tagger = EasyTokenTagger()
_ = tagger.tag_text(text=example_text, model_name_or_path="ner-ontonotes")
_ = tagger.tag_text(text=example_text, model_name_or_path="pos")
Before finally using both at once:
sentences = tagger.tag_all(text=example_text)
And now we can look at the entities tagged of each kind:
print("List entities tagged:\n")
for sen in sentences:
for entity in sen.get_spans("ner"):
print(entity)
print("List entities tagged:\n")
for sen in sentences:
for entity in sen.get_spans("pos"):
print(entity)


Households are accountable for nearly three quarters of global carbon emissions. A carbon footprint is the entire quantity of greenhouse gas emissions produced by a product or service during its manufacture, use, and disposal. It comprises carbon dioxide, the most prevalent gas released by humans, as well as other gases such as methane, fluorinated gases and nitrous oxide, all of which trap heat in the atmosphere and contribute to global warming.
The majority of a person's carbon footprint is usually created by housing, transportation, food, variety of effects on the environment, personal carbon footprint is influenced by how our house is designed and how we live in it.
A household's carbon footprint can be divided into two types. The first are direct emissions from residential energy consumption (for example, gas for space, water heating and electricity for lighting and powering appliances and gadgets). Second, are the embedded emissions. Embedded emissions from supply chains (both domestic and international) account for the majority of Western households' carbon footprints (approximately 60–70%).
A typical U.S. household has a carbon footprint of 48 metric tons CO2e/yr.The average carbon footprint for a person in the United States is 16 tons, one of the highest rates in the world


17-313: Foundations of Software Engineering
Homework 5: Quality Assurance for the People
In this assignment, you will carefully consider and engage in several QA-related processes to evaluate and look for defects in your prototype Mayan-EDMS-based graduate admissions system. The goals of this assignment are:
-
Gain hands-on experience with analysis tools, including setting up, customizing, and using them.
-
Practically assess and compare the costs and benefits of existing static and dynamic bug-finding tools.
-
Develop a plan to integrate and roll out tools in development practice.
-
Explain the predictions of a Machine Learning Model, and reason about their implications.
Project Context and Tasks
Quality Assurance is a critical part of software development. Although you have been testing your new graduate admissions system this whole time, you are now setting out to establish a sustained QA practice that can be used moving forward as you iterate over and continue to improve your system. Your CTO has assigned you the task of evaluating existing tools and practices beyond unit testing, and producing a report on (A) the cost/benefit tradeoffs and risks of several tools and processes and (B) how they might fit in development practice.
Static and Dynamic Analysis
First, you will evaluate and choose between a set of analysis tools, integrate it into your build/deployment pipeline, and document your decisions/process by way of a design document/RFC. For the purposes of this RFC, you must identify and experiment with at least N potential static and dynamic analysis tools that are applicable to your system, where N is the size of your group. We provide a starter list below; you should include at least one static analysis and one dynamic analysis tools, and at least one tool must be taken from either a Google search or from the Awesome Static/Dynamic Analysis page (that is, cannot otherwise be listed in the bulleted list).
You can create a new team repository by following the link for your team, which will clone the Mayan EDMS code automatically:
Create Assignment with Github Classroom
Apply one or more of the tools to your project. You may also apply it to one or more other programs if you wish to assess it in different contexts. Consider and experiment with the types of customization that are appropriate or necessary for this tool, both a priori (before they can be used in your project) and possibly over time. Assess the strengths and weaknesses of each tool/technique, both quantitatively and qualitatively. You might consider issues like, but not limited to: what types of problems are you hoping your tooling will catch? What types of problems does a particular tool catch? What types of customization are possible or necessary? How can/should this tool be integrated into a development process? Are there many false positives? False negatives? True positive reports about things you don’t care about?
The deliverable for this part, at a high level, is a Design Document/RFC that explains and justifies the tooling you propose to incorporate into your process, and how you propose to do so. This decision should be feature- and data-driven, and should consider usability and process questions like how and when the tooling will be applied, and by whom. See below for more details.
NOTE: you do not need to integrate ALL N tools into your repo, but you should integrate at least (1) tool so that it runs via CI, and have one commit on which it was run. You should reference this commit in your design document
Starter list of Tools:
Static Analysis:
-
Pylint, one of the best-known and most widely-used Python static analysis suite, provides a collection of tools, including a linter/style checker, pyreverse (which reverse-engineers UML diagrams), etc.
-
Pyflakes is similar to the core linter in pylint, but with an emphasis on speed and low false positives.
-
Mypy provides static type checking for Python
-
sonarQube is a proprietary product targeting multiple languages, including Python; it has an open-source version you may want to try.
-
Flake8 provides a wrapper around a number of other tools.
Dynamic Analysis:
-
The Python Profilers provides deterministic profiling of Python programs, which will provide you a set of statistics that describes how often and for how long various parts of the program executed.
-
Coverage.py is a tool for measuring code coverage of Python programs.
Others are available. Awesome Static Analysis page/repo and Awesome Dynamic Analysis page/repo have extensive listings of available static and dynamic analysis tools for a pretty hefty list of programming languages, including Python. Other tools target Django specifically; use your Googling skills, and see what you find!
ML Model Assessment
In the last homework assignment, you created a Machine Learning model. In fact, after your success with HW4, your team has started collecing data in production, and the new data for your ML service goes well beyond the data you used for testing. Therefore, your CTO is seriously considering adding it into your product.
However, before announcing it as a feature, she wants to ensure that your team has a deep understanding of how the ML model is working, as well as that it is tested with respect to any concerns that may have surfaced previously.
For this task, your team is tasked with writing a data-driven report for your CTO. You should evaluate the model, test outcomes, present your findings, and discuss them.
Your first task is to present a data-driven analysis of the predictions that your model is making. You will do this using the LIME tool we have previously looked at in class: https://github.com/marcotcr/lime
Run this tool on your model, and collect data on how the model is making predictions. You should use this data to report on the behavior of the ML recommendation system.
Here, when you run the tool, remember to use the more complete production data that your team has collected, in the place of the previous limited training data. You can find the updated data here: Production Data
The data-driven analysis will allow your company to ensure that the ML is working properly. However, you are also concerned with fairness.
You should also include in your report a data-driven analysis of the fairness of your algorithm. To analyze the fairness, you should remember the fairness discussion we had in class, based on this tool: ML Discrimination
Finally, you report should include a recommendation if you want to use the ML, scrap it, or make specific improvements before rolling it out. Specifically your report should include the following information:
-
Data-driven analysis of the predictions the model is making.
-
Any concerns you have about the quality of the predictions in light of this data.
-
Any features in the data you are concerned about from a fairness perspective. HINT: you might want to consult your last homework when considering this.
-
A data-driven analysis of the interplay between these features and your ML model. There are various ways to do this, but a simple approach might consider the following:
-
Distribution of this feature in your dataset.
-
Distribution of this feature in your accepted and rejected recommendation populations
-
Relationship between this feature and your false positives and false negatives.
-
-
Based on this data, you should consider what is the fairness strategy that you are trying to achieve. You may use one of the fairness strategies we considered in class, or define your own. If you define a new fairness strategy, you should describe it, and present why you think it is a better fit than any of the existing strategies for this product.
-
If you are not happy with the performance of the system, based on the data you have collected, you should do the following:
-
Report on what aspects of the system you are unhappy with
-
Iterate your model 1 iteration, and see if you can improve its performance. Most likely, this will NOT be enough to fix it, but your goal in this assignment is to learn enough to make a reasonable estimate of the effort needed to fix the model.
-
Make an estimate of how long it will take to bring the model up to acceptable performance. This can be a “T-Shirt” estimate (e.g., S/M/L/XL) but it should also include completion criteria. This will look like specific thresholds that your model should achieve before you would be comfortable shipping it as a part of your product.
-
-
At the end of this report, make a recommendation to your CTO. This recommendation should be one of the following:
-
It is good enough to use now, we should ship it.
-
It is not good enough to ship, but we have a plan to improve it
-
We don’t feel comfortable shipping this feature, we should scrap it.
-
Deadlines and Deliverables
This homework has one (1) deadline and two (2) deliverables. The deadline (Tuesday, Nov 23rd) is for all the deliverables: the static analysis design doc, and the report on the ML model.
Part A: Static Analysis - Group (due Nov 23) - 100 points (50%)
The deliverable for this part is a Design Document/RFC that provides (1) a justified explanation for which tool(s) you think the project should use moving forward, and (2) how it shall be integrated into your process (you must recommend at least one tool, even if it’s with reservations). This latter point should address both technical (e.g., at what point in the development/deployment process shall it be integrated? What sorts of customization or configuration will you be using?) and social issues (e.g., how will you incentivize the change?), as applicable. The justification should be based on your experiences running the tools and, as much as possible, be grounded in data about, for example, tool usability, output, and customizability.
Be sure the RFC also explains/justifies the alternative tools (or process options, if pertinent) that have been rejected. To receive full credit, you must consider at least N total tool options in your RFC, where N is the size of your team.
The document should also contain other relevant sections for a Design Document/RFC for this type of (development process) feature. Are there open questions? Issues you consider out of scope? Drawbacks of the proposed process/tooling that you are accepting for some (good) reason? Etc. That is: make sure it’s a good/complete design document!
NOTE: in your PDF submitted to gradescope, you should explictly reference at least one commit on which your tool has been run in your repo.
Submit the Design Document as a single PDF to Gradescope.
Part B: ML Explainability – Group (due Nov 23) – 100 points (50%)
For this deliverable, you will be collecting data, and writing a report. The report should include the data you collect as well as your interpretation of the data.
First, you should collect data by running LIME on your ML model from the last homework (use the model you have in the fall-2021-hw4 repository), with the new data. You should present the results of this as data in your report.
Then, you will interpret the data to explain why your machine learning model is making predictions. This information should include the features that provide the most predictive power.
You should also evaluate your machine learning model considering fairness issues. You will evaluate the performance of your model with a specific target fairness strategy in mind, and if you are unhappy with the fairness of the model, you will come up with thresholds that you feel the model must meet before you would feel comfortable using it.
Based on your findings, you should recommend one of three options. You might feel that the Model is good enough to deploy as is, you might recommend specific changes before you deploy, or you might recommend it not be deployed at all.
Submit this report as a PDF via Gradescope.


Content-Type: application/vnd.kafka.v2+json
Use the Strimzi Kafka Bridge to make HTTP requests to a Kafka cluster.
You can use the Kafka Bridge to integrate HTTP client applications with your Kafka cluster.
Install the Strimzi Kafka Bridge to run in the same environment as your Kafka cluster.
You can download and add the Kafka Bridge installation artifacts to your host machine. To try out the Kafka Bridge in your local environment, see the Kafka Bridge quickstart.
If you deployed Strimzi on Kubernetes, you can use the Strimzi Cluster Operator to deploy the Kafka Bridge to the Kubernetes cluster. You’ll need a running Kafka cluster that was deployed by the Cluster Operator in a Kubernetes namespace. You can configure your deployment to access the Kafka Bridge outside the Kubernetes cluster.
Strimzi documentation describes how to deploy the Kafka Bridge with Strimzi
The Kafka Bridge provides a RESTful interface that allows HTTP-based clients to interact with a Kafka cluster. It offers the advantages of a web API connection to Strimzi, without the need for client applications to interpret the Kafka protocol.
The API has two main resources — consumers
and topics
— that are exposed and made accessible through endpoints to interact with consumers and producers in your Kafka cluster. The resources relate only to the Kafka Bridge, not the consumers and producers connected directly to Kafka.
The Kafka Bridge supports HTTP requests to a Kafka cluster, with methods to:
Send messages to a topic.
Retrieve messages from topics.
Retrieve a list of partitions for a topic.
Create and delete consumers.
Subscribe consumers to topics, so that they start receiving messages from those topics.
Retrieve a list of topics that a consumer is subscribed to.
Unsubscribe consumers from topics.
Assign partitions to consumers.
Commit a list of consumer offsets.
Seek on a partition, so that a consumer starts receiving messages from the first or last offset position, or a given offset position.
The methods provide JSON responses and HTTP response code error handling. Messages can be sent in JSON or binary formats.
Clients can produce and consume messages without the requirement to use the native Kafka protocol.
Kafka Bridge APIs use the OpenAPI Specification (OAS). OAS provides a standard framework for describing and implementing HTTP APIs.
The Kafka Bridge OpenAPI specification is in JSON format.
You can find the OpenAPI JSON files in the src/main/resources/
folder of the Kafka Bridge source download files.
The download files are available from the GitHub release page.
You can also use the GET /openapi
method to retrieve the OpenAPI v2 specification in JSON format.
You can configure the following between the Kafka Bridge and your Kafka cluster:
TLS or SASL-based authentication
A TLS-encrypted connection
You configure the Kafka Bridge for authentication through its properties file.
You can also use ACLs in Kafka brokers to restrict the topics that can be consumed and produced using the Kafka Bridge.
Authentication and encryption between HTTP clients and the Kafka Bridge is not supported directly by the Kafka Bridge. Requests sent from clients to the Kafka Bridge are sent without authentication or encryption. Requests must use HTTP rather than HTTPS.
You can combine the Kafka Bridge with the following tools to secure it:
Network policies and firewalls that define which pods can access the Kafka Bridge
Reverse proxies (for example, OAuth 2.0)
API gateways
Specify data formats and HTTP headers to ensure valid requests are submitted to the Kafka Bridge.
API request and response bodies are always encoded as JSON.
When performing consumer operations, POST
requests must provide the following Content-Type
header if there is a non-empty body:
Content-Type: application/vnd.kafka.v2+json
When performing producer operations, POST
requests must provide Content-Type
headers specifying the embedded data format of the messages produced. This can be either json
or binary
.
| Embedded data format | Content-Type header |
|---|---|
JSON |
|
Binary |
|
The embedded data format is set per consumer, as described in the next section.
The Content-Type
must not be set if the POST
request has an empty body.
An empty body can be used to create a consumer with the default values.
The embedded data format is the format of the Kafka messages that are transmitted, over HTTP, from a producer to a consumer using the Kafka Bridge. Two embedded data formats are supported: JSON and binary.
When creating a consumer using the /consumers/groupid
endpoint, the POST
request body must specify an embedded data format of either JSON or binary. This is specified in the format
field, for example:
{
"name": "my-consumer",
"format": "binary", # (1)
# ...
}
A binary embedded data format.
The embedded data format specified when creating a consumer must match the data format of the Kafka messages it will consume.
If you choose to specify a binary embedded data format, subsequent producer requests must provide the binary data in the request body as Base64-encoded strings. For example, when sending messages using the /topics/topicname
endpoint, records.value
must be encoded in Base64:
{
"records": [
{
"key": "my-key",
"value": "ZWR3YXJkdGhldGhyZWVsZWdnZWRjYXQ="
},
]
}
Producer requests must also provide a Content-Type
header that corresponds to the embedded data format, for example, Content-Type: application/vnd.kafka.binary.v2+json
.
When sending messages using the /topics
endpoint, you enter the message payload in the request body, in the records
parameter.
The records
parameter can contain any of these optional fields:
Message headers
Message key
Message value
Destination partition
POST
request to /topicscurl -X POST \
http://localhost:8080/topics/my-topic \
-H 'content-type: application/vnd.kafka.json.v2+json' \
-d '{
"records": [
{
"key": "my-key",
"value": "sales-lead-0001"
"partition": 2
"headers": [
{
"key": "key1",
"value": "QXBhY2hlIEthZmthIGlzIHRoZSBib21iIQ==" (1)
}
]
},
]
}'
The header value in binary format and encoded as Base64.
After creating a consumer, all subsequent GET requests must provide an Accept
header in the following format:
Accept: application/vnd.kafka.EMBEDDED-DATA-FORMAT.v2+json
The EMBEDDED-DATA-FORMAT
is either json
or binary
.
For example, when retrieving records for a subscribed consumer using an embedded data format of JSON, include this Accept header:
Accept: application/vnd.kafka.json.v2+json
Cross-Origin Resource Sharing (CORS) allows you to specify allowed methods and originating URLs for accessing the Kafka cluster in your Kafka Bridge HTTP configuration.
# ...
http.cors.enabled=true
http.cors.allowedOrigins=https://strimzi.io
http.cors.allowedMethods=GET,POST,PUT,DELETE,OPTIONS,PATCH
CORS allows for simple and preflighted requests between origin sources on different domains.
Simple requests are suitable for standard requests using GET
, HEAD
, POST
methods.
A preflighted request sends a HTTP OPTIONS request as an initial check that the actual request is safe to send.
On confirmation, the actual request is sent.
Preflight requests are suitable for methods that require greater safeguards, such as PUT
and DELETE
,
and use non-standard headers.
All requests require an origins value in their header, which is the source of the HTTP request.
For example, this simple request header specifies the origin as https://strimzi.io
.
Origin: https://strimzi.io
The header information is added to the request.
curl -v -X GET HTTP-ADDRESS/bridge-consumer/records \
-H 'Origin: https://strimzi.io'\
-H 'content-type: application/vnd.kafka.v2+json'
In the response from the Kafka Bridge, an Access-Control-Allow-Origin
header is returned.
HTTP/1.1 200 OK
Access-Control-Allow-Origin: * (1)
Returning an asterisk (*
) shows the resource can be accessed by any domain.
An initial preflight request is sent to Kafka Bridge using an OPTIONS
method.
The HTTP OPTIONS request sends header information to check that Kafka Bridge will allow the actual request.
Here the preflight request checks that a POST
request is valid from https://strimzi.io
.
OPTIONS /my-group/instances/my-user/subscription HTTP/1.1
Origin: https://strimzi.io
Access-Control-Request-Method: POST (1)
Access-Control-Request-Headers: Content-Type (2)
Kafka Bridge is alerted that the actual request is a POST
request.
The actual request will be sent with a Content-Type
header.
OPTIONS
is added to the header information of the preflight request.
curl -v -X OPTIONS -H 'Origin: https://strimzi.io' \
-H 'Access-Control-Request-Method: POST' \
-H 'content-type: application/vnd.kafka.v2+json'
Kafka Bridge responds to the initial request to confirm that the request will be accepted. The response header returns allowed origins, methods and headers.
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://strimzi.io
Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS,PATCH
Access-Control-Allow-Headers: content-type
If the origin or method is rejected, an error message is returned.
The actual request does not require Access-Control-Request-Method
header, as it was confirmed in the preflight request,
but it does require the origin header.
curl -v -X POST HTTP-ADDRESS/topics/bridge-topic \
-H 'Origin: https://strimzi.io' \
-H 'content-type: application/vnd.kafka.v2+json'
The response shows the originating URL is allowed.
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://strimzi.io
You can set a different log level for each operation that is defined by the Kafka Bridge OpenAPI specification.
Each operation has a corresponding API endpoint through which the bridge receives requests from HTTP clients. You can change the log level on each endpoint to produce more or less fine-grained logging information about the incoming and outgoing HTTP requests.
Loggers are defined in the log4j.properties
file, which has the following default configuration for healthy
and ready
endpoints:
log4j.logger.http.openapi.operation.healthy=WARN, out
log4j.additivity.http.openapi.operation.healthy=false
log4j.logger.http.openapi.operation.ready=WARN, out
log4j.additivity.http.openapi.operation.ready=false
The log level of all other operations is set to INFO
by default.
Loggers are formatted as follows:
log4j.logger.http.openapi.operation.<operation_id>
Where <operation_id>
is the identifier of the specific operation.
createConsumer
deleteConsumer
subscribe
unsubscribe
poll
assign
commit
send
sendToPartition
seekToBeginning
seekToEnd
seek
healthy
ready
openapi
Use this quickstart to try out the Strimzi Kafka Bridge in your local development environment.
You will learn how to do the following:
Produce messages to topics and partitions in your Kafka cluster
Create a Kafka Bridge consumer
Perform basic consumer operations, such as subscribing the consumer to topics and retrieving the messages that you produced
In this quickstart, HTTP requests are formatted as curl commands that you can copy and paste to your terminal.
Ensure you have the prerequisites and then follow the tasks in the order provided in this chapter.
In this quickstart, you will produce and consume messages in JSON format.
A Kafka cluster is running on the host machine.
A zipped distribution of the Strimzi Kafka Bridge is available for download.
Download the latest version of the Strimzi Kafka Bridge archive from the GitHub release page.
This procedure describes how to configure the Kafka and HTTP connection properties used by the Strimzi Kafka Bridge.
You configure the Kafka Bridge, as any other Kafka client, using appropriate prefixes for Kafka-related properties.
kafka.
for general configuration that applies to producers and consumers, such as server connection and security.
kafka.consumer.
for consumer-specific configuration passed only to the consumer.
kafka.producer.
for producer-specific configuration passed only to the producer.
As well as enabling HTTP access to a Kafka cluster, HTTP properties provide the capability to enable and define access control for the Kafka Bridge through Cross-Origin Resource Sharing (CORS). CORS is a HTTP mechanism that allows browser access to selected resources from more than one origin. To configure CORS, you define a list of allowed resource origins and HTTP methods to access them. Additional HTTP headers in requests describe the CORS origins that are permitted access to the Kafka cluster.
Edit the application.properties
file provided with the Strimzi Kafka Bridge installation archive.
Use the properties file to specify Kafka and HTTP-related properties, and to enable distributed tracing.
Configure standard Kafka-related properties, including properties specific to the Kafka consumers and producers.
Use:
kafka.bootstrap.servers
to define the host/port connections to the Kafka cluster
kafka.producer.acks
to provide acknowledgments to the HTTP client
kafka.consumer.auto.offset.reset
to determine how to manage reset of the offset in Kafka
For more information on configuration of Kafka properties, see the Apache Kafka website
Configure HTTP-related properties to enable HTTP access to the Kafka cluster.
For example:
bridge.id=my-bridge
http.enabled=true
http.host=<IP_ADDRESS>
http.port=8080 (1)
http.cors.enabled=true (2)
http.cors.allowedOrigins=https://strimzi.io (3)
http.cors.allowedMethods=GET,POST,PUT,DELETE,OPTIONS,PATCH (4)
The default HTTP configuration for the Kafka Bridge to listen on port 8080.
Set to true
to enable CORS.
Comma-separated list of allowed CORS origins. You can use a URL or a Java regular expression.
Comma-separated list of allowed HTTP methods for CORS.
Follow this procedure to install the Strimzi Kafka Bridge.
If you have not already done so, unzip the Kafka Bridge installation archive to any directory.
Run the Kafka Bridge script using the configuration properties as a parameter:
For example:
./bin/kafka_bridge_run.sh --config-file=<path>/configfile.properties
Check to see that the installation was successful in the log.
HTTP-Kafka Bridge started and listening on port 8080
HTTP-Kafka Bridge bootstrap servers localhost:9092
Use the Kafka Bridge to produce messages to a Kafka topic in JSON format by using the topics endpoint.
You can produce messages to topics in JSON format by using the topics endpoint. You can specify destination partitions for messages in the request body. The partitions endpoint provides an alternative method for specifying a single destination partition for all messages as a path parameter.
In this procedure, messages are produced to a topic called bridge-quickstart-topic
.
The Kafka cluster has a topic with three partitions.
You can use the kafka-topics.sh
utility to create topics.
bin/kafka-topics.sh --bootstrap-server localhost:9092 --create --topic bridge-quickstart-topic --partitions 3 --replication-factor 1
bin/kafka-topics.sh --bootstrap-server localhost:9092 --describe --topic bridge-quickstart-topic
|
Note
|
If you deployed Strimzi on Kubernetes, you can create a topic using the KafkaTopic custom resource.
|
Using the Kafka Bridge, produce three messages to the topic you created:
curl -X POST \
http://localhost:8080/topics/bridge-quickstart-topic \
-H 'content-type: application/vnd.kafka.json.v2+json' \
-d '{
"records": [
{
"key": "my-key",
"value": "sales-lead-0001"
},
{
"value": "sales-lead-0002",
"partition": 2
},
{
"value": "sales-lead-0003"
}
]
}'
sales-lead-0001
is sent to a partition based on the hash of the key.
sales-lead-0002
is sent directly to partition 2.
sales-lead-0003
is sent to a partition in the bridge-quickstart-topic
topic using a round-robin method.
If the request is successful, the Kafka Bridge returns an offsets
array, along with a 200
code and a content-type
header of application/vnd.kafka.v2+json
. For each message, the offsets
array describes:
The partition that the message was sent to
The current message offset of the partition
#...
{
"offsets":[
{
"partition":0,
"offset":0
},
{
"partition":2,
"offset":0
},
{
"partition":0,
"offset":1
}
]
}
Make other curl requests to find information on topics and partitions.
curl -X GET \
http://localhost:8080/topics
[
"__strimzi_store_topic",
"__strimzi-topic-operator-kstreams-topic-store-changelog",
"bridge-quickstart-topic",
"my-topic"
]
curl -X GET \
http://localhost:8080/topics/bridge-quickstart-topic
{
"name": "bridge-quickstart-topic",
"configs": {
"compression.type": "producer",
"leader.replication.throttled.replicas": "",
"min.insync.replicas": "1",
"message.downconversion.enable": "true",
"segment.jitter.ms": "0",
"cleanup.policy": "delete",
"flush.ms": "9223372036854775807",
"follower.replication.throttled.replicas": "",
"segment.bytes": "1073741824",
"retention.ms": "604800000",
"flush.messages": "9223372036854775807",
"message.format.version": "2.8-IV1",
"max.compaction.lag.ms": "9223372036854775807",
"file.delete.delay.ms": "60000",
"max.message.bytes": "1048588",
"min.compaction.lag.ms": "0",
"message.timestamp.type": "CreateTime",
"preallocate": "false",
"index.interval.bytes": "4096",
"min.cleanable.dirty.ratio": "0.5",
"unclean.leader.election.enable": "false",
"retention.bytes": "-1",
"delete.retention.ms": "86400000",
"segment.ms": "604800000",
"message.timestamp.difference.max.ms": "9223372036854775807",
"segment.index.bytes": "10485760"
},
"partitions": [
{
"partition": 0,
"leader": 0,
"replicas": [
{
"broker": 0,
"leader": true,
"in_sync": true
},
{
"broker": 1,
"leader": false,
"in_sync": true
},
{
"broker": 2,
"leader": false,
"in_sync": true
}
]
},
{
"partition": 1,
"leader": 2,
"replicas": [
{
"broker": 2,
"leader": true,
"in_sync": true
},
{
"broker": 0,
"leader": false,
"in_sync": true
},
{
"broker": 1,
"leader": false,
"in_sync": true
}
]
},
{
"partition": 2,
"leader": 1,
"replicas": [
{
"broker": 1,
"leader": true,
"in_sync": true
},
{
"broker": 2,
"leader": false,
"in_sync": true
},
{
"broker": 0,
"leader": false,
"in_sync": true
}
]
}
]
}
curl -X GET \
http://localhost:8080/topics/bridge-quickstart-topic/partitions
[
{
"partition": 0,
"leader": 0,
"replicas": [
{
"broker": 0,
"leader": true,
"in_sync": true
},
{
"broker": 1,
"leader": false,
"in_sync": true
},
{
"broker": 2,
"leader": false,
"in_sync": true
}
]
},
{
"partition": 1,
"leader": 2,
"replicas": [
{
"broker": 2,
"leader": true,
"in_sync": true
},
{
"broker": 0,
"leader": false,
"in_sync": true
},
{
"broker": 1,
"leader": false,
"in_sync": true
}
]
},
{
"partition": 2,
"leader": 1,
"replicas": [
{
"broker": 1,
"leader": true,
"in_sync": true
},
{
"broker": 2,
"leader": false,
"in_sync": true
},
{
"broker": 0,
"leader": false,
"in_sync": true
}
]
}
]
curl -X GET \
http://localhost:8080/topics/bridge-quickstart-topic/partitions/0
{
"partition": 0,
"leader": 0,
"replicas": [
{
"broker": 0,
"leader": true,
"in_sync": true
},
{
"broker": 1,
"leader": false,
"in_sync": true
},
{
"broker": 2,
"leader": false,
"in_sync": true
}
]
}
curl -X GET \
http://localhost:8080/topics/bridge-quickstart-topic/partitions/0/offsets
{
"beginning_offset": 0,
"end_offset": 1
}
After producing messages to topics and partitions, create a Kafka Bridge consumer.
Before you can perform any consumer operations in the Kafka cluster, you must first create a consumer by using the consumers endpoint. The consumer is referred to as a Kafka Bridge consumer.
Create a Kafka Bridge consumer in a new consumer group named bridge-quickstart-consumer-group
:
curl -X POST http://localhost:8080/consumers/bridge-quickstart-consumer-group \
-H 'content-type: application/vnd.kafka.v2+json' \
-d '{
"name": "bridge-quickstart-consumer",
"auto.offset.reset": "earliest",
"format": "json",
"enable.auto.commit": false,
"fetch.min.bytes": 512,
"consumer.request.timeout.ms": 30000
}'
The consumer is named bridge-quickstart-consumer
and the embedded data format is set as json
.
Some basic configuration settings are defined.
The consumer will not commit offsets to the log automatically because the enable.auto.commit
setting is false
. You will commit the offsets manually later in this quickstart.
If the request is successful, the Kafka Bridge returns the consumer ID (instance_id
) and base URL (base_uri
) in the response body, along with a 200
code.
#...
{
"instance_id": "bridge-quickstart-consumer",
"base_uri":"http://<bridge_id>-bridge-service:8080/consumers/bridge-quickstart-consumer-group/instances/bridge-quickstart-consumer"
}
Copy the base URL (base_uri
) to use in the other consumer operations in this quickstart.
Now that you have created a Kafka Bridge consumer, you can subscribe it to topics.
After you have created a Kafka Bridge consumer, subscribe it to one or more topics by using the subscription endpoint. When subscribed, the consumer starts receiving all messages that are produced to the topic.
Subscribe the consumer to the bridge-quickstart-topic
topic that you created earlier, in Producing messages to topics and partitions:
curl -X POST http://localhost:8080/consumers/bridge-quickstart-consumer-group/instances/bridge-quickstart-consumer/subscription \
-H 'content-type: application/vnd.kafka.v2+json' \
-d '{
"topics": [
"bridge-quickstart-topic"
]
}'
The topics
array can contain a single topic (as shown here) or multiple topics. If you want to subscribe the consumer to multiple topics that match a regular expression, you can use the topic_pattern
string instead of the topics
array.
If the request is successful, the Kafka Bridge returns a 204
(No Content) code only.
After subscribing a Kafka Bridge consumer to topics, you can retrieve messages from the consumer.
Retrieve the latest messages from the Kafka Bridge consumer by requesting data from the records endpoint. In production, HTTP clients can call this endpoint repeatedly (in a loop).
Produce additional messages to the Kafka Bridge consumer, as described in Producing messages to topics and partitions.
Submit a GET
request to the records
endpoint:
curl -X GET http://localhost:8080/consumers/bridge-quickstart-consumer-group/instances/bridge-quickstart-consumer/records \
-H 'accept: application/vnd.kafka.json.v2+json'
After creating and subscribing to a Kafka Bridge consumer, a first GET request will return an empty response because the poll operation starts a rebalancing process to assign partitions.
Repeat step two to retrieve messages from the Kafka Bridge consumer.
The Kafka Bridge returns an array of messages — describing the topic name, key, value, partition, and offset — in the response body, along with a 200
code. Messages are retrieved from the latest offset by default.
HTTP/1.1 200 OK
content-type: application/vnd.kafka.json.v2+json
#...
[
{
"topic":"bridge-quickstart-topic",
"key":"my-key",
"value":"sales-lead-0001",
"partition":0,
"offset":0
},
{
"topic":"bridge-quickstart-topic",
"key":null,
"value":"sales-lead-0003",
"partition":0,
"offset":1
},
#...
|
Note
|
If an empty response is returned, produce more records to the consumer as described in Producing messages to topics and partitions, and then try retrieving messages again. |
After retrieving messages from a Kafka Bridge consumer, try committing offsets to the log.
Use the offsets endpoint to manually commit offsets to the log for all messages received by the Kafka Bridge consumer. This is required because the Kafka Bridge consumer that you created earlier, in Creating a Kafka Bridge consumer, was configured with the enable.auto.commit
setting as false
.
Commit offsets to the log for the bridge-quickstart-consumer
:
curl -X POST http://localhost:8080/consumers/bridge-quickstart-consumer-group/instances/bridge-quickstart-consumer/offsets
Because no request body is submitted, offsets are committed for all the records that have been received by the consumer. Alternatively, the request body can contain an array (OffsetCommitSeekList) that specifies the topics and partitions that you want to commit offsets for.
If the request is successful, the Kafka Bridge returns a 204
code only.
After committing offsets to the log, try out the endpoints for seeking to offsets.
Use the positions endpoints to configure the Kafka Bridge consumer to retrieve messages for a partition from a specific offset, and then from the latest offset. This is referred to in Apache Kafka as a seek operation.
Seek to a specific offset for partition 0 of the quickstart-bridge-topic
topic:
curl -X POST http://localhost:8080/consumers/bridge-quickstart-consumer-group/instances/bridge-quickstart-consumer/positions \
-H 'content-type: application/vnd.kafka.v2+json' \
-d '{
"offsets": [
{
"topic": "bridge-quickstart-topic",
"partition": 0,
"offset": 2
}
]
}'
If the request is successful, the Kafka Bridge returns a 204
code only.
Submit a GET
request to the records
endpoint:
curl -X GET http://localhost:8080/consumers/bridge-quickstart-consumer-group/instances/bridge-quickstart-consumer/records \
-H 'accept: application/vnd.kafka.json.v2+json'
The Kafka Bridge returns messages from the offset that you seeked to.
Restore the default message retrieval behavior by seeking to the last offset for the same partition. This time, use the positions/end endpoint.
curl -X POST http://localhost:8080/consumers/bridge-quickstart-consumer-group/instances/bridge-quickstart-consumer/positions/end \
-H 'content-type: application/vnd.kafka.v2+json' \
-d '{
"partitions": [
{
"topic": "bridge-quickstart-topic",
"partition": 0
}
]
}'
If the request is successful, the Kafka Bridge returns another 204
code.
|
Note
|
You can also use the positions/beginning endpoint to seek to the first offset for one or more partitions. |
In this quickstart, you have used the Strimzi Kafka Bridge to perform several common operations on a Kafka cluster. You can now delete the Kafka Bridge consumer that you created earlier.
Delete the Kafka Bridge consumer that you used throughout this quickstart.
Delete the Kafka Bridge consumer by sending a DELETE
request to the instances endpoint.
curl -X DELETE http://localhost:8080/consumers/bridge-quickstart-consumer-group/instances/bridge-quickstart-consumer
If the request is successful, the Kafka Bridge returns a 204
code.
The Strimzi Kafka Bridge provides a REST API for integrating HTTP based client applications with a Kafka cluster. You can use the API to create and manage consumers and send and receive records over HTTP rather than the native Kafka protocol.
Version : 0.1.0
Consumers : Consumer operations to create consumers in your Kafka cluster and perform common actions, such as subscribing to topics, retrieving processed records, and committing offsets.
Producer : Producer operations to send records to a specified topic or topic partition.
Seek : Seek operations that enable a consumer to begin receiving messages from a given offset position.
Topics : Topic operations to send messages to a specified topic or topic partition, optionally including message keys in requests. You can also retrieve topics and topic metadata.
application/json
application/json
Type : < string, < integer (int32) > array > map
Information about Kafka Bridge instance.
| Name | Schema |
|---|---|
bridge_version |
string |
| Name | Description | Schema |
|---|---|---|
auto.offset.reset |
Resets the offset position for the consumer. If set to |
string |
consumer.request.timeout.ms |
Sets the maximum amount of time, in milliseconds, for the consumer to wait for messages for a request. If the timeout period is reached without a response, an error is returned. Default is |
integer |
enable.auto.commit |
If set to |
boolean |
fetch.min.bytes |
Sets the minimum amount of data, in bytes, for the consumer to receive. The broker waits until the data to send exceeds this amount. Default is |
integer |
format |
The allowable message format for the consumer, which can be |
string |
isolation.level |
If set to |
string |
name |
The unique name for the consumer instance. The name is unique within the scope of the consumer group. The name is used in URLs. If a name is not specified, a randomly generated name is assigned. |
string |
| Name | Schema |
|---|---|
headers |
|
key |
string |
offset |
integer (int64) |
partition |
integer (int32) |
topic |
string |
value |
string |
Type : < ConsumerRecord > array
| Name | Description | Schema |
|---|---|---|
base_uri |
Base URI used to construct URIs for subsequent requests against this consumer instance. |
string |
instance_id |
Unique ID for the consumer instance in the group. |
string |
| Name | Schema |
|---|---|
error_code |
integer (int32) |
message |
string |
| Name | Description | Schema |
|---|---|---|
key |
string |
|
value |
The header value in binary format, base64-encoded |
string (byte) |
Type : < KafkaHeader > array
| Name | Schema |
|---|---|
offset |
integer (int64) |
partition |
integer (int32) |
topic |
string |
| Name | Schema |
|---|---|
offsets |
< OffsetCommitSeek > array |
| Name | Schema |
|---|---|
offset |
integer (int64) |
partition |
integer (int32) |
| Name | Schema |
|---|---|
offsets |
< OffsetRecordSent > array |
| Name | Schema |
|---|---|
beginning_offset |
integer (int64) |
end_offset |
integer (int64) |
| Name | Schema |
|---|---|
partition |
integer (int32) |
topic |
string |
| Name | Schema |
|---|---|
leader |
integer (int32) |
partition |
integer (int32) |
replicas |
< Replica > array |
| Name | Schema |
|---|---|
partitions |
< Partition > array |
| Name | Schema |
|---|---|
headers |
|
partition |
integer (int32) |
| Name | Schema |
|---|---|
records |
< ProducerRecord > array |
Type : object
| Name | Schema |
|---|---|
records |
< ProducerRecordToPartition > array |
| Name | Schema |
|---|---|
broker |
integer (int32) |
in_sync |
boolean |
leader |
boolean |
| Name | Schema |
|---|---|
partitions |
< AssignedTopicPartitions > array |
topics |
| Name | Description | Schema |
|---|---|---|
configs |
Per-topic configuration overrides |
< string, string > map |
name |
Name of the topic |
string |
partitions |
< PartitionMetadata > array |
| Name | Description | Schema |
|---|---|---|
topic_pattern |
A regex topic pattern for matching multiple topics |
string |
topics |
< string > array |
Retrieves information about the Kafka Bridge instance, in JSON format.
| HTTP Code | Description | Schema |
|---|---|---|
200 |
Information about Kafka Bridge instance. |
application/json
{
"bridge_version" : "0.16.0"
}
Creates a consumer instance in the given consumer group. You can optionally specify a consumer name and supported configuration options. It returns a base URI which must be used to construct URLs for subsequent requests against this consumer instance.
| Type | Name | Description | Schema |
|---|---|---|---|
Path |
groupid |
ID of the consumer group in which to create the consumer. |
string |
Body |
body |
Name and configuration of the consumer. The name is unique within the scope of the consumer group. If a name is not specified, a randomly generated name is assigned. All parameters are optional. The supported configuration options are shown in the following example. |
| HTTP Code | Description | Schema |
|---|---|---|
200 |
Consumer created successfully. |
|
409 |
A consumer instance with the specified name already exists in the Kafka Bridge. |
|
422 |
One or more consumer configuration options have invalid values. |
application/vnd.kafka.v2+json
application/vnd.kafka.v2+json
Consumers
{
"name" : "consumer1",
"format" : "binary",
"auto.offset.reset" : "earliest",
"enable.auto.commit" : false,
"fetch.min.bytes" : 512,
"consumer.request.timeout.ms" : 30000,
"isolation.level" : "read_committed"
}
{
"instance_id" : "consumer1",
"base_uri" : "http://localhost:8080/consumers/my-group/instances/consumer1"
}
{
"error_code" : 409,
"message" : "A consumer instance with the specified name already exists in the Kafka Bridge."
}
{
"error_code" : 422,
"message" : "One or more consumer configuration options have invalid values."
}
Deletes a specified consumer instance. The request for this operation MUST use the base URL (including the host and port) returned in the response from the POST
request to /consumers/{groupid}
that was used to create this consumer.
| Type | Name | Description | Schema |
|---|---|---|---|
Path |
groupid |
ID of the consumer group to which the consumer belongs. |
string |
Path |
name |
Name of the consumer to delete. |
string |
| HTTP Code | Description | Schema |
|---|---|---|
204 |
Consumer removed successfully. |
No Content |
404 |
The specified consumer instance was not found. |
application/vnd.kafka.v2+json
application/vnd.kafka.v2+json
Consumers
{
"error_code" : 404,
"message" : "The specified consumer instance was not found."
}
Assigns one or more topic partitions to a consumer.
| Type | Name | Description | Schema |
|---|---|---|---|
Path |
groupid |
ID of the consumer group to which the consumer belongs. |
string |
Path |
name |
Name of the consumer to assign topic partitions to. |
string |
Body |
body |
List of topic partitions to assign to the consumer. |
| HTTP Code | Description | Schema |
|---|---|---|
204 |
Partitions assigned successfully. |
No Content |
404 |
The specified consumer instance was not found. |
|
409 |
Subscriptions to topics, partitions, and patterns are mutually exclusive. |
application/vnd.kafka.v2+json
application/vnd.kafka.v2+json
Consumers
{
"partitions" : [ {
"topic" : "topic",
"partition" : 0
}, {
"topic" : "topic",
"partition" : 1
} ]
}
{
"error_code" : 404,
"message" : "The specified consumer instance was not found."
}
{
"error_code" : 409,
"message" : "Subscriptions to topics, partitions, and patterns are mutually exclusive."
}
Commits a list of consumer offsets. To commit offsets for all records fetched by the consumer, leave the request body empty.
| Type | Name | Description | Schema |
|---|---|---|---|
Path |
groupid |
ID of the consumer group to which the consumer belongs. |
string |
Path |
name |
Name of the consumer. |
string |
Body |
body |
List of consumer offsets to commit to the consumer offsets commit log. You can specify one or more topic partitions to commit offsets for. |
| HTTP Code | Description | Schema |
|---|---|---|
204 |
Commit made successfully. |
No Content |
404 |
The specified consumer instance was not found. |
application/vnd.kafka.v2+json
application/vnd.kafka.v2+json
Consumers
{
"offsets" : [ {
"topic" : "topic",
"partition" : 0,
"offset" : 15
}, {
"topic" : "topic",
"partition" : 1,
"offset" : 42
} ]
}
{
"error_code" : 404,
"message" : "The specified consumer instance was not found."
}
Configures a subscribed consumer to fetch offsets from a particular offset the next time it fetches a set of records from a given topic partition. This overrides the default fetch behavior for consumers. You can specify one or more topic partitions.
| Type | Name | Description | Schema |
|---|---|---|---|
Path |
groupid |
ID of the consumer group to which the consumer belongs. |
string |
Path |
name |
Name of the subscribed consumer. |
string |
Body |
body |
List of partition offsets from which the subscribed consumer will next fetch records. |
| HTTP Code | Description | Schema |
|---|---|---|
204 |
Seek performed successfully. |
No Content |
404 |
The specified consumer instance was not found, or the specified consumer instance did not have one of the specified partitions assigned. |
application/vnd.kafka.v2+json
application/vnd.kafka.v2+json
Consumers
Seek
{
"offsets" : [ {
"topic" : "topic",
"partition" : 0,
"offset" : 15
}, {
"topic" : "topic",
"partition" : 1,
"offset" : 42
} ]
}
{
"error_code" : 404,
"message" : "The specified consumer instance was not found."
}
Configures a subscribed consumer to seek (and subsequently read from) the first offset in one or more given topic partitions.
| Type | Name | Description | Schema |
|---|---|---|---|
Path |
groupid |
ID of the consumer group to which the subscribed consumer belongs. |
string |
Path |
name |
Name of the subscribed consumer. |
string |
Body |
body |
List of topic partitions to which the consumer is subscribed. The consumer will seek the first offset in the specified partitions. |
| HTTP Code | Description | Schema |
|---|---|---|
204 |
Seek to the beginning performed successfully. |
No Content |
404 |
The specified consumer instance was not found, or the specified consumer instance did not have one of the specified partitions assigned. |
application/vnd.kafka.v2+json
application/vnd.kafka.v2+json
Consumers
Seek
{
"partitions" : [ {
"topic" : "topic",
"partition" : 0
}, {
"topic" : "topic",
"partition" : 1
} ]
}
{
"error_code" : 404,
"message" : "The specified consumer instance was not found."
}
Configures a subscribed consumer to seek (and subsequently read from) the offset at the end of one or more of the given topic partitions.
| Type | Name | Description | Schema |
|---|---|---|---|
Path |
groupid |
ID of the consumer group to which the subscribed consumer belongs. |
string |
Path |
name |
Name of the subscribed consumer. |
string |
Body |
body |
List of topic partitions to which the consumer is subscribed. The consumer will seek the last offset in the specified partitions. |
| HTTP Code | Description | Schema |
|---|---|---|
204 |
Seek to the end performed successfully. |
No Content |
404 |
The specified consumer instance was not found, or the specified consumer instance did not have one of the specified partitions assigned. |
application/vnd.kafka.v2+json
application/vnd.kafka.v2+json
Consumers
Seek
{
"partitions" : [ {
"topic" : "topic",
"partition" : 0
}, {
"topic" : "topic",
"partition" : 1
} ]
}
{
"error_code" : 404,
"message" : "The specified consumer instance was not found."
}
Retrieves records for a subscribed consumer, including message values, topics, and partitions. The request for this operation MUST use the base URL (including the host and port) returned in the response from the POST
request to /consumers/{groupid}
that was used to create this consumer.
| Type | Name | Description | Schema |
|---|---|---|---|
Path |
groupid |
ID of the consumer group to which the subscribed consumer belongs. |
string |
Path |
name |
Name of the subscribed consumer to retrieve records from. |
string |
Query |
max_bytes |
The maximum size, in bytes, of unencoded keys and values that can be included in the response. Otherwise, an error response with code 422 is returned. |
integer |
Query |
timeout |
The maximum amount of time, in milliseconds, that the HTTP Bridge spends retrieving records before timing out the request. |
integer |
| HTTP Code | Description | Schema |
|---|---|---|
200 |
Poll request executed successfully. |
|
404 |
The specified consumer instance was not found. |
|
406 |
The |
|
422 |
Response exceeds the maximum number of bytes the consumer can receive |
application/vnd.kafka.json.v2+json
application/vnd.kafka.binary.v2+json
application/vnd.kafka.v2+json
Consumers
[ {
"topic" : "topic",
"key" : "key1",
"value" : {
"foo" : "bar"
},
"partition" : 0,
"offset" : 2
}, {
"topic" : "topic",
"key" : "key2",
"value" : [ "foo2", "bar2" ],
"partition" : 1,
"offset" : 3
} ]
[
{
"topic": "test",
"key": "a2V5",
"value": "Y29uZmx1ZW50",
"partition": 1,
"offset": 100,
},
{
"topic": "test",
"key": "a2V5",
"value": "a2Fma2E=",
"partition": 2,
"offset": 101,
}
]
{
"error_code" : 404,
"message" : "The specified consumer instance was not found."
}
{
"error_code" : 406,
"message" : "The `format` used in the consumer creation request does not match the embedded format in the Accept header of this request."
}
{
"error_code" : 422,
"message" : "Response exceeds the maximum number of bytes the consumer can receive"
}
Subscribes a consumer to one or more topics. You can describe the topics to which the consumer will subscribe in a list (of Topics
type) or as a topic_pattern
field. Each call replaces the subscriptions for the subscriber.
| Type | Name | Description | Schema |
|---|---|---|---|
Path |
groupid |
ID of the consumer group to which the subscribed consumer belongs. |
string |
Path |
name |
Name of the consumer to subscribe to topics. |
string |
Body |
body |
List of topics to which the consumer will subscribe. |
| HTTP Code | Description | Schema |
|---|---|---|
204 |
Consumer subscribed successfully. |
No Content |
404 |
The specified consumer instance was not found. |
|
409 |
Subscriptions to topics, partitions, and patterns are mutually exclusive. |
|
422 |
A list (of |
application/vnd.kafka.v2+json
application/vnd.kafka.v2+json
Consumers
{
"topics" : [ "topic1", "topic2" ]
}
{
"error_code" : 404,
"message" : "The specified consumer instance was not found."
}
{
"error_code" : 409,
"message" : "Subscriptions to topics, partitions, and patterns are mutually exclusive."
}
{
"error_code" : 422,
"message" : "A list (of Topics type) or a topic_pattern must be specified."
}
Retrieves a list of the topics to which the consumer is subscribed.
| Type | Name | Description | Schema |
|---|---|---|---|
Path |
groupid |
ID of the consumer group to which the subscribed consumer belongs. |
string |
Path |
name |
Name of the subscribed consumer. |
string |
| HTTP Code | Description | Schema |
|---|---|---|
200 |
List of subscribed topics and partitions. |
|
404 |
The specified consumer instance was not found. |
application/vnd.kafka.v2+json
Consumers
{
"topics" : [ "my-topic1", "my-topic2" ],
"partitions" : [ {
"my-topic1" : [ 1, 2, 3 ]
}, {
"my-topic2" : [ 1 ]
} ]
}
{
"error_code" : 404,
"message" : "The specified consumer instance was not found."
}
Unsubscribes a consumer from all topics.
| Type | Name | Description | Schema |
|---|---|---|---|
Path |
groupid |
ID of the consumer group to which the subscribed consumer belongs. |
string |
Path |
name |
Name of the consumer to unsubscribe from topics. |
string |
| HTTP Code | Description | Schema |
|---|---|---|
204 |
Consumer unsubscribed successfully. |
No Content |
404 |
The specified consumer instance was not found. |
Consumers
{
"error_code" : 404,
"message" : "The specified consumer instance was not found."
}
Check if the bridge is running. This does not necessarily imply that it is ready to accept requests.
| HTTP Code | Description | Schema |
|---|---|---|
200 |
The bridge is healthy |
No Content |
Retrieves the OpenAPI v2 specification in JSON format.
| HTTP Code | Description | Schema |
|---|---|---|
200 |
OpenAPI v2 specification in JSON format retrieved successfully. |
string |
application/json
Check if the bridge is ready and can accept requests.
| HTTP Code | Description | Schema |
|---|---|---|
200 |
The bridge is ready |
No Content |
Retrieves a list of all topics.
| HTTP Code | Description | Schema |
|---|---|---|
200 |
List of topics. |
< string > array |
application/vnd.kafka.v2+json
Topics
[ "topic1", "topic2" ]
Sends one or more records to a given topic, optionally specifying a partition, key, or both.
| Type | Name | Description | Schema |
|---|---|---|---|
Path |
topicname |
Name of the topic to send records to or retrieve metadata from. |
string |
Query |
async |
Whether to return immediately upon sending records, instead of waiting for metadata. No offsets will be returned if specified. Defaults to false. |
boolean |
Body |
body |
| HTTP Code | Description | Schema |
|---|---|---|
200 |
Records sent successfully. |
|
404 |
The specified topic was not found. |
|
422 |
The record list is not valid. |
application/vnd.kafka.json.v2+json
application/vnd.kafka.binary.v2+json
application/vnd.kafka.v2+json
Producer
Topics
{
"records" : [ {
"key" : "key1",
"value" : "value1"
}, {
"value" : "value2",
"partition" : 1
}, {
"value" : "value3"
} ]
}
{
"offsets" : [ {
"partition" : 2,
"offset" : 0
}, {
"partition" : 1,
"offset" : 1
}, {
"partition" : 2,
"offset" : 2
} ]
}
{
"error_code" : 404,
"message" : "The specified topic was not found."
}
{
"error_code" : 422,
"message" : "The record list contains invalid records."
}
Retrieves the metadata about a given topic.
| Type | Name | Description | Schema |
|---|---|---|---|
Path |
topicname |
Name of the topic to send records to or retrieve metadata from. |
string |
| HTTP Code | Description | Schema |
|---|---|---|
200 |
Topic metadata |
application/vnd.kafka.v2+json
Topics
{
"name" : "topic",
"offset" : 2,
"configs" : {
"cleanup.policy" : "compact"
},
"partitions" : [ {
"partition" : 1,
"leader" : 1,
"replicas" : [ {
"broker" : 1,
"leader" : true,
"in_sync" : true
}, {
"broker" : 2,
"leader" : false,
"in_sync" : true
} ]
}, {
"partition" : 2,
"leader" : 2,
"replicas" : [ {
"broker" : 1,
"leader" : false,
"in_sync" : true
}, {
"broker" : 2,
"leader" : true,
"in_sync" : true
} ]
} ]
}
Retrieves a list of partitions for the topic.
| Type | Name | Description | Schema |
|---|---|---|---|
Path |
topicname |
Name of the topic to send records to or retrieve metadata from. |
string |
| HTTP Code | Description | Schema |
|---|---|---|
200 |
List of partitions |
< PartitionMetadata > array |
404 |
The specified topic was not found. |
application/vnd.kafka.v2+json
Topics
[ {
"partition" : 1,
"leader" : 1,
"replicas" : [ {
"broker" : 1,
"leader" : true,
"in_sync" : true
}, {
"broker" : 2,
"leader" : false,
"in_sync" : true
} ]
}, {
"partition" : 2,
"leader" : 2,
"replicas" : [ {
"broker" : 1,
"leader" : false,
"in_sync" : true
}, {
"broker" : 2,
"leader" : true,
"in_sync" : true
} ]
} ]
{
"error_code" : 404,
"message" : "The specified topic was not found."
}
Sends one or more records to a given topic partition, optionally specifying a key.
| Type | Name | Description | Schema |
|---|---|---|---|
Path |
partitionid |
ID of the partition to send records to or retrieve metadata from. |
integer |
Path |
topicname |
Name of the topic to send records to or retrieve metadata from. |
string |
Body |
body |
List of records to send to a given topic partition, including a value (required) and a key (optional). |
| HTTP Code | Description | Schema |
|---|---|---|
200 |
Records sent successfully. |
|
404 |
The specified topic partition was not found. |
|
422 |
The record is not valid. |
application/vnd.kafka.json.v2+json
application/vnd.kafka.binary.v2+json
application/vnd.kafka.v2+json
Producer
Topics
{
"records" : [ {
"key" : "key1",
"value" : "value1"
}, {
"value" : "value2"
} ]
}
{
"offsets" : [ {
"partition" : 2,
"offset" : 0
}, {
"partition" : 1,
"offset" : 1
}, {
"partition" : 2,
"offset" : 2
} ]
}
{
"error_code" : 404,
"message" : "The specified topic partition was not found."
}
{
"error_code" : 422,
"message" : "The record is not valid."
}
Retrieves partition metadata for the topic partition.
| Type | Name | Description | Schema |
|---|---|---|---|
Path |
partitionid |
ID of the partition to send records to or retrieve metadata from. |
integer |
Path |
topicname |
Name of the topic to send records to or retrieve metadata from. |
string |
| HTTP Code | Description | Schema |
|---|---|---|
200 |
Partition metadata |
|
404 |
The specified topic partition was not found. |
application/vnd.kafka.v2+json
Topics
{
"partition" : 1,
"leader" : 1,
"replicas" : [ {
"broker" : 1,
"leader" : true,
"in_sync" : true
}, {
"broker" : 2,
"leader" : false,
"in_sync" : true
} ]
}
{
"error_code" : 404,
"message" : "The specified topic partition was not found."
}
Retrieves a summary of the offsets for the topic partition.
| Type | Name | Description | Schema |
|---|---|---|---|
Path |
partitionid |
ID of the partition. |
integer |
Path |
topicname |
Name of the topic containing the partition. |
string |
| HTTP Code | Description | Schema |
|---|---|---|
200 |
A summary of the offsets for the topic partition. |
|
404 |
The specified topic partition was not found. |
application/vnd.kafka.v2+json
Topics
{
"beginning_offset" : 10,
"end_offset" : 50
}
{
"error_code" : 404,
"message" : "The specified topic partition was not found."
}
Revised on 2022-08-17 07:42:00 UTC


Lets Talk
don't you want your memories to last forever? join us we can keep them and remind you of them.
Subscribe to our email and get updates right in your inbox
Excellent Services
What We Do
mexican offers the best offers you could ever dream of.
we are one of the best.
Those smoothing sounds penetrating through you ears.
Peoples Loved
am in love with this organisation..big up to you guys.
thohoyandou
great i love their morality and teamwork.
orange groove (Alpha Discovering)
i adore this guys they really know what they ar doing.
ELIM
Get In Touch
© 2018-2020 Mexican Crew. All Rights Reserved | Design by Malulekeblessing


--- layout: post title: Text Classification using Support Vector Machines in Ruby date: '2011-11-14T13:59:00.001-08:00' author: Rimas Silkaitis tags: - ruby - machine learning modified_time: '2011-12-11T03:18:49.019-08:00' blogger_id: tag:blogger.com,1999:blog-6201986.post-6769608546949438597 blogger_orig_url: http://neovintage.blogspot.com/2011/11/text-classification-using-support.html ---
Support Vector Machines represent a group of supervised learning classifiers that will try to predict the outcome of a feature set. I don't want to bore you with the details but I would recommend that you read Ilya's post about SVMs. It's very informative and it will give you the basics of what you need to understand to get started.
In my case, I've been working on a fairly large scale text classification problem at work when I realized that SVMs would be perfect for the job. Unfortunately, for our needs the current state of Ruby support for SVMs wasn't where we needed it to be.
I am happy to introduce rb-libsvm to the world!
While I can't take credit for the entire gem myself, I did help clean up some pieces of the codebase and gemify the code to make it possible to install from Rubygems.
Basic Usage Example:
As for the future plans for this gem, one of the biggest features I can think of building would be the Marshaling of the Libsvm::Model object. This would be a big performance win since you wouldn't have to re-train the classifier. If you have any other ideas for features, I'd be happy to hear about them.


{% extends "layout.html" %} {% block content %} {% from "_macros.html" import render_form, render_field %}
Don't have an account? Click here to create one.
Already registered? Click here to login.
Forgot your password? Click here to reset it.


As a start, we wanted to create a web platform to network, collaborate, and learn in order to be better prepared for professional UX opportunities.
"I want to be a UX professional but I don't know how to start..."
Many students at UCLA are interested in getting into the UX space, however, they are unsure where to start. A typical UX job requires 3+ years of experience for applicants and most internship opportunities are discipline-based, therefore students from an interdisciplinary program like Digital Humanities with non-design and non-programming experience are hardly exposed to professional user experience project experience. This is despite the fact that UX research and design require a strong sense of humanities, exploring “human-centered” experiences, beyond technical skills design and programming.
To provide a web-based networking space between design and research volunteers and clients, with projects focusing on humans in the human-centered design process.
The volunteers will acquire the practical skills and outcomes by participating in a project, partly or fully as much as they can contribute; while the clients can have creative design solutions based on human research conducted by truly interdisciplinary (or transdisciplinary) team members.
How might we build up a network space to help each other on UX projects?
The design process for the product development (HUE) and web presence design (2020).
The team interviewed peers at UCLA and completed a self-questionnaire to explore how individuals explore their career interests in user experience. Here is a summary of the findings:
| Theme | Details |
|---|---|
| Future Career Goals | UX Designer/Researcher with a focus on humanistic research, aesthetic judgment, and experience |
| Strengths or Weaknesses | Strength: Empathy, Attention to detail Weakness: Confidence experience |
| Common Challenges | So much to learn, imposter syndrome - Research + data + craft/prototype experiences Social issues + humanistic purpose |
| Expected Outcome | Connect + collaborate + like-minded individuals Real-world problems Freelance Experience |
| Competitive Analysis | (Slack, Discord, Behance, Wix, Squarespace, Handshake) Overwhelming + difficult to keep up-to-date Portfolios - What to present? Feedback, Templates Meeting other individuals interested in UX through job-searching sites (Handshake, LinkedIn) |
Based on findings between our own responses and expectations for a UCLA-based network, we outlined the key features of members, projects, and resources as what we wanted to see on our platform:
Four types of personas can be involved in this networking project:
When deciding on the title of our design consulting project, we wanted to touch upon each of our team member’s roots in Digital Humanities. In striving for a humanities-based brand, we came upon HUE, an abbreviation for “Humans in User Experience”. While UE is not a common abbreviation for User eExperience (UX), we felt this was a part of our platform that we could leverage and differentiate ourselves from other UX networks. HUE is also a play on the design terms meaning a color or shade.
Three main features of communication, collaboration, and information sharing are provided through the website.
Here are the key wireframes to test the core content and the layout.
Depending on the user's situation, for non-members, current working members, and clients, users can complete different type of communication, collaborative relationship building, and information sharing tasks.
The detailed user sequence and interation points over the wireframes.
Check the wireflows
We had three rounds of team review with cognitive walkthrough. We found that the mentor information was missing in the wireframe and added the list as 'advisors'. We replaced the inputs with Google forms to make it easier to share and manage the dataset to increase accuracy of data (avoiding bot entries) and ease of database management. The latest revision reflects:
By applying the design system developed with the brand logo (color scheme with warm orange, yellow and dark gray) interface design was drafted and tested. The detail contents were filled with. Accessibility audit was conducted to check the color contrast requirements.
We decided to use the ucla digital humanities webhost (humspace). Bootstrap was used as CSS framework. PHP was used for the member login process.
Experience the interactive Beta Website (2020 Summer)
As increasing number of the members and the advisors, we slightly updated the interface design. It needs still more work for the mobile firnedly version.
Experience the current Website (2022 Winter)It has been like starting up a non-profit organization to deal with many ambiguous and ambitious plans. I have learned a lot about value cycles and business-oriented decision-making on top of quality management of members' voluntary works. HUE started as a small group of people who want to continue research and design momentum for voluntary service to the community, but it has been successful to connect people and resources to grow together. We are still working on the process modeling and how to optimize the client collaboration and new member onboarding. We will keep experimenting with a co-creative process on how to model the proper UX research and design practice and consultancy between student members, experienced members, advisors, and future clients.


Beautiful Autumn with colorful leafs.
Blue footed boobies are birds that live in flocks and have a life expectancy of apporximately 17 years in the wild. .


{% for questionnaire in archived_questionnaires %}
{% with questionnaire.sections.all|first as first_section %}
{{ questionnaire.name }} {{ questionnaire.year }}
{% if questionnaire.is_deletable %}
Delete
{% include 'base/modals/_confirm.html' with object_type='Questionnaire' title='Confirm Delete Questionnaire' action="delete" url=questionnaire.id|get_url_with_ids:"delete_questionnaire_page" object=questionnaire confirm='Yes' extra_message="Only this instance will be deleted. All regional adapations will be archived and can be deleted by regional admins." %}
{% endif %}
{% endwith %}
{% endfor %}
Finalized
{% for questionnaire in finalized_questionnaires %}
{% with questionnaire.sections.all|first as first_section %}
{{ questionnaire.name }} {{ questionnaire.year }}
{% endwith %}
{% if questionnaire.is_finalized %}
{% endif %}
{% if questionnaire.is_published %}
Published
{% endif %}


Features
Find and connect with the right people during and after an event!
Few clicks to set your event up
Your guests will appreciate effective networking
Grow your community by providing superb networking opportunities
Couple of clicks to set up your event.
Ask them to input the code straight to a browser. Simple!
Your guests check-in with Meetlify using LinkedIn profile and can interact with other attendees
Try our app for free for first event
Pay as you go plan that suits your needs


ImpactStyle
public enum ImpactStyle
Impact feedback styles
- light: A impact feedback between small, light user interface elements.
- medium: A impact feedback between moderately sized user interface elements.
- heavy: A impact feedback between large, heavy user interface elements.


 The wall should be straight and N meters long, and its thickness should be constant; however, it should have different heights in different places. The height of the wall is specified by an array H of N positive integers. H[I] is the height of the wall from I to I+1 meters to the right of its left end. In particular, H[0] is the height of the wall's left end and H[N−1] is the height of the wall's right end.
The wall should be built of cuboid stone blocks (that is, all sides of such blocks are rectangular). Your task is to compute the minimum number of blocks needed to build the wall.
Write a function:
def solution(H)
that, given an array H of N positive integers specifying the height of the wall, returns the minimum number of blocks needed to build it.
For example, given array H containing N = 9 integers:
H[0] = 8 H[1] = 8 H[2] = 5 H[3] = 7 H[4] = 9 H[5] = 8 H[6] = 7 H[7] = 4 H[8] = 8the function should return 7. The figure shows one possible arrangement of seven blocks.
Assume that:
- N is an integer within the range [1..100,000];
- each element of array H is an integer within the range [1..1,000,000,000].
Complexity:
- expected worst-case time complexity is O(N);
- expected worst-case space complexity is O(N), beyond input storage (not counting the storage required for input arguments).


Group of professionals from different fields meets twice per month in the heart of Seoul to discuss about AI or implement various AI applications.
Martin is Machine Learning Engineer with a passion for learning new things and solving interesting problems.
Medical Data Engineer, currently working at Linewalks, Inc.
Adel is a researcher in Quantum Information with an interest in Machine Learning.
It is recommended to think about project you want to work on in advance. You can continue working on some of your projects. You can learn new framework that could be useful for you later on. Or maybe you want implement some new NN architecture? Great! There are no limits to projects, however, the project should be related to Artificial Intelligence.
Seoul AI Hackathon allows you to participate either as a single participant or in a team. In case you want to participate in a team, all members (not more than 2 is recommended) have to RSVP to this event through meetup.com. If you want to search for potential team members, the best way is through our slack.
Before joining slack you have to ask for invitation at this page.


This section includes the following topics:
Java Plug-in offers two ways to access the DOM: Through
JSObject
and through the Common DOM API. Each method
is described below, along with security considerations.
JSObject
Java applets may need to perform Java-to-JavaScript
communication to access the Document Object Model (DOM) or to call
JavaScript functions on an HTML page. Browsers allow communication
between Java and JavaScript through the Java wrapper class
netscape.javascript.JSObject
. For more information,
see
Java Packages for LiveConnect.
Because the JavaScript rendering engine is implemented
differently between browsers, Java Plug-in provides different
degrees of support for JSObject
in Internet Explorer
and Navigator. This document specifies how JSObject
support works in different browser environments.
JSObject
WorksJSObjec
t provides an easy way to access the DOM of
an HTML page. But because different browsers implement the DOM
differently, using JSObject
in a Java applet may yield
different behaviors in Java Plug-in. For details about the DOM
implementation in a particular browser, consult the developer guide
for that browser.
In general, applets access JSObject
as follows:
import netscape.javascript.*; import java.applet.*; import java.awt.*; class MyApplet extends Applet { public void init() { JSObject win = JSObject.getWindow(this); JSObject doc = (JSObject) win.getMember("document"); JSObject loc = (JSObject) doc.getMember("location"); String s = (String) loc.getMember("href"); // document.location.href win.call("f", null); // Call f() in HTML page } } |
The starting point is the static
method
public static JSObject getWindow(Applet a)
which returns a JSObject
representing the
Window
that contains the given applet. Since this
method takes only java.applet.Applet
as parameter,
JSObject
can be accessed from an applet, but not from
a bean unless the bean is also an applet.
Once the Window
object is obtained, the applet can
navigate the DOM of the HTML page using the following methods:
public Object call(String methodName, Object
args[])
public Object eval(String s)
public Object getMember(String name)
public Object getSlot(int index)
public void removeMember(String name)
public void setMember(String name, Object
value)
public void setSlot(int index, Object value)
public String toString()
public boolean equals(Object obj)
We recommend using only getWindow()
,
call()
, eval()
, setMember()
and getMember()
in Java Plug-in. The implementations
of getSlot()
, setSlot()
,
removeMember()
and toString()
are
browser-dependent; i.e., the result of execution may vary depending
on the version and platform of the browser in which Java Plug-in is
running.
For more information about using JSObject
, please
read the section called "Java to JavaScript
Communication" on the
LiveConnect page.
To compile Java code to take advantage of JSObject
,
you must have the package netscape.javascript in the
CLASSPATH
. Since 1.4.2 Java Plug-In ships
netscape.javascript in a JAR file called
plugin.jar
. To compile an applet which uses
JSObject
, add plugin.jar
in the
CLASSPATH
before compilation.
Note that although JSObject
is supported in Java
Plug-in, it is not supported in AppletViewer in the Java SE
platform. As a result, applets using JSObject
may not
run in AppletViewer or result in exceptions.
JSObject
Support in Java Plug-inDue to security reasons, JSObject
support is not
enabled in Java Plug-in by default. To enable JSObject
support in Java Plug-in, a new attribute called
MAYSCRIPT
needs to be present in the
EMBED/OBJECT
tag as follows:
APPLET
tag:
<APPLET code="XYZApp.class" codebase="html/" align="baseline" width="200" height="200" MAYSCRIPT> <PARAM NAME="model" VALUE="models/HyaluronicAcid.xyz"> No JDK 1.3 support for APPLET!! </APPLET> |
OBJECT
tag:
<OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93" width="200" height="200" align="baseline" codebase="http://java.sun.com/products/plugin/1.3/jinstall-13-win32.cab#Version=1,3,0,0"> <PARAM NAME="code" VALUE="XYZApp.class"> <PARAM NAME="codebase" VALUE="html/"> <PARAM NAME="type" VALUE="application/x-java-applet;version=1.3"> <PARAM NAME="MAYSCRIPT" VALUE="true"> <PARAM NAME="model" VALUE="models/HyaluronicAcid.xyz"> No JDK 1.3 support for APPLET!! </OBJECT> |
EMBED
tag:
<EMBED type="application/x-java-applet;version=1.3" width="200" height="200" align="baseline" code="XYZApp.class" codebase="html/" model="models/HyaluronicAcid.xyz" MAYSCRIPT=true pluginspage="http://java.sun.com/products/plugin/1.3/plugin-install.html"> <NOEMBED> No JDK 1.3 support for APPLET!! </NOEMBED> </EMBED> |
If MAYSCRIPT
is specified as false, or if
MAYSCRIPT
is absent, JSObject
is
disabled. For more information about the MAYSCRIPT
attribute in the EMBED/OBJECT
tag, see Using OBJECT
, EMBED
and
APPLET
Tags in Java Plug-in.
JavaScript and LiveConnect are technologies from Netscape Communications Corporation. Due to the differences in the Javascript engine implemented by Mozilla and Microsoft, data marshalling between Java and JavaScript via LiveConnect may result in different datatypes for different browsers. The main differences in JavaScript implementations from vendors are in JavaScript datatype support, mapping of datatypes between Java and JavaScript, and DOM element implementation.
NoteThe original JavaScript specification is available at http://devedge-temp.mozilla.org/library/manuals/2000/javascript/1.3/guide/index.html. The original LiveConnect specification is available at http://devedge-temp.mozilla.org/library/manuals/2000/javascript/1.3/guide/lc.html#1037078. |
This section discusses the Common DOM API in Java Plug-in 6. It provides a standard API for accessing the DOM in the browser for browsers from different browser vendors running on various platforms.
NoteFull support is provided with Internet Explorer 6 and supported Mozilla browsers. Support is limited with other browsers. |
This API is built upon the Document Object Model (DOM) Level 2 recommendation. (See http://www.w3.org/DOM/ for various w3c recommendations.) The Document Object Model (DOM) is a set of interfaces defined using Interface Definition Language (IDL) and including Java Language bindings.
The Common DOM API includes the following w3c-defined interface packages:
org.w3c.dom.*
org.w3c.dom.css.*
org.w3c.dom.events.*
org.w3c.dom.html.*
org.w3c.dom.stylesheets.*
org.w3c.dom.views.*
The Common DOM classes allow an application to access the
underlying DOM of the browser through the APIs in the
org.w3c.dom
and org.w3c.dom.html
packages.
Each DOM represents the underlying representation of a single
XML/HTML document within the browser, and each browser may display
more than one XML/HTML document in multiple browser frames/windows.
Thus, when an application requests to access the DOM through the
Common DOM classes, it is important to return the DOM associated
with the application. In order to obtain the proper DOM associated
with the application, a Java object will be passed to
DOMService.getService()
.
DOMService
will return the proper
DOMService
implementations associated with the object,
or an exception will be thrown. Ordinarily the Java object is an
applet or JavaBeans component. However, this specification doesn't
preclude other Java object types from being used, if the
DOMServiceProvider
can handle it.
To perform an action on the DOM, an object that implements
DOMAction
will need to be passed to
DOMService.invokeAndWait()
or
DOMService.invokeLater()
. DOMAction.run()
will then be executed on the DOM access dispatch thread.
Here is a simple example of obtaining the title of the Document object:
DOMService service = null; try { service = DOMService.getService(MyApplet); String title = (String) service.invokeAndWait(new DOMAction() { public Object run(DOMAccessor accessor) { HTMLDocument doc = (HTMLDocument) accessor.getDocument(MyApplet); return doc.getTitle(); } }); } catch (DOMUnsupportedException e1) { } catch (DOMAccessException e2) { } |
Since there may be more than one
DOMServiceProvider
, it is important to allow third
parties to plug their DOMServiceProvider
implementations into the Common DOM classes. To achieve that, a new
Java property, com.sun.browser.dom.DOMServiceProvider
,
is defined.
If this property is defined, it should contain a list of class
names of the DOMServiceProvider
implementations, each
separated by a character "|".
When DOMService.getService()
is called,
DOMServiceProvider
implementations specified by the
com.sun.browser.dom.DOMServiceProvider
will be called
one-by-one to determine if the provide can determine the DOM
association of the object, according to the order that is specified
in the property. In case two DOMServiceProvider
implementations may be able to handle the same object, the provider
that is specified first in the property will be used.
Because the DOM of each browser is implemented differently, DOM
access is not expected to be thread safe. Accessing implementation
of DOM objects in this specification must be restricted on the DOM
access dispatch thread only, so thread safely can be ensured. To
accomplish that, code accessing the DOM objects must be scoped
within the DOMAction.run()
block. To invoke the
action, either DOMService.invokeAndWait()
or
DOMService.invokeLater()
should be used, so that
DOMAction.run()
will be executed in the DOM access
dispatch thread.
Although implementations of DOM objects should not be called
outside the DOMAction.run()
block, the application may
cache these DOM objects around as instance member of a class, or
pass these DOM objects between threads. However, caching the DOM
objects as static members of any object is prohibited, since static
members tend to stay around much longer than the lifecycle of the
underlying DOM object.
The only object in the Common DOM classes that can be called from
any thread is DOMService
. Access to other objects in
the Common DOM classes is restricted within the
DOMAction.run()
block; otherwise, an exception will be
thrown.
The browser DOM provides access to every service in the browser,
so it is important to ensure that security is checked properly
during each call into the DOM. When
DOMService.invokeAndWait()
or
DOMService.invokeLater()
is called, the security
context of the caller will be captured. Later, when the
corresponding DOMAction.run()
is executed on the DOM
access dispatch thread, the caller's security context will be
passed to the browser DOM when implementations of the DOM objects
are called. DOMAccessException
will be thrown if the
original caller doesn't have the required privileges to access the
DOM.
Security policy of DOM access in each browser is different. As a
result, even if a Java application is signed and fully trusted,
accessing the DOM objects in the browser may still result in
DOMAccessException
.
Implementation of the DOM objects represents the real underlying
objects in the browser DOM. As the XML/HTML document is changed
on-the-fly, DOM objects in Java may no longer be valid. Accessing
an invalid DOM object will result in
org.w3c.dom.DOMException
, according to the W3C DOM
Level 2 Specification. Developers who write code to access DOM
objects in DOMAction.run()
should not assume the
validity of the DOM objects at any given moment.
Third parties implementing this specification must provide
implementations of the Common DOM classes in the
com.sun.browser.dom
package. Implementations of the
W3C DOM Level 2 APIs must also conformance to the W3C DOM Level 2
Specification. However, because each browser may implement a
different subset of the W3C DOM APIs, third parties are not
required to provide implementations of all org.w3c.dom
and org.w3c.dom.html
classes.
com.sun.browser.dom
This section defines the API of the
com.sun.browser.dom
package.
public abstract class
DOMService
The DOMService
defines a service API that enables
applications to access a document
object representing
the underlying DOM of the browser window
that embeds
the applications.
|
|
Note that Object obj
in the getService(Object
obj)
method above is the applet or the bean.
public abstract class DOMServiceProvider
Implementation instances of the public abstract class
DOMServiceProvider
enable access to the underlying browser
DOM for a given Java object. Instances of
DOMServiceProvider
should not be obtained by the
application directly.
public abstract class DOMServiceProvider |
Note that Object obj
in the canHandle(Object
obj)
and getDocument(Object obj)
methods above
is the applet or the bean.
public interface DOMAccessor
DOMAccessor
represents the interface that can be
used within DOMAction.run()
to access the entry point
of the browser DOM.
public interface DOMAccessor |
Note that Object obj
in the
getDocument(Object obj)
method above is the applet or
the bean.
public interface DOMAction
DOMAction
encapsulates all the actions of the
applications that will be performed on the browser's DOM.
public interface DOMAction |
public class DOMUnsupportedException
This exception is thrown from
DOMService.getService()
and
DOMServiceProvider.getDocument()
if the association
between the Java object and the DOM cannot be found.
public class DOMUnsupportedException extends
Exception |
public class DOMAccessException
This exception is thrown from
DOMService.accessAndWait()
if any DOM objects throws
any exception when it is accessed within
DOMAction.run()
.
public class DOMAccessException extends
Exception |


Improved Infinispan Docker image available
The Infinispan Docker image has been improved, making it easier to run Infinispan Servers in clustered, domain and standalone modes, with different protocol stacks.
In this blog post we’ll show a few usage scenarios and how to combine it with the jgroups-gossip image to create Infinispan Server clusters in docker based environments.
==== Getting started
By default the container runs in clustered mode, and to start a node simply execute:
Bringing a second container will cause it to form a cluster.The membership can be verified by running a command directly in the newly launched container:
Example output:
==== Using a different JGroups stack
The command above creates a cluster with the default JGroups stack (UDP), but it’s possible to pick another one provided it’s supported by the server. For example, to use TCP:
==== Running on cloud environments
We recently dockerized the JGroups Gossip Router to be used as an alternative discovery mechanism in environments where multicast is not enabled, such as cloud environments.
Employing a gossip router will enable discovery via TCP, where the router acts as a registry: each member will register itself in this registry upon start and also discover other members.
The gossip router container can be launched by:
Take note of the address where the router will bind to, it’s needed by the Infinispan nodes. The address can be easily obtained by:
Finally we can now launch our cluster specifying the tcp-gossip stack with the location of the gossip router:
==== Launching Standalone mode
Passing an extra parameter allows to run a server in standalone (non-clustered) mode:
==== Server Management Console in Domain mode
Domain mode is a special case of clustered mode (and currently a requirement to use the Server Management Console), that involves launching a domain controller process plus one or more host controller processes. The domain controller does not hold data, it is used as a centralized management process that can replicate configuration and provision servers on the host controllers.
Running a domain controller is easily achievable with a parameter:
Once the domain controller is running, it’s possible to start one or more host controllers. In the default configuration, each host controller has two Infinispan server instances:
The command line interface can be used to verify the hosts managed in the domain:
It should output all the host names that are part of the domain, including the master (domain controller):
To get access to the Management console, use credentials admin/admin and go to port 9990 of the domain controller, for example: http://<IP_ADDRESS>:9990/
==== Versions
The image is built on Dockerhub shortly after each Infinispan release (stable and unstable), and the improvements presented in this post are available for Infinispan 9.0.0.Alpha3 and Infinispan 8.2.3.Final. As a reminder, make sure to pick the right version when launching containers:
Getting involved
The image was created to be flexible and easy to use, but if something is not working for you or if you have any suggestions to improve it, please report it at https://github.com/jboss-dockerfiles/infinispan/issues/
Enjoy!


PlugFest Documents
The IG validates the current working assumptions of IG and WG in practical PlugFests. The so-called Current Practices document defines the draft versions to implement and also serves as quick-start guide for developers.
| Document | Iteration | Last Update |
|---|---|---|
| Current Practices | 5 |
Jul 7, 2017 |
| TestThing Thing Description | 2 |
Jul 7, 2017 |
| TestThing Script | 2 |
Jul 7, 2017 |
| Test Protocol | 3 |
Jul 7, 2017 |


Creating a morning ☀ ritual 🛏🚿🥣
Time. I want more of it. But somehow my day seems filled with things on autopilot and all the things I want to do are all piling up - The pet projects I want to finish, the books I want to read. There are no more hours in a day left and I want to do and accomplish so much.  Because when you don’t do anything, nothing can go wrong right?
So I’ve reached a point where I need to do something about it. I’m at an impasse if you will. So I’ve started with a challenge. Today is day one. A physical and mental challenge. For at least 30 days. My end date is wednesday the 5th of December.
My current morning ritual morning chaos goes a little something like this:
- 7.30 Wake up after hitting the snooze button at least 3 times and being very tired because I went to bed at 01.30.
- Hurry while I get dressed and prepare breakfast and coffee for the three of us. The coffee I usually forget to drink.
- 8.20 Leave home and bike my kid to school. Barely be on time so I don’t have time to read to him on school which all the other parents have time for. (And I hate myself for it)
- I’m at work at 8.40 which is way to early, I’m usually entering the office with the first batch of employees. Now I can relax and have a coffee.
As you can see, this is far from optimal, stressful and there are lots of irritation and frustration points along the way. I need to change that.
What are my goals?
I want more time. More time for myself to learn and to develop myself. To learn new things, read more books and to finally finish that big pile of pet projects. More time to be spend with the people I love. Actually I want to better manage myself within the time I have in a day. In the madness of everyday life I come home and I clean a little and start with cooking for my girlfriend and our son. One of us takes him to bed and we run through his evening ritual. After that my engergy is gone. I want to change this cycle. Also; I don’t want to teach my son how I currently handle time and constantly be late for appointments with myself or with others. I want to be a good example of how to manage yourself and be productive. And teach him that almost everything can be learned when you apply yourself and hold yourself to it.
Peer pressure
I’ve decided to become more personal on Twitter and share this challenge, because having the social pressure has possitive effects and might help me achive my goals [pdf]. I want to share this daily.
Challenge
Before starting this challenge with myself, I’ve read up on a lot of resources to better prepare myself. I’ve also found a lot of tips on how to go about wakingup earlier. I even calculated my sleep rhythem with this handy tool and gain a little insight into how sleep rhythems work. Another good source of information is the Sleep Foundation, they have a bunch of interresting articles about sleep.
Schedule
This challenge is about creating a new morning ritual. Including the preparation the night before. And I’ve set myself some ground rules to not fail. Not really sure if this will work, but you have to start somewhere - I might change and optimize this along the way.
My ground rules/preparation:
- Evening preparation:
- Set the table and preparing my sons lunch.
- Fill the water cooker and fill the coffee grinder. Can’t start the day without a fresh brew 😉
- Pickout clothes(both for exercise and work) for the day to come.
- Go to bed earlier - be in before 22.00. I’ve never had any trouble falling asleep, this usually takes me about 5 minutes.
- No devices(laptop/phone/tablet) in the bedroom.
My ideal morning ritual looks like this:
- 5.30 Wake up without hitting the snooze button.
- 5.35 Get dressed for yoga
- 5.45 Practice yoga for 30 minutes
- 6.15 Have cup of tea and a healthy breakfast
- 6.30 Read a book, write some code or learn a new skill
- 7.00 Have an ice cold shower to get me fired up
- 7.10 Normal morning ritual when my son and girlfriend wake up
I’ll post my progress on Twitter daily and with the hastags #WakeUpEarlyChallenge #30days and I’ll keep a record on this site.


This browser out of date. Update browser here
If you are looking for old version of VISCALENDAR check here here


{{ define "header" }} {{/* We can override any block in the baseof file be defining it in the template */}} {{ partial "page-header.html" . }} {{ end }} {{ define "newsletter_signup" }} {{ end }} {{ define "main" }} {{ $section := .Site.GetPage "section" .Section }}
By {{ if reflect.IsSlice . }} {{ delimit . ", " | markdownify }} {{else}} {{ . | markdownify }} {{ end }}
{{ end }} {{/* Hugo uses Go's date formatting is set by example. Here are two formats */}} {{/* Show "reading time" and "word count" but only if one of the following are true: 1) A global config `params` value is set `show_reading_time = true` 2) A section front matter value is set `show_reading_time = true` 3) A page front matter value is set `show_reading_time = true` */}} {{ if (or (eq (.Param "show_reading_time") true) (eq $section.Params.show_reading_time true) )}} - {{ .ReadingTime}} minutes read - {{ .WordCount}} words {{ end }}