The 9.2 release of Komodo IDE is live and includes new features such as Docker and Vagrant integration, collaboration improvements, a package installer, and UI changes.
Learn how to use the service registration and discovery services in ZooKeeper to manage microservices when refactoring from an existing monolithic application.
Liquibase is a great tool, and comparable to Git for databases. While it might not technically be a source control system, it's packed with similar functionality.
Distributed transaction tracing is a useful way to monitor or evaluate your microservices architecture for performance, particularly when measuring end-to-end requests.
In this article, excerpted from the book Docker in Action, I will show you how to open access to shared memory between containers. Linux provides a few tools for sharing memory between processes running on the same computer. This form of inter-process communication (IPC) performs at memory speeds. It is often used when the latency associated with network or pipe based IPC drags software performance below requirements. The best examples of shared memory based IPC usage is in scientific computing and some popular database technologies like PostgreSQL. Docker creates a unique IPC namespace for each container by default. The Linux IPC namespace partitions shared memory primitives like named shared memory blocks and semaphores, as well as message queues. It is okay if you are not sure what these are. Just know that they are tools used by Linux programs to coordinate processing. The IPC namespace prevents processes in one container from accessing the memory on the host or in other containers. Sharing IPC Primitives Between Containers I’ve created an image named allingeek/ch6_ipc that contains both a producer and consumer. They communicate using shared memory. Listing 1 will help you understand the problem with running these in separate containers. Listing 1: Launch a Communicating Pair of Programs # start a producer docker -d -u nobody --name ch6_ipc_producer \ allingeek/ch6_ipc -producer # start the consumer docker -d -u nobody --name ch6_ipc_consumer \ allingeek/ch6_ipc -consumer Listing 1 starts two containers. The first creates a message queue and starts broadcasting messages on it. The second should pull from the message queue and write the messages to the logs. You can see what each is doing by using the following commands to inspect the logs of each: docker logs ch6_ipc_producer docker logs ch6_ipc_consumer If you executed the commands in Listing 1 something should be wrong. The consumer never sees any messages on the queue. Each process used the same key to identify the shared memory resource but they referred to different memory. The reason is that each container has its own shared memory namespace. If you need to run programs that communicate with shared memory in different containers, then you will need to join their IPC namespaces with the --ipc flag. The --ipc flag has a container mode that will create a new container in the same IPC namespace as another target container. Listing 2: Joining Shared Memory Namespaces # remove the original consumer docker rm -v ch6_ipc_consumer # start a new consumer with a joined IPC namespace docker -d --name ch6_ipc_consumer \ --ipc container:ch6_ipc_producer \ allingeek/ch6_ipc -consumer Listing 2 rebuilds the consumer container and reuses the IPC namespace of the ch6_ipc_producer container. This time the consumer should be able to access the same memory location where the server is writing. You can see this working by using the following commands to inspect the logs of each: docker logs ch6_ipc_producer docker logs ch6_ipc_consumer Remember to cleanup your running containers before moving on: # remember: the v option will clean up volumes, # the f option will kill the container if it is running, # and the rm command takes a list of containers docker rm -vf ch6_ipc_producer ch6_ipc_consumer There are obvious security implications to reusing the shared memory namespaces of containers. But this option is available if you need it. Sharing memory between containers is safer alternative to sharing memory with the host.
This technical tip explains how to add a watermark to a document in Microsoft Word document inside Android Applications. Sometimes you need to insert a watermark into a Word document, for instance if you would like to print a draft document or mark it as confidential. In Microsoft Word, you can quickly insert a watermark using the Insert Watermark command. Not many people using this command realize that such “watermark” is just a shape with text inserted into a header or footer and positioned in the centre of the page. While Aspose.Words doesn't have a single insert watermark command like Microsoft Word, it is very easy to insert any shape or image into a header or footer and thus create a watermark of any imaginable type. The code below inserts a watermark into a Word document. [Java Code Sample] package AddWatermark; import java.awt.Color; import java.io.File; import java.net.URI; import com.aspose.words.Document; import com.aspose.words.Shape; import com.aspose.words.ShapeType; import com.aspose.words.RelativeHorizontalPosition; import com.aspose.words.RelativeVerticalPosition; import com.aspose.words.WrapType; import com.aspose.words.VerticalAlignment; import com.aspose.words.HorizontalAlignment; import com.aspose.words.Paragraph; import com.aspose.words.Section; import com.aspose.words.HeaderFooterType; import com.aspose.words.HeaderFooter; public class Program { public static void main(String[] args) throws Exception { // Sample infrastructure. URI exeDir = Program.class.getResource("").toURI(); String dataDir = new File(exeDir.resolve("../../Data")) + File.separator; Document doc = new Document(dataDir + "TestFile.doc"); insertWatermarkText(doc, "CONFIDENTIAL"); doc.save(dataDir + "TestFile Out.doc"); } /** * Inserts a watermark into a document. * * @param doc The input document. * @param watermarkText Text of the watermark. */ private static void insertWatermarkText(Document doc, String watermarkText) throws Exception { // Create a watermark shape. This will be a WordArt shape. // You are free to try other shape types as watermarks. Shape watermark = new Shape(doc, ShapeType.TEXT_PLAIN_TEXT); // Set up the text of the watermark. watermark.getTextPath().setText(watermarkText); watermark.getTextPath().setFontFamily("Arial"); watermark.setWidth(500); watermark.setHeight(100); // Text will be directed from the bottom-left to the top-right corner. watermark.setRotation(-40); // Remove the following two lines if you need a solid black text. watermark.getFill().setColor(Color.GRAY); // Try LightGray to get more Word-style watermark watermark.setStrokeColor(Color.GRAY); // Try LightGray to get more Word-style watermark // Place the watermark in the page center. watermark.setRelativeHorizontalPosition(RelativeHorizontalPosition.PAGE); watermark.setRelativeVerticalPosition(RelativeVerticalPosition.PAGE); watermark.setWrapType(WrapType.NONE); watermark.setVerticalAlignment(VerticalAlignment.CENTER); watermark.setHorizontalAlignment(HorizontalAlignment.CENTER); // Create a new paragraph and append the watermark to this paragraph. Paragraph watermarkPara = new Paragraph(doc); watermarkPara.appendChild(watermark); // Insert the watermark into all headers of each document section. for (Section sect : doc.getSections()) { // There could be up to three different headers in each section, since we want // the watermark to appear on all pages, insert into all headers. insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_PRIMARY); insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_FIRST); insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_EVEN); } } private static void insertWatermarkIntoHeader(Paragraph watermarkPara, Section sect, int headerType) throws Exception { HeaderFooter header = sect.getHeadersFooters().getByHeaderFooterType(headerType); if (header == null) { // There is no header of the specified type in the current section, create it. header = new HeaderFooter(sect.getDocument(), headerType); sect.getHeadersFooters().add(header); } // Insert a clone of the watermark into the header. header.appendChild(watermarkPara.deepClone(true)); } }
This example is an improved version of my previous example Android GridView Example. Instead of using static images to display the grid items, let's make this example more realistic by downloading the data in real-time from the server and rendering the grid items. The following video depicts the output of this example. Without wasting much time, let us jump straight into what it takes to build this kind of GridView. You need to follow the following steps to complete this example. 1. Add GridView in Activity Layout First, create a new android project. For this example, I prefer to use Android Studio. Create a new layout file to your project res/layout folder and name it as activity_grid_view.xml. And add the following code blocks. The above layout is pretty straightforward. We have declared an GridView and a ProgressBar in activity layout. The progress bar will be displayed when the data is downloaded. 2. Declare GridView Item Layout Let us now add another file named grid_item_layout.xml to res/layout folder. This layout will be used by a custom grid adapter for laying out individual grid items. For the sake of simplicity, we are adding an ImageView and a TextView. 3. Adding Internet Permission You might be aware that, the Android application must declare all the permissions that are required for the application. As we need to download the data from the server, we need to add INTERNET permission. Add the following line to AndroidManifest.xml the file. Notice that we have also declared all the activities used in the application. 4. Adding Picasso Image Downloading Library Android open-source developer community brings some interesting libraries that can be integrated easily into Android applications. They serve a great deal of purpose and save a lot of time. Here in this example, I am talking about Picasso the image-loading library. We will add the Picasso library for downloading and caching images. Visit here to learn more about how to use the Picasso library on Android. You can add the Picasso library by adding the following dependency to the build.gradle file. dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:21.0.3' compile 'com.squareup.picasso:picasso:2.5.2' } 5. Create a GridView Custom Adapter A grid view is an adapter view. It requires an adapter to render the collection of data items. Add a new class named GridViewAdapter.java to your project and add the following code snippets. package com.javatechig.gridviewexample; import java.util.ArrayList; import android.app.Activity; import android.content.Context; import android.text.Html; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.TextView; import com.squareup.picasso.Picasso; public class GridViewAdapter extends ArrayAdapter { private Context mContext; private int layoutResourceId; private ArrayList mGridData = new ArrayList(); public GridViewAdapter(Context mContext, int layoutResourceId, ArrayList mGridData) { super(mContext, layoutResourceId, mGridData); this.layoutResourceId = layoutResourceId; this.mContext = mContext; this.mGridData = mGridData; } /** * Updates grid data and refresh grid items. * @param mGridData */ public void setGridData(ArrayList mGridData) { this.mGridData = mGridData; notifyDataSetChanged(); } @Override public View getView(int position, View convertView, ViewGroup parent) { View row = convertView; ViewHolder holder; if (row == null) { LayoutInflater inflater = ((Activity) mContext).getLayoutInflater(); row = inflater.inflate(layoutResourceId, parent, false); holder = new ViewHolder(); holder.titleTextView = (TextView) row.findViewById(R.id.grid_item_title); holder.imageView = (ImageView) row.findViewById(R.id.grid_item_image); row.setTag(holder); } else { holder = (ViewHolder) row.getTag(); } GridItem item = mGridData.get(position); holder.titleTextView.setText(Html.fromHtml(item.getTitle())); Picasso.with(mContext).load(item.getImage()).into(holder.imageView); return row; } static class ViewHolder { TextView titleTextView; ImageView imageView; } } Notice the following in the above code snippets, The setGridData() method updates the data display on GridView. The Picasso.with().load() the method is used to download the image from the URL and display it on the image view. The GridViewAdapter class constructor requires the id of the grid item layout and the list of data to operate on. You might be surprised, where the GridItem class came from. It's not magic, we need to add GridItem.java class to our project. The GridItem class looks as follows. 6. Download Data and Hook it to the Activity Now we will be heading towards hooking the adapter to GridView and making it functional. Create a new Java class and name it as GridViewActivity.java and perform the following steps. Override the onCreate() method and set the layout by calling setContentView() method Initialize the GridView and ProgressBar components by using their declared layout id. Initialize the CustomGridView adapter bypassing the grid row layout id and the list of GridItem objects. Use AsyncTask to download data from the server, once the download is successful read the stream JSON response. Parse the JSON string into the list of GridItem objects. Once downloading and parsing is completed, in onPostExecute() callback update the UI elements. The following code does all the above steps as described. Add the following code to GridViewActivity class. import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.GridView; import android.widget.ProgressBar; import android.widget.Toast; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; public class GridViewActivity extends ActionBarActivity { private static final String TAG = GridViewActivity.class.getSimpleName(); private GridView mGridView; private ProgressBar mProgressBar; private GridViewAdapter mGridAdapter; private ArrayList mGridData; private String FEED_URL = "http://javatechig.com/?json=get_recent_posts&count=45"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_gridview); mGridView = (GridView) findViewById(R.id.gridView); mProgressBar = (ProgressBar) findViewById(R.id.progressBar); //Initialize with empty data mGridData = new ArrayList<>(); mGridAdapter = new GridViewAdapter(this, R.layout.grid_item_layout, mGridData); mGridView.setAdapter(mGridAdapter); //Start download new AsyncHttpTask().execute(FEED_URL); mProgressBar.setVisibility(View.VISIBLE); } //Downloading data asynchronously public class AsyncHttpTask extends AsyncTask { @Override protected Integer doInBackground(String... params) { Integer result = 0; try { // Create Apache HttpClient HttpClient httpclient = new DefaultHttpClient(); HttpResponse httpResponse = httpclient.execute(new HttpGet(params[0])); int statusCode = httpResponse.getStatusLine().getStatusCode(); // 200 represents HTTP OK if (statusCode == 200) { String response = streamToString(httpResponse.getEntity().getContent()); parseResult(response); result = 1; // Successful } else { result = 0; //"Failed } } catch (Exception e) { Log.d(TAG, e.getLocalizedMessage()); } return result; } @Override protected void onPostExecute(Integer result) { // Download complete. Let us update UI if (result == 1) { mGridAdapter.setGridData(mGridData); } else { Toast.makeText(GridViewActivity.this, "Failed to fetch data!", Toast.LENGTH_SHORT).show(); } mProgressBar.setVisibility(View.GONE); } } String streamToString(InputStream stream) throws IOException { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stream)); String line; String result = ""; while ((line = bufferedReader.readLine()) != null) { result += line; } // Close stream if (null != stream) { stream.close(); } return result; } /** * Parsing the feed results and get the list * @param result */ private void parseResult(String result) { try { JSONObject response = new JSONObject(result); JSONArray posts = response.optJSONArray("posts"); GridItem item; for (int i = 0; i < posts.length(); i++) { JSONObject post = posts.optJSONObject(i); String title = post.optString("title"); item = new GridItem(); item.setTitle(title); JSONArray attachments = post.getJSONArray("attachments"); if (null != attachments && attachments.length() > 0) { JSONObject attachment = attachments.getJSONObject(0); if (attachment != null) item.setImage(attachment.getString("url")); } mGridData.add(item); } } catch (JSONException e) { e.printStackTrace(); } } } At this point, you will be able to run the app and notice that the app will download the data from the server and display it on GridView. 7. Handle GridView Click Event Right now GridView is not responding to user clicks. Let us make it more functional by adding the following code. mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { public void onItemClick(AdapterView parent, View v, int position, long id) { //Get item at position GridItem item = (GridItem) parent.getItemAtPosition(position); //Pass the image title and url to DetailsActivity Intent intent = new Intent(GridViewActivity.this, DetailsActivity.class); intent.putExtra("title", item.getTitle()); intent.putExtra("image", item.getImage()); //Start details activity startActivity(intent); } }); When a user clicks on a grid item, we will start another activity that displays the full-screen image. You can start one activity from another by calling startActivity() method. We need to pass the details of the item such as the title, and image URL for displaying it on DetailsActivity. 8. Create Details Activity Layout Add a new layout file to res/layout directory, and name it as activity_details_view.xml and add the following code snippets. 9. Completing the Details Activity The DetailsActivity retrieves the details passed from GridViewActivity and renders the details on the screen. Create a new class named DetailsActivity and add the following code snippets. package com.javatechig.gridviewexample; import android.os.Bundle; import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBarActivity; import android.text.Html; import android.widget.ImageView; import android.widget.TextView; import com.squareup.picasso.Picasso; public class DetailsActivity extends ActionBarActivity { private TextView titleTextView; private ImageView imageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_details_view); ActionBar actionBar = getSupportActionBar(); actionBar.hide(); String title = getIntent().getStringExtra("title"); String image = getIntent().getStringExtra("image"); titleTextView = (TextView) findViewById(R.id.title); imageView = (ImageView) findViewById(R.id.grid_item_image); titleTextView.setText(Html.fromHtml(title)); Picasso.with(this).load(image).into(imageView); } } 10. Download the Complete Example Download from GitHub. 11. Custom Activity Transition in GridView Continue reading in our next tutorial.